Skip to content

Commit

Permalink
feat: added overview and details table for scenario-3
Browse files Browse the repository at this point in the history
  • Loading branch information
SagarRajput-7 committed Oct 28, 2024
1 parent 8913ef9 commit e775ef6
Show file tree
Hide file tree
Showing 11 changed files with 279 additions and 31 deletions.
28 changes: 19 additions & 9 deletions frontend/src/pages/MessagingQueues/MQDetailPage/MQDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { ListMinus } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';

import { MessagingQueuesViewType } from '../MessagingQueuesUtils';
import {
MessagingQueuesViewType,
ProducerLatencyOptions,
} from '../MessagingQueuesUtils';
import { SelectLabelWithComingSoon } from '../MQCommon/MQCommon';
import MessagingQueueOverview from '../MQDetails/MessagingQueueOverview';
import MessagingQueuesDetails from '../MQDetails/MQDetails';
Expand All @@ -21,6 +24,11 @@ function MQDetailPage(): JSX.Element {
MessagingQueuesViewType.consumerLag.value,
);

const [
producerLatencyOption,
setproducerLatencyOption,
] = useState<ProducerLatencyOptions>(ProducerLatencyOptions.Producers);

useEffect(() => {
logEvent('Messaging Queues: Detail page visited', {});
}, []);
Expand Down Expand Up @@ -54,13 +62,8 @@ function MQDetailPage(): JSX.Element {
value: MessagingQueuesViewType.partitionLatency.value,
},
{
label: (
<SelectLabelWithComingSoon
label={MessagingQueuesViewType.producerLatency.label}
/>
),
label: MessagingQueuesViewType.producerLatency.label,
value: MessagingQueuesViewType.producerLatency.value,
disabled: true,
},
{
label: (
Expand All @@ -81,11 +84,18 @@ function MQDetailPage(): JSX.Element {
{selectedView === MessagingQueuesViewType.consumerLag.value ? (
<MessagingQueuesGraph />
) : (
<MessagingQueueOverview selectedView={selectedView} />
<MessagingQueueOverview
selectedView={selectedView}
option={producerLatencyOption}
setOption={setproducerLatencyOption}
/>
)}
</div>
<div className="messaging-queue-details">
<MessagingQueuesDetails selectedView={selectedView} />
<MessagingQueuesDetails
selectedView={selectedView}
producerLatencyOption={producerLatencyOption}
/>
</div>
</div>
);
Expand Down
39 changes: 39 additions & 0 deletions frontend/src/pages/MessagingQueues/MQDetails/MQDetails.style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,42 @@
flex-direction: column;
gap: 24px;
}

.mq-overview-container {
display: flex;
padding: 24px;
flex-direction: column;
align-items: start;
gap: 16px;

border-radius: 6px;
border: 1px solid var(--bg-slate-500);
background: var(--bg-ink-500);

.mq-overview-title {
color: var(--bg-vanilla-200);

font-family: Inter;
font-size: 18px;
font-style: normal;
font-weight: 500;
line-height: 28px;
}

.mq-details-options {
letter-spacing: -0.06px;
cursor: pointer;

.ant-radio-button-wrapper {
border-color: var(--bg-slate-400);
color: var(--bg-vanilla-400);
}
.ant-radio-button-wrapper-checked {
background: var(--bg-slate-400);
color: var(--bg-vanilla-100);
}
.ant-radio-button-wrapper::before {
width: 0px;
}
}
}
88 changes: 71 additions & 17 deletions frontend/src/pages/MessagingQueues/MQDetails/MQDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Radio } from 'antd';
import { QueryParams } from 'constants/query';
import useUrlQuery from 'hooks/useUrlQuery';
import { isEmpty } from 'lodash-es';
import { Dispatch, SetStateAction, useMemo, useState } from 'react';
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { ErrorResponse, SuccessResponse } from 'types/api';
Expand All @@ -14,6 +14,7 @@ import {
ConsumerLagDetailTitle,
MessagingQueueServiceDetailType,
MessagingQueuesViewType,
ProducerLatencyOptions,
SelectedTimelineQuery,
} from '../MessagingQueuesUtils';
import { ComingSoon } from '../MQCommon/MQCommon';
Expand All @@ -23,9 +24,14 @@ import {
MessagingQueuesPayloadProps,
} from './MQTables/getConsumerLagDetails';
import { getPartitionLatencyDetails } from './MQTables/getPartitionLatencyDetails';
import { getTopicThroughputDetails } from './MQTables/getTopicThroughputDetails';
import MessagingQueuesTable from './MQTables/MQTables';

