Skip to content

Commit

Permalink
feat: added histogram charts and right panel
Browse files Browse the repository at this point in the history
  • Loading branch information
SagarRajput-7 committed Jan 23, 2025
1 parent 43b9b32 commit 5516cd5
Show file tree
Hide file tree
Showing 12 changed files with 904 additions and 98 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,74 @@
.celery-task-detail-drawer {
.ant-drawer-wrapper-body {
background: var(--bg-ink-500);
border: 1px solid var(--bg-ink-300);
}

.ant-drawer-body {
padding: 0px;

.ant-card {
border: none;
.ant-card-body {
height: 100%;
background: var(--bg-ink-500);

.ant-table {
background: var(--bg-ink-500);
}
}
}
}

.ant-drawer-header {
border-bottom: 1px solid var(--bg-ink-300);
.ant-drawer-header-title {
.ant-drawer-close {
position: absolute;
right: 0;
}

button > svg {
color: var(--bg-vanilla-100);
}

.ant-drawer-title {
display: flex;
flex-direction: column;
align-items: flex-start;

.title {
color: var(--bg-vanilla-100);
font-family: Inter;
font-size: 18px;
font-style: normal;
font-weight: 600;
line-height: 18px;
letter-spacing: -0.45px;
}

.subtitle {
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 20px;
}
}
}
}

.ant-drawer-footer {
border-top: 1px solid var(--bg-ink-300);

.footer-text {
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
}
}
}
126 changes: 106 additions & 20 deletions frontend/src/components/CeleryTask/CeleryTaskDetail/CeleryTaskDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,143 @@ import './CeleryTaskDetail.style.scss';

import { Color, Spacing } from '@signozhq/design-tokens';
import { Divider, Drawer, Typography } from 'antd';
import { QueryParams } from 'constants/query';
import dayjs from 'dayjs';
import { useIsDarkMode } from 'hooks/useDarkMode';
import useUrlQuery from 'hooks/useUrlQuery';
import { X } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom';
import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers';
import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { GlobalReducer } from 'types/reducer/globalTime';

import CeleryTaskGraph from '../CeleryTaskGraph/CeleryTaskGraph';
import { celerySlowestTasksTableWidgetData } from '../CeleryTaskGraph/CeleryTaskGraphUtils';

export type CeleryTaskData = {
taskName: string;
taskId: string;
taskStatus: string;
taskCreatedAt: string;
taskCompletedAt: string;
entity: string;
value: string | number;
timeRange: [number, number];
};

export type CeleryTaskDetailProps = {
task: CeleryTaskData | null;
onClose: () => void;
mainTitle: string;
widgetData: Widgets;
taskData: CeleryTaskData;
drawerOpen: boolean;
};

