feat: added worker count and other misc changes (#6951)

* feat: added worker count - via autocomplete API

* feat: added worker count and code fix

* feat: added lightMode styles for all celery feat

* feat: changed routes to have redirects, subroute etc

* feat: feedback changes

* feat: removed console.log
This commit is contained in:
SagarRajput-7 2025-01-29 17:32:01 +05:30 committed by GitHub
parent 36f91d1993
commit fb3b70b729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 470 additions and 268 deletions

View File

@ -28,7 +28,6 @@ import {
LogsExplorer,
LogsIndexToFields,
LogsSaveViews,
MQDetailPage,
MySettings,
NewDashboardPage,
OldLogsExplorer,
@ -395,10 +394,10 @@ const routes: AppRoutes[] = [
key: 'INTEGRATIONS',
},
{
path: ROUTES.MESSAGING_QUEUES,
path: ROUTES.MESSAGING_QUEUES_KAFKA,
exact: true,
component: MessagingQueues,
key: 'MESSAGING_QUEUES',
key: 'MESSAGING_QUEUES_KAFKA',
isPrivate: true,
},
{
@ -416,10 +415,10 @@ const routes: AppRoutes[] = [
isPrivate: true,
},
{
path: ROUTES.MESSAGING_QUEUES_DETAIL,
path: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
exact: true,
component: MQDetailPage,
key: 'MESSAGING_QUEUES_DETAIL',
component: MessagingQueues,
key: 'MESSAGING_QUEUES_KAFKA_DETAIL',
isPrivate: true,
},
{
@ -461,6 +460,7 @@ export const oldRoutes = [
'/logs-save-views',
'/traces-save-views',
'/settings/access-tokens',
'/messaging-queues',
];
export const oldNewRoutesMapping: Record<string, string> = {
@ -470,6 +470,7 @@ export const oldNewRoutesMapping: Record<string, string> = {
'/logs-save-views': '/logs/saved-views',
'/traces-save-views': '/traces/saved-views',
'/settings/access-tokens': '/settings/api-keys',
'/messaging-queues': '/messaging-queues/overview',
};
export const ROUTES_NOT_TO_BE_OVERRIDEN: string[] = [

View File

@ -12,7 +12,14 @@
cursor: pointer;
}
.celery-overview-table {
.celery-overview-table-container {
width: 100%;
> .ant-input-search {
margin-bottom: 8px;
}
.celery-overview-table {
.ant-table {
.ant-table-thead > tr > th {
padding: 12px;
@ -103,4 +110,42 @@
}
}
}
}
}
.lightMode {
.celery-overview-table-container {
.celery-overview-table {
.ant-table {
.ant-table-thead > tr > th {
background: var(--bg-vanilla-100);
color: var(--text-ink-300);
}
.ant-table-cell {
background: var(--bg-vanilla-100);
color: var(--bg-ink-500);
}
.ant-table-tbody > tr:hover > td {
background: rgba(0, 0, 0, 0.04);
}
}
.ant-pagination {
background: var(--bg-vanilla-100);
.ant-pagination-item {
&-active {
background: var(--bg-robin-500);
border-color: var(--bg-robin-500);
a {
color: var(--bg-vanilla-100) !important;
}
}
}
}
}
}
}

View File

@ -400,6 +400,15 @@ export default function CeleryOverviewTable({
confirm();
};
// Add defaultSorting state
const [sortedInfo, setSortedInfo] = useState<{
columnKey: string;
order: 'ascend' | 'descend';
}>({
columnKey: 'error_percentage',
order: 'descend',
});
const columns = useMemo(
() =>
getDraggedColumns<RowData>(
@ -411,10 +420,15 @@ export default function CeleryOverviewTable({
handleSearch,
item.key?.toString(),
),
// Only set defaultSortOrder for error_percentage, but allow sorting for all columns
...(item.key === 'error_percentage' && {
defaultSortOrder: 'descend',
}),
sortOrder: sortedInfo.columnKey === item.key ? sortedInfo.order : null,
})),
draggedColumns,
),
[tableData, draggedColumns],
[tableData, draggedColumns, sortedInfo],
);
const handleDragColumn = useCallback(
(fromIndex: number, toIndex: number) =>
@ -459,7 +473,7 @@ export default function CeleryOverviewTable({
]);
return (
<div style={{ width: '100%' }}>
<div className="celery-overview-table-container">
<Input.Search
placeholder="Search across all columns"
onChange={(e): void => setSearchText(e.target.value)}
@ -488,6 +502,12 @@ export default function CeleryOverviewTable({
className: 'clickable-row',
})}
tableLayout="fixed"
onChange={(_pagination, _filters, sorter): void => {
setSortedInfo({
columnKey: (sorter as { columnKey: string }).columnKey,
order: (sorter as { order: 'ascend' | 'descend' }).order,
});
}}
/>
</div>
);

View File

@ -8,6 +8,11 @@ import { DataSource } from 'types/common/queryBuilder';
export interface Filters {
searchText: string;
attributeKey: string | string[];
aggregateOperator?: string;
dataSource?: DataSource;
aggregateAttribute?: string;
filterAttributeKeyDataType?: DataTypes;
tagType?: string;
}
export interface GetAllFiltersResponse {
@ -16,7 +21,15 @@ export interface GetAllFiltersResponse {
}
export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const { searchText, attributeKey } = props;
const {
searchText,
attributeKey,
aggregateOperator,
dataSource,
aggregateAttribute,
filterAttributeKeyDataType,
tagType,
} = props;
const { data, isLoading } = useQuery(
['attributesValues', attributeKey, searchText],
@ -26,13 +39,14 @@ export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const responses = await Promise.all(
keys.map((key) =>
getAttributesValues({
aggregateOperator: 'noop',
dataSource: DataSource.TRACES,
aggregateAttribute: '',
aggregateOperator: aggregateOperator || 'noop',
dataSource: dataSource || DataSource.TRACES,
aggregateAttribute: aggregateAttribute || '',
attributeKey: key,
searchText: searchText ?? '',
filterAttributeKeyDataType: DataTypes.String,
tagType: 'tag',
filterAttributeKeyDataType:
filterAttributeKeyDataType || DataTypes.String,
tagType: tagType || 'tag',
}),
),
);

View File

@ -72,3 +72,51 @@
}
}
}
.lightMode {
.celery-task-detail-drawer {
.ant-drawer-wrapper-body {
background: var(--bg-vanilla-100);
border: 1px solid var(--bg-vanilla-300);
}
.ant-drawer-body {
.ant-card {
.ant-card-body {
background: var(--bg-vanilla-100);
.ant-table {
background: var(--bg-vanilla-100);
}
}
}
}
.ant-drawer-header {
border-bottom: 1px solid var(--bg-vanilla-300);
.ant-drawer-header-title {
button > svg {
color: var(--bg-ink-500);
}
.ant-drawer-title {
.title {
color: var(--bg-ink-400);
}
.subtitle {
color: var(--bg-ink-300);
}
}
}
}
.ant-drawer-footer {
border-top: 1px solid var(--bg-vanilla-300);
.footer-text {
color: var(--bg-ink-400);
}
}
}
}

View File

@ -24,12 +24,53 @@
.widget-graph-container {
&.bar {
height: calc(100% - 105px);
height: calc(100% - 110px);
}
}
}
}
.celery-task-graph-worker-count {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid var(--bg-slate-500);
background: linear-gradient(
0deg,
rgba(171, 189, 255, 0) 0%,
rgba(171, 189, 255, 0) 100%
),
#0b0c0e;
.ant-card-body {
height: 100%;
width: 100%;
}
.worker-count-text-container {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.celery-task-graph-worker-count-text {
font-size: 2.5vw;
text-align: center;
}
}
.worker-count-header {
display: flex;
justify-content: start;
align-items: start;
position: absolute;
height: 100%;
width: 100%;
}
}
.celery-task-graph-bar,
.celery-task-graph-task-latency {
height: 380px !important;
@ -46,7 +87,7 @@
.widget-graph-container {
&.bar {
height: calc(100% - 105px);
height: calc(100% - 110px);
}
&.graph {
@ -126,3 +167,40 @@
background-color: var(--bg-vanilla-100);
}
}
.lightMode {
.celery-task-graph-grid-container {
.celery-task-graph-grid {
.celery-task-graph-worker-count {
border: 1px solid var(--bg-vanilla-300);
background: unset;
}
}
}
.celery-task-states {
border-bottom: 1px solid var(--bg-vanilla-300);
&__tab {
&:not([data-last-tab='true']) {
border-right: 1px solid var(--bg-vanilla-300);
}
&--selected {
background-color: var(--bg-vanilla-200);
}
}
&__label {
color: var(--bg-ink-500);
}
&__value {
color: var(--bg-slate-100);
}
&__indicator {
background-color: var(--bg-ink-400);
}
}
}

View File

@ -1,11 +1,15 @@
import './CeleryTaskGraph.style.scss';
import { Card, Typography } from 'antd';
import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder';
import { GlobalReducer } from 'types/reducer/globalTime';
import { CaptureDataProps } from '../CeleryTaskDetail/CeleryTaskDetail';
import { useCeleryFilterOptions } from '../useCeleryFilterOptions';
import CeleryTaskBar from './CeleryTaskBar';
import CeleryTaskGraph from './CeleryTaskGraph';
import {
@ -13,7 +17,6 @@ import {
celeryErrorByWorkerWidgetData,
celeryLatencyByWorkerWidgetData,
celeryTasksByWorkerWidgetData,
celeryWorkerOnlineWidgetData,
} from './CeleryTaskGraphUtils';
import CeleryTaskLatencyGraph from './CeleryTaskLatencyGraph';
@ -28,11 +31,6 @@ export default function CeleryTaskGraphGrid({
(state) => state.globalTime,
);
const celeryWorkerOnlineData = useMemo(
() => celeryWorkerOnlineWidgetData(minTime, maxTime),
[minTime, maxTime],
);
const celeryActiveTasksData = useMemo(
() => celeryActiveTasksWidgetData(minTime, maxTime),
[minTime, maxTime],
@ -65,15 +63,31 @@ export default function CeleryTaskGraphGrid({
'Latency by worker',
];
const { options } = useCeleryFilterOptions(
'worker',
'rate',
DataSource.METRICS,
'flower_task_runtime_seconds_sum',
DataTypes.String,
'tag',
);
return (
<div className="celery-task-graph-grid-container">
<div className="celery-task-graph-grid">
<CeleryTaskBar queryEnabled={queryEnabled} onClick={onClick} />
<CeleryTaskGraph
key={celeryWorkerOnlineData.id}
widgetData={celeryWorkerOnlineData}
queryEnabled={queryEnabled}
/>
<Card className="celery-task-graph-worker-count">
<div className="worker-count-header">
<Typography.Text className="worker-count-header-text">
Worker Count
</Typography.Text>
</div>
<div className="worker-count-text-container">
<Typography.Text className="celery-task-graph-worker-count-text">
{options.filter((option) => option.value).length}
</Typography.Text>
</div>
</Card>
</div>
<div className="celery-task-graph-grid">
<CeleryTaskLatencyGraph onClick={onClick} queryEnabled={queryEnabled} />

View File

@ -490,49 +490,6 @@ export const celeryActiveTasksWidgetData = (
}),
);
export const celeryWorkerOnlineWidgetData = (
startTime: number,
endTime: number,
): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
title: 'Worker Online',
description: 'Represents the number of workers online.',
panelTypes: PANEL_TYPES.VALUE,
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'flower_task_runtime_seconds_sum--float64--Sum--true',
isColumn: true,
isJSON: false,
key: 'flower_task_runtime_seconds_sum',
type: 'Sum',
},
aggregateOperator: 'rate',
dataSource: DataSource.METRICS,
disabled: false,
expression: 'A',
filters: {
items: [],
op: 'AND',
},
functions: [],
groupBy: [],
having: [],
legend: '',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: getStepInterval(startTime, endTime),
timeAggregation: 'rate',
},
],
}),
);
export const celeryTaskLatencyWidgetData = (
type: string,
startTime: number,

View File

@ -1,11 +1,18 @@
import { DefaultOptionType } from 'antd/es/select';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import { useState } from 'react';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder';
import { useGetAllFilters } from './CeleryTaskConfigOptions/useGetCeleryFilters';
export const useCeleryFilterOptions = (
type: string | string[],
aggregateOperator?: string,
dataSource?: DataSource,
aggregateAttribute?: string,
filterAttributeKeyDataType?: DataTypes,
tagType?: string,
): {
searchText: string;
handleSearch: (value: string) => void;
@ -16,6 +23,11 @@ export const useCeleryFilterOptions = (
const { isFetching, options } = useGetAllFilters({
attributeKey: type,
searchText,
aggregateOperator,
dataSource,
aggregateAttribute,
filterAttributeKeyDataType,
tagType,
});
const handleDebouncedSearch = useDebouncedFn((searchText): void => {
setSearchText(searchText as string);

View File

@ -59,8 +59,8 @@ const ROUTES = {
WORKSPACE_SUSPENDED: '/workspace-suspended',
SHORTCUTS: '/shortcuts',
INTEGRATIONS: '/integrations',
MESSAGING_QUEUES: '/messaging-queues',
MESSAGING_QUEUES_DETAIL: '/messaging-queues/detail',
MESSAGING_QUEUES_KAFKA: '/messaging-queues/kafka',
MESSAGING_QUEUES_KAFKA_DETAIL: '/messaging-queues/kafka/detail',
INFRASTRUCTURE_MONITORING_HOSTS: '/infrastructure-monitoring/hosts',
INFRASTRUCTURE_MONITORING_KUBERNETES: '/infrastructure-monitoring/kubernetes',
MESSAGING_QUEUES_CELERY_TASK: '/messaging-queues/celery-task',

View File

@ -287,8 +287,8 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
routeKey === 'TRACES_EXPLORER' || routeKey === 'TRACES_SAVE_VIEWS';
const isMessagingQueues = (): boolean =>
routeKey === 'MESSAGING_QUEUES' ||
routeKey === 'MESSAGING_QUEUES_DETAIL' ||
routeKey === 'MESSAGING_QUEUES_KAFKA' ||
routeKey === 'MESSAGING_QUEUES_KAFKA_DETAIL' ||
routeKey === 'MESSAGING_QUEUES_CELERY_TASK' ||
routeKey === 'MESSAGING_QUEUES_OVERVIEW';

View File

@ -23,21 +23,15 @@ import {
TableData,
} from './utils';
export const HoverButtonWrapper = styled.div`
const ButtonWrapper = styled.div`
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
opacity: 0;
transition: opacity 0.2s;
`;
const RelativeWrapper = styled.div`
position: relative;
&:hover ${HoverButtonWrapper} {
opacity: 1;
}
`;
function GridTableComponent({
@ -206,12 +200,12 @@ function GridTableComponent({
return (
<RelativeWrapper>
{LineClampedTextComponent}
<HoverButtonWrapper className="hover-button">
<ButtonWrapper className="hover-button">
<button type="button" className="open-traces-button">
<Compass size={12} />
Open Trace
</button>
</HoverButtonWrapper>
</ButtonWrapper>
</RelativeWrapper>
);
},

View File

@ -239,7 +239,7 @@ function SideNav(): JSX.Element {
);
registerShortcut(GlobalShortcuts.NavigateToMessagingQueues, () =>
onClickHandler(ROUTES.MESSAGING_QUEUES, null),
onClickHandler(ROUTES.MESSAGING_QUEUES_OVERVIEW, null),
);
registerShortcut(GlobalShortcuts.NavigateToAlerts, () =>

View File

@ -49,8 +49,8 @@ export const routeConfig: Record<string, QueryParams[]> = {
[ROUTES.TRACE_EXPLORER]: [QueryParams.resourceAttributes],
[ROUTES.LOGS_PIPELINES]: [QueryParams.resourceAttributes],
[ROUTES.WORKSPACE_LOCKED]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_DETAIL]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_KAFKA]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_CELERY_TASK]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_OVERVIEW]: [QueryParams.resourceAttributes],
[ROUTES.INFRASTRUCTURE_MONITORING_HOSTS]: [QueryParams.resourceAttributes],

View File

@ -94,7 +94,7 @@ const menuItems: SidebarItem[] = [
icon: <LayoutGrid size={16} />,
},
{
key: ROUTES.MESSAGING_QUEUES,
key: ROUTES.MESSAGING_QUEUES_OVERVIEW,
label: 'Messaging Queues',
icon: <ListMinus size={16} />,
},

View File

@ -29,7 +29,7 @@ const breadcrumbNameMap: Record<string, string> = {
[ROUTES.SUPPORT]: 'Support',
[ROUTES.WORKSPACE_LOCKED]: 'Workspace Locked',
[ROUTES.WORKSPACE_SUSPENDED]: 'Workspace Suspended',
[ROUTES.MESSAGING_QUEUES]: 'Messaging Queues',
[ROUTES.MESSAGING_QUEUES_OVERVIEW]: 'Messaging Queues',
};
function ShowBreadcrumbs(props: RouteComponentProps): JSX.Element {

View File

@ -212,8 +212,8 @@ export const routesToSkip = [
ROUTES.SERVICE_TOP_LEVEL_OPERATIONS,
ROUTES.ALERT_HISTORY,
ROUTES.ALERT_OVERVIEW,
ROUTES.MESSAGING_QUEUES,
ROUTES.MESSAGING_QUEUES_DETAIL,
ROUTES.MESSAGING_QUEUES_KAFKA,
ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
ROUTES.MESSAGING_QUEUES_CELERY_TASK,
ROUTES.MESSAGING_QUEUES_OVERVIEW,
ROUTES.INFRASTRUCTURE_MONITORING_HOSTS,

View File

@ -1,22 +1,4 @@
.celery-overview-container {
.celery-overview-breadcrumb {
display: flex;
padding: 0px 16px;
align-items: center;
gap: 8px;
padding-top: 10px;
padding-bottom: 8px;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
border-bottom: 1px solid var(--bg-slate-400);
}
.celery-overview-content {
display: flex;
flex-direction: column;
@ -42,3 +24,15 @@
}
}
}
.lightMode {
.celery-overview-container {
.celery-overview-content {
.celery-overview-content-header {
.celery-overview-content-header-title {
color: var(--bg-slate-200);
}
}
}
}
}

View File

@ -28,3 +28,16 @@
}
}
}
.lightMode {
.overview-right-panel-graph-card {
border: 1px solid var(--bg-vanilla-300) !important;
background: var(--bg-vanilla-100);
.request-rate-card,
.error-rate-card,
.avg-latency-card {
border-bottom: 0.75px solid var(--bg-vanilla-300);
}
}
}

View File

@ -29,7 +29,9 @@ export default function CeleryOverviewDetails({
case 'span_name':
return getFiltersFromKeyValue('name', value, '');
case 'messaging_system':
return getFiltersFromKeyValue('messaging.system', value, 'tag');
return value === 'celery'
? undefined
: getFiltersFromKeyValue('messaging.system', value, 'tag');
case 'destination':
return getFiltersFromKeyValue(
details.messaging_system === 'celery'
@ -48,12 +50,6 @@ export default function CeleryOverviewDetails({
return keyValues.filter((item) => item !== undefined) as TagFilterItem[];
}, [details]);
const groupByFilter = useMemo(
() =>
getFiltersFromKeyValue('messaging.destination.partition.id', '', 'tag').key,
[],
);
return (
<Drawer
width="60%"
@ -92,7 +88,7 @@ export default function CeleryOverviewDetails({
>
<div className="celery-overview-detail-container">
<ValueInfo filters={filters} />
<OverviewRightPanelGraph filters={filters} groupByFilter={groupByFilter} />
<OverviewRightPanelGraph filters={filters} />
</div>
</Drawer>
);

View File

@ -49,6 +49,8 @@
margin-top: 8px;
background: #262626;
border: none;
box-shadow: none;
border-radius: 4px;
&:hover {
background: #404040;
@ -61,3 +63,32 @@
}
}
}
.lightMode {
.value-info-card {
border: 1px solid var(--bg-vanilla-300) !important;
background: var(--bg-vanilla-100);
.metric-column {
.metric-title {
color: var(--bg-slate-100);
}
.metric-unit {
color: var(--bg-ink-500);
}
.metric-reference {
color: var(--bg-ink-500);
}
.trace-button {
background: var(--bg-slate-200);
&:hover {
background: var(--bg-slate-100);
}
}
}
}
}

View File

@ -1,22 +1,4 @@
.celery-task-container {
.celery-task-breadcrumb {
display: flex;
padding: 0px 16px;
align-items: center;
gap: 8px;
padding-top: 10px;
padding-bottom: 8px;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
border-bottom: 1px solid var(--bg-slate-400);
}
.celery-content {
display: flex;
flex-direction: column;
@ -42,3 +24,15 @@
}
}
}
.lightMode {
.celery-task-container {
.celery-content {
.celery-content-header {
.celery-content-header-title {
color: var(--bg-slate-200);
}
}
}
}
}

View File

@ -1,13 +1,12 @@
/* eslint-disable no-nested-ternary */
import '../MessagingQueues.styles.scss';
import { Select, Typography } from 'antd';
import { Select } from 'antd';
import logEvent from 'api/common/logEvent';
import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes';
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
import useUrlQuery from 'hooks/useUrlQuery';
import { ListMinus } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
@ -65,20 +64,27 @@ function MQDetailPage(): JSX.Element {
selectedView !== MessagingQueuesViewType.dropRate.value &&
selectedView !== MessagingQueuesViewType.metricPage.value;
const handleBackClick = (): void => {
history.push(ROUTES.MESSAGING_QUEUES_KAFKA);
};
return (
<div className="messaging-queue-container">
<div className="messaging-breadcrumb">
<ListMinus size={16} />
<Typography.Text
onClick={(): void => history.push(ROUTES.MESSAGING_QUEUES)}
className="message-queue-text"
>
Messaging Queues
</Typography.Text>
</div>
<div className="messaging-header">
<div className="header-config">
<div
onClick={handleBackClick}
className="message-queue-text"
onKeyDown={(e): void => {
if (e.key === 'Enter' || e.key === ' ') {
handleBackClick();
}
}}
role="button"
tabIndex={0}
>
Kafka / views /
</div>
<Select
className="messaging-queue-options"
defaultValue={MessagingQueuesViewType.consumerLag.value}

View File

@ -1,31 +1,6 @@
.messaging-queue-container {
.messaging-breadcrumb {
display: flex;
padding: 0px 16px;
align-items: center;
gap: 8px;
padding-top: 10px;
padding-bottom: 8px;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
border-bottom: 1px solid var(--bg-slate-400);
.message-queue-text {
cursor: pointer;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
}
}
.messaging-header {
@ -334,14 +309,6 @@
.lightMode {
.messaging-queue-container {
.messaging-breadcrumb {
color: var(--bg-ink-400);
border-bottom: 1px solid var(--bg-vanilla-300);
.message-queue-text {
color: var(--bg-ink-400);
}
}
.messaging-header {
color: var(--bg-ink-400);
border-bottom: 1px solid var(--bg-vanilla-300);

View File

@ -30,7 +30,7 @@ function MessagingQueues(): JSX.Element {
});
history.push(
`${ROUTES.MESSAGING_QUEUES_DETAIL}?${QueryParams.mqServiceView}=${callerView}`,
`${ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL}?${QueryParams.mqServiceView}=${callerView}`,
);
};

View File

@ -6,10 +6,11 @@ import ROUTES from 'constants/routes';
import history from 'lib/history';
import { ListMinus, Rows3 } from 'lucide-react';
import CeleryOverview from 'pages/Celery/CeleryOverview/CeleryOverview';
import { useLocation } from 'react-use';
import { useLocation } from 'react-router-dom';
import CeleryTask from '../Celery/CeleryTask/CeleryTask';
import MessagingQueues from './MessagingQueues';
import MQDetailPage from './MQDetailPage/MQDetailPage';
export const Kafka: TabRoutes = {
Component: MessagingQueues,
@ -18,8 +19,19 @@ export const Kafka: TabRoutes = {
<ListMinus size={16} /> Kafka
</div>
),
route: ROUTES.MESSAGING_QUEUES,
key: ROUTES.MESSAGING_QUEUES,
route: ROUTES.MESSAGING_QUEUES_KAFKA,
key: ROUTES.MESSAGING_QUEUES_KAFKA,
};
export const KafkaDetail: TabRoutes = {
Component: MQDetailPage,
name: (
<div className="tab-item">
<ListMinus size={16} /> Kafka
</div>
),
route: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
key: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
};
export const Celery: TabRoutes = {
@ -47,7 +59,13 @@ export const Overview: TabRoutes = {
export default function MessagingQueuesMainPage(): JSX.Element {
const { pathname } = useLocation();
const routes: TabRoutes[] = [Kafka, Celery, Overview];
const isKafkaDetail = pathname === ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL;
const routes: TabRoutes[] = [
Overview,
isKafkaDetail ? KafkaDetail : Kafka,
Celery,
];
return (
<div className="messaging-queues-module-container">

View File

@ -52,8 +52,8 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
ALL_CHANNELS: ['ADMIN', 'EDITOR', 'VIEWER'],
INGESTION_SETTINGS: ['ADMIN', 'EDITOR', 'VIEWER'],
ALL_DASHBOARD: ['ADMIN', 'EDITOR', 'VIEWER'],
MESSAGING_QUEUES: ['ADMIN', 'EDITOR', 'VIEWER'],
MESSAGING_QUEUES_DETAIL: ['ADMIN', 'EDITOR', 'VIEWER'],
MESSAGING_QUEUES_KAFKA: ['ADMIN', 'EDITOR', 'VIEWER'],
MESSAGING_QUEUES_KAFKA_DETAIL: ['ADMIN', 'EDITOR', 'VIEWER'],
ALL_ERROR: ['ADMIN', 'EDITOR', 'VIEWER'],
APPLICATION: ['ADMIN', 'EDITOR', 'VIEWER'],
CHANNELS_EDIT: ['ADMIN'],