const MQServiceDetailTypePerView = {
const MQServiceDetailTypePerView = (
producerLatencyOption: ProducerLatencyOptions,
): {
[x: string]: MessagingQueueServiceDetailType[];
} => ({
[MessagingQueuesViewType.consumerLag.value]: [
MessagingQueueServiceDetailType.ConsumerDetails,
MessagingQueueServiceDetailType.ProducerDetails,
Expand All @@ -37,33 +43,41 @@ const MQServiceDetailTypePerView = {
MessagingQueueServiceDetailType.ProducerDetails,
],
[MessagingQueuesViewType.producerLatency.value]: [
MessagingQueueServiceDetailType.ConsumerDetails,
MessagingQueueServiceDetailType.ProducerDetails,
producerLatencyOption === ProducerLatencyOptions.Consumers
? MessagingQueueServiceDetailType.ConsumerDetails
: MessagingQueueServiceDetailType.ProducerDetails,
],
};
});

interface MessagingQueuesOptionsProps {
currentTab: MessagingQueueServiceDetailType;
setCurrentTab: Dispatch<SetStateAction<MessagingQueueServiceDetailType>>;
selectedView: string;
producerLatencyOption: ProducerLatencyOptions;
}

function MessagingQueuesOptions({
currentTab,
setCurrentTab,
selectedView,
producerLatencyOption,
}: MessagingQueuesOptionsProps): JSX.Element {
const [option, setOption] = useState<MessagingQueueServiceDetailType>(
currentTab,
);

useEffect(() => {
setOption(currentTab);
}, [currentTab]);

const handleChange = (value: MessagingQueueServiceDetailType): void => {
setOption(value);
setCurrentTab(value);
};

const renderRadioButtons = (): JSX.Element[] => {
const detailTypes = MQServiceDetailTypePerView[selectedView] || [];
const detailTypes =
MQServiceDetailTypePerView(producerLatencyOption)[selectedView] || [];
return detailTypes.map((detailType) => (
<Radio.Button
key={detailType}
Expand Down Expand Up @@ -162,13 +176,18 @@ export const getMetaDataAndAPIPerView = (
start: minTime,
end: maxTime,
variables: {
partition: '',
topic: '',
consumer_group: '',
// partition: configDetails?.partition,
// topic: configDetails?.topic,
// service_name: configDetails?.service_name,

// todo-sagar: look at above props
partition: selectedTimelineQuery?.partition,
topic: selectedTimelineQuery?.topic,
service_name: 'consumer-svc-1', // todo-sagar remove hardcode
},
detailType,
},
tableApi: getConsumerLagDetails,
tableApi: getTopicThroughputDetails,
},
};
};
Expand All @@ -180,6 +199,7 @@ const checkValidityOfDetailConfigs = (
// configDetails?: {
// [key: string]: string;
// },
// eslint-disable-next-line sonarjs/cognitive-complexity
): boolean => {
if (selectedView === MessagingQueuesViewType.consumerLag.value) {
return !(
Expand Down Expand Up @@ -208,18 +228,47 @@ const checkValidityOfDetailConfigs = (
);
}

if (selectedView === MessagingQueuesViewType.producerLatency.value) {
// todo-sagar - change to configdetails and add service_name
if (isEmpty(selectedTimelineQuery)) {
return false;
}

if (currentTab === MessagingQueueServiceDetailType.ProducerDetails) {
return Boolean(
selectedTimelineQuery?.topic && selectedTimelineQuery?.partition,
);
}
return Boolean(selectedTimelineQuery?.topic);
}

return false;
};

function MessagingQueuesDetails({
selectedView,
producerLatencyOption,
}: {
selectedView: string;
producerLatencyOption: ProducerLatencyOptions;
}): JSX.Element {
const [currentTab, setCurrentTab] = useState<MessagingQueueServiceDetailType>(
MessagingQueueServiceDetailType.ConsumerDetails,
);

useEffect(() => {
if (
producerLatencyOption &&
selectedView === MessagingQueuesViewType.producerLatency.value
) {
setCurrentTab(
producerLatencyOption === ProducerLatencyOptions.Consumers
? MessagingQueueServiceDetailType.ConsumerDetails
: MessagingQueueServiceDetailType.ProducerDetails,
);
}
}, [selectedView, producerLatencyOption]);

const urlQuery = useUrlQuery();
const timelineQuery = decodeURIComponent(
urlQuery.get(QueryParams.selectedTimelineQuery) || '',
Expand All @@ -244,20 +293,25 @@ function MessagingQueuesDetails({
(state) => state.globalTime,
);

const serviceConfigDetails = getMetaDataAndAPIPerView({
detailType: currentTab,
minTime,
maxTime,
selectedTimelineQuery: timelineQueryData,
configDetails: configDetailQueryData,
});
const serviceConfigDetails = useMemo(
() =>
getMetaDataAndAPIPerView({
detailType: currentTab,
minTime,
maxTime,
selectedTimelineQuery: timelineQueryData,
configDetails: configDetailQueryData,
}),
[configDetailQueryData, currentTab, maxTime, minTime, timelineQueryData],
);

return (
<div className="mq-details">
<MessagingQueuesOptions
currentTab={currentTab}
setCurrentTab={setCurrentTab}
selectedView={selectedView}
producerLatencyOption={producerLatencyOption}
/>
<MessagingQueuesTable
currentTab={currentTab}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.mq-tables-container {
width: 100%;
height: 100%;

.mq-table-title {
display: flex;
align-items: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ function MessagingQueuesTable({
[timelineQuery],
);

console.log(tableApi, tableApiPayload, validConfigPresent);

const paginationConfig = useMemo(
() =>
tableData?.length > 20 && {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ export interface MessagingQueueServicePayload {
partition?: string;
topic?: string;
consumer_group?: string;
service_name?: string;
};
detailType?: MessagingQueueServiceDetailType;
detailType?: MessagingQueueServiceDetailType | 'producer' | 'consumer';
}

export interface MessagingQueuesPayloadProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { ErrorResponse, SuccessResponse } from 'types/api';

import {
MessagingQueueServicePayload,
MessagingQueuesPayloadProps,
} from './getConsumerLagDetails';

export const getTopicThroughputDetails = async (
props: MessagingQueueServicePayload,
): Promise<
SuccessResponse<MessagingQueuesPayloadProps['payload']> | ErrorResponse
> => {
const { detailType, ...rest } = props;
const endpoint = `/messaging-queues/kafka/topic-throughput/${detailType}`;
try {
const response = await axios.post(endpoint, {
...rest,
});

return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data.data,
};
} catch (error) {
return ErrorResponseHandler((error as AxiosError) || SOMETHING_WENT_WRONG);
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { ErrorResponse, SuccessResponse } from 'types/api';

import {
MessagingQueueServicePayload,
MessagingQueuesPayloadProps,
} from './getConsumerLagDetails';

export const getTopicThroughputOverview = async (
props: Omit<MessagingQueueServicePayload, 'variables'>,
): Promise<
SuccessResponse<MessagingQueuesPayloadProps['payload']> | ErrorResponse
> => {
const { detailType, start, end } = props;
console.log(detailType);
try {
const response = await axios.post(
`messaging-queues/kafka/topic-throughput/${detailType}`,
{
start,
end,
},
);

return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data.data,
};
} catch (error) {
return ErrorResponseHandler((error as AxiosError) || SOMETHING_WENT_WRONG);
}
};
Loading

0 comments on commit e775ef6

Please sign in to comment.