export default function CeleryTaskDetail({
task,
mainTitle,
widgetData,
taskData,
onClose,
drawerOpen,
}: CeleryTaskDetailProps): JSX.Element {
const isDarkMode = useIsDarkMode();

const shouldShowDrawer =
!!taskData.entity && !!taskData.timeRange[0] && drawerOpen;

const formatTimestamp = (timestamp: number): string =>
dayjs(timestamp * 1000).format('MM-DD-YYYY hh:mm A');

const [totalTask, setTotalTask] = useState(0);

const getGraphData = (graphData?: MetricRangePayloadProps['data']): void => {
console.log(graphData);
setTotalTask((graphData?.result?.[0] as any)?.table?.rows.length);
};

// set time range
const { minTime, maxTime, selectedTime } = useSelector<
AppState,
GlobalReducer
>((state) => state.globalTime);

const startTime = taskData.timeRange[0];
const endTime = taskData.timeRange[1];

const urlQuery = useUrlQuery();
const location = useLocation();
const history = useHistory();
const dispatch = useDispatch();

useEffect(() => {
urlQuery.delete(QueryParams.relativeTime);
urlQuery.set(QueryParams.startTime, startTime.toString());
urlQuery.set(QueryParams.endTime, endTime.toString());

const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
history.replace(generatedUrl);

if (startTime !== endTime) {
dispatch(UpdateTimeInterval('custom', [startTime, endTime]));
}

return (): void => {
urlQuery.delete(QueryParams.relativeTime);
urlQuery.delete(QueryParams.startTime);
urlQuery.delete(QueryParams.endTime);

if (selectedTime !== 'custom') {
dispatch(UpdateTimeInterval(selectedTime));
urlQuery.set(QueryParams.relativeTime, selectedTime);
} else {
dispatch(UpdateTimeInterval('custom', [minTime, maxTime]));
urlQuery.set(QueryParams.startTime, minTime.toString());
urlQuery.set(QueryParams.endTime, maxTime.toString());
}

const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
history.replace(generatedUrl);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<Drawer
width="50%"
width="45%"
title={
<>
<Divider type="vertical" />
<Typography.Text className="title">{task?.taskName}</Typography.Text>
</>
<div>
<Typography.Text className="title">{mainTitle}</Typography.Text>
<div>
<Typography.Text className="subtitle">
{`${formatTimestamp(taskData.timeRange[0])} ${
taskData.timeRange[1]
? `- ${formatTimestamp(taskData.timeRange[1])}`
: ''
}`}
</Typography.Text>
<Divider type="vertical" />
<Typography.Text className="subtitle">task-details</Typography.Text>
</div>
</div>
}
placement="right"
onClose={onClose}
open={!!task}
open={shouldShowDrawer}
style={{
overscrollBehavior: 'contain',
background: isDarkMode ? Color.BG_INK_400 : Color.BG_VANILLA_100,
}}
className="celery-task-detail-drawer"
destroyOnClose
closeIcon={<X size={16} style={{ marginTop: Spacing.MARGIN_1 }} />}
footer={
<Typography.Text className="footer-text">{`Total Task: ${totalTask}`}</Typography.Text>
}
>
{task && (
<CeleryTaskGraph
widgetData={celerySlowestTasksTableWidgetData}
onClick={(): void => {}}
/>
)}
<CeleryTaskGraph
widgetData={widgetData}
onClick={(): void => {}}
getGraphData={getGraphData}
queryEnabled
/>
</Drawer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

.celery-task-graph-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-columns: 60% 40%;
align-items: flex-start;
gap: 10px;
width: 100%;
Expand All @@ -23,8 +23,29 @@
height: calc(100% - 24px);

.widget-graph-container {
&.bar {
height: calc(100% - 116px);
&.histogram {
height: calc(100% - 85px);
}
}
}
}

.celery-task-graph-histogram {
height: 380px !important;
width: 100%;
box-sizing: border-box;

.celery-task-graph-grid-content {
padding: 6px;
height: 100%;
}

.ant-card-body {
height: calc(100% - 18px);

.widget-graph-container {
&.histogram {
height: calc(100% - 85px);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,20 @@ import { useDispatch } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom';
import { UpdateTimeInterval } from 'store/actions';
import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';

import { CeleryTaskData } from '../CeleryTaskDetail/CeleryTaskDetail';
import { CeleryTaskGraphStates } from './CeleryTaskGraphStates';

function CeleryTaskGraph({
widgetData,
onClick,
getGraphData,
queryEnabled,
}: {
widgetData: Widgets;
onClick: (task: CeleryTaskData) => void;
getGraphData?: (graphData?: MetricRangePayloadProps['data']) => void;
queryEnabled: boolean;
}): JSX.Element {
const history = useHistory();
const { pathname } = useLocation();
Expand Down Expand Up @@ -50,7 +54,6 @@ function CeleryTaskGraph({
$panelType={PANEL_TYPES.TIME_SERIES}
className="celery-task-graph"
>
{widgetData.title === 'All' && <CeleryTaskGraphStates />}
<GridCard
widget={widgetData}
headerMenuList={[...ViewMenuAction]}
Expand All @@ -59,9 +62,15 @@ function CeleryTaskGraph({
console.log('clicked', arg); // todo-sagar: add logic to handle click
onClick(arg as any);
}}
getGraphData={getGraphData}
isQueryEnabled={queryEnabled}
/>
</Card>
);
}

CeleryTaskGraph.defaultProps = {
getGraphData: undefined,
};

export default CeleryTaskGraph;
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,21 @@ import { CeleryTaskData } from '../CeleryTaskDetail/CeleryTaskDetail';
import CeleryTaskGraph from './CeleryTaskGraph';
import {
celeryActiveTasksWidgetData,
celeryAllStateWidgetData,
celeryErrorByWorkerWidgetData,
celeryLatencyByWorkerWidgetData,
celeryTaskLatencyWidgetData,
celeryTasksByWorkerWidgetData,
celeryWorkerOnlineWidgetData,
} from './CeleryTaskGraphUtils';
import CeleryTaskHistogram from './CeleryTaskHistogram';

export default function CeleryTaskGraphGrid({
onClick,
queryEnabled,
}: {
onClick: (task: CeleryTaskData) => void;
queryEnabled: boolean;
}): JSX.Element {
const widgetData = [
celeryActiveTasksWidgetData,
celeryWorkerOnlineWidgetData,
celeryAllStateWidgetData,
celeryTaskLatencyWidgetData,
];

const bottomWidgetData = [
celeryTasksByWorkerWidgetData,
celeryErrorByWorkerWidgetData,
Expand All @@ -33,13 +28,36 @@ export default function CeleryTaskGraphGrid({
return (
<div className="celery-task-graph-grid-container">
<div className="celery-task-graph-grid">
{widgetData.map((widget) => (
<CeleryTaskGraph key={widget.id} widgetData={widget} onClick={onClick} />
))}
<CeleryTaskHistogram onClick={onClick} queryEnabled={queryEnabled} />
<CeleryTaskGraph
key={celeryWorkerOnlineWidgetData.id}
widgetData={celeryWorkerOnlineWidgetData}
onClick={onClick}
queryEnabled={queryEnabled}
/>
</div>
<div className="celery-task-graph-grid">
<CeleryTaskGraph
key={celeryTaskLatencyWidgetData.id}
widgetData={celeryTaskLatencyWidgetData}
onClick={onClick}
queryEnabled={queryEnabled}
/>
<CeleryTaskGraph
key={celeryActiveTasksWidgetData.id}
widgetData={celeryActiveTasksWidgetData}
onClick={onClick}
queryEnabled={queryEnabled}
/>
</div>
<div className="celery-task-graph-grid-bottom">
{bottomWidgetData.map((widget) => (
<CeleryTaskGraph key={widget.id} widgetData={widget} onClick={onClick} />
{bottomWidgetData.map((widgetData) => (
<CeleryTaskGraph
key={widgetData.id}
widgetData={widgetData}
onClick={onClick}
queryEnabled={queryEnabled}
/>
))}
</div>
</div>
Expand Down
Loading

0 comments on commit 5516cd5

Please sign in to comment.