Compare commits

..

2 Commits

Author SHA1 Message Date
Naman Verma
7551064aac test: correct errors pkg in test file 2026-05-21 13:14:40 +05:30
Naman Verma
d00be5895d fix: add check for percentile aggregation for non-histogram metrics 2026-05-21 11:57:38 +05:30
404 changed files with 23302 additions and 11751 deletions

7
.github/CODEOWNERS vendored
View File

@@ -118,9 +118,6 @@ go.mod @therealpandey
/tests/integration/ @therealpandey
# e2e tests
/tests/e2e/ @AshwinBhatkal
# Flagger Owners
/pkg/flagger/ @therealpandey
@@ -165,7 +162,3 @@ go.mod @therealpandey
/frontend/src/lib/dashboard/ @SigNoz/pulse-frontend
/frontend/src/lib/dashboardVariables/ @SigNoz/pulse-frontend
/frontend/src/components/NewSelect/ @SigNoz/pulse-frontend
## Dashboard V2
/frontend/src/pages/DashboardPageV2/ @SigNoz/pulse-frontend
/frontend/src/pages/DashboardsListPageV2/ @SigNoz/pulse-frontend

View File

@@ -2689,6 +2689,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesClusterRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -2758,6 +2759,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesDaemonSetRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -2827,6 +2829,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesDeploymentRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -2905,6 +2908,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesHostRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -2980,6 +2984,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesJobRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -3027,6 +3032,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesNamespaceRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -3104,6 +3110,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesNodeRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -3202,6 +3209,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesPodRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -3546,6 +3554,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesStatefulSetRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
@@ -3606,6 +3615,7 @@ components:
records:
items:
$ref: '#/components/schemas/InframonitoringtypesVolumeRecord'
nullable: true
type: array
requiredMetricsCheck:
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'

View File

@@ -49,7 +49,7 @@
"@signozhq/design-tokens": "2.1.4",
"@signozhq/icons": "0.4.0",
"@signozhq/resizable": "0.0.2",
"@signozhq/ui": "0.0.21",
"@signozhq/ui": "0.0.19",
"@tanstack/react-table": "8.21.3",
"@tanstack/react-virtual": "3.13.22",
"@uiw/codemirror-theme-copilot": "4.23.11",

View File

@@ -14,13 +14,8 @@
*/
const BANNED_COMPONENTS = {
Typography:
'Use @signozhq/ui/typography Typography instead of antd Typography.',
Switch: 'Use @signozhq/ui/switch Switch instead of antd Switch.',
Typography: 'Use @signozhq/ui Typography instead of antd Typography.',
Badge: 'Use @signozhq/ui/badge instead of antd Badge.',
Progress: 'Use @signozhq/ui/progress instead of antd Progress.',
Select:
'Use SelectSimple / ComboboxSimple from @signozhq/ui/select or @signozhq/ui/combobox instead of antd Select.',
};
export default {

View File

@@ -77,8 +77,8 @@ importers:
specifier: 0.0.2
version: 0.0.2(@types/react@18.0.26)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
'@signozhq/ui':
specifier: 0.0.21
version: 0.0.21(@emotion/is-prop-valid@1.2.0)(@signozhq/icons@0.4.0)(@types/react-dom@18.0.10)(@types/react@18.0.26)(react-dom@18.2.0(react@18.2.0))(react-router-dom@5.3.4(react@18.2.0))(react-router@6.30.3(react@18.2.0))(react@18.2.0)
specifier: 0.0.19
version: 0.0.19(@emotion/is-prop-valid@1.2.0)(@signozhq/icons@0.4.0)(@types/react-dom@18.0.10)(@types/react@18.0.26)(react-dom@18.2.0(react@18.2.0))(react-router-dom@5.3.4(react@18.2.0))(react-router@6.30.3(react@18.2.0))(react@18.2.0)
'@tanstack/react-table':
specifier: 8.21.3
version: 8.21.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -3269,8 +3269,8 @@ packages:
peerDependencies:
react: ^18.2.0
'@signozhq/ui@0.0.21':
resolution: {integrity: sha512-uLM3Vqwxlk2USXbwtb3qRLpjZR9b9QSHFQq/jtcfYNMDmIE/sNjSj0nRkEhX4RqqRgsLRt2PVA33aeWxDOLO3g==}
'@signozhq/ui@0.0.19':
resolution: {integrity: sha512-2q6aRxN/PR4PlR2xJZAREEuvLPiDFggfFKzCW2Z5vHVVbrgnvZHWD1jPUuwszfEg0ceH3UvkwqceO7wN4uRJAA==}
peerDependencies:
'@signozhq/icons': 0.3.0
react: ^18.2.0
@@ -3851,6 +3851,27 @@ packages:
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
'@webassemblyjs/ast@1.14.1':
resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==}
'@webassemblyjs/floating-point-hex-parser@1.13.2':
resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==}
'@webassemblyjs/helper-api-error@1.13.2':
resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==}
'@webassemblyjs/helper-buffer@1.14.1':
resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==}
'@webassemblyjs/helper-numbers@1.13.2':
resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==}
'@webassemblyjs/helper-wasm-bytecode@1.13.2':
resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==}
'@webassemblyjs/helper-wasm-section@1.14.1':
resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==}
'@xmldom/xmldom@0.8.13':
resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==}
engines: {node: '>=10.0.0'}
@@ -12013,7 +12034,7 @@ snapshots:
- react-dom
- tailwindcss
'@signozhq/ui@0.0.21(@emotion/is-prop-valid@1.2.0)(@signozhq/icons@0.4.0)(@types/react-dom@18.0.10)(@types/react@18.0.26)(react-dom@18.2.0(react@18.2.0))(react-router-dom@5.3.4(react@18.2.0))(react-router@6.30.3(react@18.2.0))(react@18.2.0)':
'@signozhq/ui@0.0.19(@emotion/is-prop-valid@1.2.0)(@signozhq/icons@0.4.0)(@types/react-dom@18.0.10)(@types/react@18.0.26)(react-dom@18.2.0(react@18.2.0))(react-router-dom@5.3.4(react@18.2.0))(react-router@6.30.3(react@18.2.0))(react@18.2.0)':
dependencies:
'@chenglou/pretext': 0.0.5
'@radix-ui/react-checkbox': 1.3.3(@types/react-dom@18.0.10)(@types/react@18.0.26)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)

View File

@@ -4,7 +4,7 @@
"no_alerts_found": "No alerts found during the evaluation. This happens when rule condition is unsatisfied. You may adjust the rule threshold and retry.",
"button_testrule": "Test Notification",
"label_channel_select": "Notification Channels",
"placeholder_channel_select": "Select one or more channels",
"placeholder_channel_select": "select one or more channels",
"channel_select_tooltip": "Leave empty to send this alert on all the configured channels",
"preview_chart_unexpected_error": "An unexpeced error occurred updating the chart, please check your query.",
"preview_chart_threshold_label": "Threshold",

View File

@@ -4,7 +4,7 @@
"no_alerts_found": "No alerts found during the evaluation. This happens when rule condition is unsatisfied. You may adjust the rule threshold and retry.",
"button_testrule": "Test Notification",
"label_channel_select": "Notification Channels",
"placeholder_channel_select": "Select one or more channels",
"placeholder_channel_select": "select one or more channels",
"channel_select_tooltip": "Leave empty to send this alert on all the configured channels",
"preview_chart_unexpected_error": "An unexpeced error occurred updating the chart, please check your query.",
"preview_chart_threshold_label": "Threshold",

View File

@@ -166,7 +166,6 @@ function createMockAppContext(
userPreferences: [],
hostsData: null,
isLoggedIn: true,
isPreflightLoading: false,
org: [{ createdAt: 0, id: 'org-id', displayName: 'Test Org' }],
isFetchingUser: false,
isFetchingActiveLicense: false,

View File

@@ -59,7 +59,6 @@ function App(): JSX.Element {
isLoggedIn: isLoggedInState,
featureFlags,
org,
isPreflightLoading,
} = useAppContext();
const [routes, setRoutes] = useState<AppRoutes[]>(defaultRoutes);
const isAIAssistantEnabled = useIsAIAssistantEnabled();
@@ -387,10 +386,6 @@ function App(): JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isCloudUser, isEnterpriseSelfHostedUser]);
if (isPreflightLoading) {
return <Spinner tip="Loading..." />;
}
// if the user is in logged in state
if (isLoggedInState) {
// if the setup calls are loading then return a spinner

View File

@@ -1,72 +0,0 @@
import axios from 'axios';
import { getIsNoAuthMode } from 'utils/noAuthMode';
import { interceptorRejected } from '../index';
jest.mock('utils/noAuthMode', () => ({
getIsNoAuthMode: jest.fn(),
}));
jest.mock('api/v2/sessions/rotate/post', () => ({
__esModule: true,
default: jest.fn(),
}));
jest.mock('AppRoutes/utils', () => ({
__esModule: true,
default: jest.fn(),
}));
jest.mock('../utils', () => ({
Logout: jest.fn(),
}));
// oxlint-disable-next-line typescript/no-require-imports typescript/no-var-requires
const post = require('api/v2/sessions/rotate/post').default;
// oxlint-disable-next-line typescript/no-require-imports typescript/no-var-requires
const { Logout } = require('../utils');
describe('interceptorRejected — no-auth mode', () => {
beforeEach(() => {
jest.clearAllMocks();
jest.spyOn(axios, 'isAxiosError').mockReturnValue(true);
});
it('does NOT call rotate or Logout when no-auth mode is enabled on 401', async () => {
(getIsNoAuthMode as jest.Mock).mockReturnValue(true);
const error = {
isAxiosError: true,
response: {
status: 401,
config: { url: '/dashboards', method: 'get' },
},
config: { url: '/dashboards', headers: {} },
};
await interceptorRejected(error as any).catch(() => {});
expect(post).not.toHaveBeenCalled();
expect(Logout).not.toHaveBeenCalled();
});
it('DOES attempt rotate when no-auth mode is disabled on 401', async () => {
(getIsNoAuthMode as jest.Mock).mockReturnValue(false);
(post as jest.Mock).mockResolvedValue({
data: { accessToken: 'a', refreshToken: 'b' },
});
const error = {
isAxiosError: true,
response: {
status: 401,
config: { url: '/dashboards', method: 'get' },
},
config: { url: '/dashboards', headers: {} },
};
await interceptorRejected(error as any).catch(() => {});
expect(post).toHaveBeenCalled();
});
});

View File

@@ -3488,9 +3488,9 @@ export interface InframonitoringtypesClustersDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesClusterRecordDTO[];
records: InframonitoringtypesClusterRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -3566,9 +3566,9 @@ export interface InframonitoringtypesDaemonSetsDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesDaemonSetRecordDTO[];
records: InframonitoringtypesDaemonSetRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -3644,9 +3644,9 @@ export interface InframonitoringtypesDeploymentsDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesDeploymentRecordDTO[];
records: InframonitoringtypesDeploymentRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -3730,9 +3730,9 @@ export interface InframonitoringtypesHostsDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesHostRecordDTO[];
records: InframonitoringtypesHostRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -3816,9 +3816,9 @@ export interface InframonitoringtypesJobsDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesJobRecordDTO[];
records: InframonitoringtypesJobRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -3866,9 +3866,9 @@ export interface InframonitoringtypesNamespacesDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesNamespaceRecordDTO[];
records: InframonitoringtypesNamespaceRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -3933,9 +3933,9 @@ export interface InframonitoringtypesNodesDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesNodeRecordDTO[];
records: InframonitoringtypesNodeRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -4017,9 +4017,9 @@ export interface InframonitoringtypesPodsDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesPodRecordDTO[];
records: InframonitoringtypesPodRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -4437,9 +4437,9 @@ export interface InframonitoringtypesStatefulSetsDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesStatefulSetRecordDTO[];
records: InframonitoringtypesStatefulSetRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer
@@ -4506,9 +4506,9 @@ export interface InframonitoringtypesVolumesDTO {
*/
endTimeBeforeRetention: boolean;
/**
* @type array
* @type array,null
*/
records: InframonitoringtypesVolumeRecordDTO[];
records: InframonitoringtypesVolumeRecordDTO[] | null;
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
/**
* @type integer

View File

@@ -13,7 +13,6 @@ import { Events } from 'constants/events';
import { LOCALSTORAGE } from 'constants/localStorage';
import { getBasePath } from 'utils/basePath';
import { eventEmitter } from 'utils/getEventEmitter';
import { getIsNoAuthMode } from 'utils/noAuthMode';
import apiV1, { apiAlertManager, apiV2, apiV3, apiV4, apiV5 } from './apiV1';
import { Logout } from './utils';
@@ -109,10 +108,7 @@ export const interceptorRejected = async (
if (axios.isAxiosError(value) && value.response) {
const { response } = value;
const isNoAuthMode = getIsNoAuthMode();
if (
!isNoAuthMode &&
response.status === 401 &&
// if the session rotate call or the create session errors out with 401 or the delete sessions call returns 401 then we do not retry!
response.config.url !== '/sessions/rotate' &&
@@ -144,20 +140,16 @@ export const interceptorRejected = async (
return await Promise.resolve(reResponse);
} catch (error) {
if ((error as AxiosError)?.response?.status === 401) {
void Logout();
Logout();
}
}
} catch (error) {
void Logout();
Logout();
}
}
if (
!isNoAuthMode &&
response.status === 401 &&
response.config.url === '/sessions/rotate'
) {
void Logout();
if (response.status === 401 && response.config.url === '/sessions/rotate') {
Logout();
}
}
return await Promise.reject(value);

View File

@@ -1,3 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor" d="M8.932 20.806c-.369 0-.738.007-1.109 0-.35-.007-.587-.206-.623-.5a.587.587 0 0 1 .53-.636c.79-.062 1.582-.063 2.372-.003a.548.548 0 0 1 .522.602c-.024.326-.253.526-.616.54zM1.792 8.345c-.392 0-.782.008-1.173.002-.327-.006-.577-.22-.614-.512-.037-.293.146-.544.499-.615.192-.032.388-.045.583-.039a81.515 81.515 0 0 1 1.597 0c.163 0 .325.019.483.056.288.073.445.318.411.617-.034.298-.214.477-.515.487-.424.014-.848.004-1.272.004zm7.588 8.417H4.292a2.464 2.464 0 0 1-.326-.007c-.294-.04-.48-.209-.508-.506-.029-.298.11-.501.391-.606.179-.065.365-.051.549-.051 3.347 0 6.695.005 10.042-.006 1.174-.004 2.187-.439 2.993-1.3.69-.738 1.053-1.63 1.16-2.635.085-.788-.027-1.513-.516-2.156-.544-.718-1.28-1.078-2.163-1.082-3.163-.013-6.328-.005-9.487-.01-.336 0-.673-.027-1.007-.058-.29-.027-.45-.201-.469-.492-.021-.317.141-.545.429-.6a1.55 1.55 0 0 1 .29-.015h10.177c1.71.004 3.187 1.038 3.726 2.654.383 1.147.246 2.304-.182 3.416-.824 2.135-2.762 3.448-5.055 3.454-1.652.005-3.304 0-4.956 0zm2.906-13.568c1.533 0 3.066-.008 4.598 0 2.935.018 5.629 1.892 6.653 4.626.442 1.181.538 2.403.412 3.657-.185 1.842-.735 3.552-1.776 5.084-1.608 2.365-3.873 3.68-6.679 4.118-.95.148-1.905.13-2.86.13-.397 0-.61-.181-.633-.51-.025-.351.196-.621.587-.645.434-.026.87-.004 1.305-.016 2.641-.072 4.928-.982 6.74-2.935 1.269-1.37 1.912-3.039 2.13-4.878.151-1.275.135-2.544-.37-3.752-.773-1.85-2.159-2.983-4.068-3.509-.74-.204-1.5-.243-2.26-.247-2.837-.017-5.675-.007-8.511-.007-.12 0-.24.004-.359-.006a.57.57 0 0 1-.517-.536.557.557 0 0 1 .456-.557c.13-.018.261-.024.392-.019h4.762Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,7 +0,0 @@
<svg width="456" height="456" viewBox="0 0 456 456" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="456" height="456" rx="50" fill="#512BD4"/>
<path d="M81.2738 291.333C78.0496 291.333 75.309 290.259 73.052 288.11C70.795 285.906 69.6665 283.289 69.6665 280.259C69.6665 277.173 70.795 274.529 73.052 272.325C75.309 270.121 78.0496 269.019 81.2738 269.019C84.5518 269.019 87.3193 270.121 89.5763 272.325C91.887 274.529 93.0424 277.173 93.0424 280.259C93.0424 283.289 91.887 285.906 89.5763 288.11C87.3193 290.259 84.5518 291.333 81.2738 291.333Z" fill="white"/>
<path d="M210.167 289.515H189.209L133.994 202.406C132.597 200.202 131.441 197.915 130.528 195.546H130.044C130.474 198.081 130.689 203.508 130.689 211.827V289.515H112.149V171H134.477L187.839 256.043C190.096 259.57 191.547 261.994 192.192 263.316H192.514C191.977 260.176 191.708 254.859 191.708 247.365V171H210.167V289.515Z" fill="white"/>
<path d="M300.449 289.515H235.561V171H297.87V187.695H254.746V221.249H294.485V237.861H254.746V272.903H300.449V289.515Z" fill="white"/>
<path d="M392.667 187.695H359.457V289.515H340.272V187.695H307.143V171H392.667V187.695Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,15 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18">
<defs>
<linearGradient id="a" x1="9" y1="17" x2="9" y2="1" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0078d4"/>
<stop offset="1" stop-color="#5ea0ef"/>
</linearGradient>
</defs>
<circle cx="9" cy="9" r="8" fill="url(#a)"/>
<ellipse cx="9" cy="9" rx="3.2" ry="8" fill="none" stroke="#fff" stroke-width=".7"/>
<line x1="1" y1="9" x2="17" y2="9" stroke="#fff" stroke-width=".7"/>
<line x1="2" y1="5.5" x2="16" y2="5.5" stroke="#fff" stroke-width=".5"/>
<line x1="2" y1="12.5" x2="16" y2="12.5" stroke="#fff" stroke-width=".5"/>
<circle cx="9" cy="9" r="8" fill="none" stroke="#fff" stroke-width=".7"/>
<path d="M13.5 10.5l1.5-1.5-1.5-1.5M4.5 10.5L3 9l1.5-1.5" stroke="#50e6ff" stroke-width="1" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 877 B

View File

@@ -1,15 +0,0 @@
<svg width="142" height="142" viewBox="0 0 142 142" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clipPath="url(#clip0_0_812)" transform="matrix(1.002103,0,0,1.0377318,6.9399999e-7,-2.5317276e-4)">
<path d="m 141.702,68.418 c 0,7.4632 -4.567,14.1123 -6.748,20.8385 -2.263,6.9789 -2.552,15.0285 -6.776,20.8385 -4.267,5.868 -11.856,8.611 -17.719,12.881 -5.805,4.228 -10.7345,10.628 -17.7061,12.895 -6.7286,2.186 -14.4463,-0.021 -21.9018,-0.021 -7.4555,0 -15.1731,2.207 -21.8998,0.021 C 41.9778,133.604 37.048,127.204 31.2428,122.976 25.3799,118.706 17.7913,115.963 13.5247,110.095 9.30055,104.287 9.01135,96.2374 6.74791,89.2565 4.56351,82.5225 0,75.8735 0,68.418 0,60.9624 4.56737,54.3057 6.74791,47.5795 9.01135,40.6005 9.30055,32.5507 13.5247,26.741 17.7913,20.8753 25.3799,18.1297 31.2428,13.8617 37.048,9.63414 41.9778,3.23209 48.9513,0.966872 55.678,-1.21924 63.3956,0.986167 70.8511,0.986167 c 7.4555,0 15.1732,-2.205407 21.8999,-0.019295 6.9735,2.265218 11.903,8.667268 17.708,12.894828 5.863,4.268 13.452,7.0136 17.719,12.8793 4.224,5.8097 4.513,13.8595 6.776,20.8385 2.181,6.7262 6.748,13.3771 6.748,20.8385 z" fill="#326ce5"/>
<path d="m 70.8473,8.18683 c -33.2383,0 -60.1837,26.96657 -60.1837,60.23097 0,33.2642 26.9454,60.2312 60.1837,60.2312 33.2387,0 60.1837,-26.959 60.1837,-60.2312 0,-33.2721 -26.945,-60.23097 -60.1837,-60.23097 z M 70.8319,123.408 C 40.4778,123.408 15.9058,98.8053 15.9,68.4274 15.9,38.0167 40.5357,13.3791 70.9109,13.437 c 30.3751,0.0579 54.9111,24.6589 54.8841,55.0329 -0.027,30.374 -24.609,54.9481 -54.9631,54.9381 z" fill="#ffffff"/>
<path d="m 13.5883,60.53 c 8.1804,0 8.1804,3.859 16.3589,3.859 8.1784,0 8.1804,-3.859 16.3607,-3.859 8.1804,0 8.1785,3.859 16.3589,3.859 8.1804,0 8.1785,-3.859 16.3589,-3.859 8.1804,0 8.1803,3.859 16.3588,3.859 8.1785,0 8.1805,-3.859 16.3605,-3.859 8.181,0 8.181,3.859 16.361,3.859" stroke="#ffffff" strokeMiterlimit="10"/>
<path d="m 13.5883,68.248 c 8.1804,0 8.1804,3.859 16.3589,3.859 8.1784,0 8.1804,-3.859 16.3607,-3.859 8.1804,0 8.1785,3.859 16.3589,3.859 8.1804,0 8.1785,-3.859 16.3589,-3.859 8.1804,0 8.1803,3.859 16.3588,3.859 8.1785,0 8.1805,-3.859 16.3605,-3.859 8.181,0 8.181,3.859 16.361,3.859" stroke="#ffffff" strokeMiterlimit="10"/>
<path d="m 13.5883,77.5095 c 8.1804,0 8.1804,3.859 16.3589,3.859 8.1784,0 8.1804,-3.859 16.3607,-3.859 8.1804,0 8.1785,3.859 16.3589,3.859 8.1804,0 8.1785,-3.859 16.3589,-3.859 8.1804,0 8.1803,3.859 16.3588,3.859 8.1785,0 8.1805,-3.859 16.3605,-3.859 8.181,0 8.181,3.859 16.361,3.859" stroke="#ffffff" strokeMiterlimit="10"/>
<path d="m 70.8473,8.18683 c -33.2383,0 -60.1837,26.96657 -60.1837,60.23097 0,33.2642 26.9454,60.2312 60.1837,60.2312 33.2387,0 60.1837,-26.959 60.1837,-60.2312 0,-33.2721 -26.945,-60.23097 -60.1837,-60.23097 z M 70.8319,123.408 C 40.4778,123.408 15.9058,98.8053 15.9,68.4274 15.9,38.0167 40.5357,13.3791 70.9109,13.437 c 30.3751,0.0579 54.9111,24.6589 54.8841,55.0329 -0.027,30.374 -24.609,54.9481 -54.9631,54.9381 z" fill="#ffffff"/>
</g>
<defs>
<clipPath id="clip0_0_812">
<rect width="141.702" height="136.837" fill="#ffffff"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,55 +0,0 @@
<svg viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<g>
<rect x="122" y="-0.4" transform="matrix(-0.866 -0.5 0.5 -0.866 163.3196 363.3136)" fill="#E535AB" width="16.6" height="320.3"/>
</g>
</g>
<g>
<g>
<rect x="39.8" y="272.2" fill="#E535AB" width="320.3" height="16.6"/>
</g>
</g>
<g>
<g>
<rect x="37.9" y="312.2" transform="matrix(-0.866 -0.5 0.5 -0.866 83.0693 663.3409)" fill="#E535AB" width="185" height="16.6"/>
</g>
</g>
<g>
<g>
<rect x="177.1" y="71.1" transform="matrix(-0.866 -0.5 0.5 -0.866 463.3409 283.0693)" fill="#E535AB" width="185" height="16.6"/>
</g>
</g>
<g>
<g>
<rect x="122.1" y="-13" transform="matrix(-0.5 -0.866 0.866 -0.5 126.7903 232.1221)" fill="#E535AB" width="16.6" height="185"/>
</g>
</g>
<g>
<g>
<rect x="109.6" y="151.6" transform="matrix(-0.5 -0.866 0.866 -0.5 266.0828 473.3766)" fill="#E535AB" width="320.3" height="16.6"/>
</g>
</g>
<g>
<g>
<rect x="52.5" y="107.5" fill="#E535AB" width="16.6" height="185"/>
</g>
</g>
<g>
<g>
<rect x="330.9" y="107.5" fill="#E535AB" width="16.6" height="185"/>
</g>
</g>
<g>
<g>
<rect x="262.4" y="240.1" transform="matrix(-0.5 -0.866 0.866 -0.5 126.7953 714.2875)" fill="#E535AB" width="14.5" height="160.9"/>
</g>
</g>
<path fill="#E535AB" d="M369.5,297.9c-9.6,16.7-31,22.4-47.7,12.8c-16.7-9.6-22.4-31-12.8-47.7c9.6-16.7,31-22.4,47.7-12.8 C373.5,259.9,379.2,281.2,369.5,297.9"/>
<path fill="#E535AB" d="M90.9,137c-9.6,16.7-31,22.4-47.7,12.8c-16.7-9.6-22.4-31-12.8-47.7c9.6-16.7,31-22.4,47.7-12.8 C94.8,99,100.5,120.3,90.9,137"/>
<path fill="#E535AB" d="M30.5,297.9c-9.6-16.7-3.9-38,12.8-47.7c16.7-9.6,38-3.9,47.7,12.8c9.6,16.7,3.9,38-12.8,47.7 C61.4,320.3,40.1,314.6,30.5,297.9"/>
<path fill="#E535AB" d="M309.1,137c-9.6-16.7-3.9-38,12.8-47.7c16.7-9.6,38-3.9,47.7,12.8c9.6,16.7,3.9,38-12.8,47.7 C340.1,159.4,318.7,153.7,309.1,137"/>
<path fill="#E535AB" d="M200,395.8c-19.3,0-34.9-15.6-34.9-34.9c0-19.3,15.6-34.9,34.9-34.9c19.3,0,34.9,15.6,34.9,34.9 C234.9,380.1,219.3,395.8,200,395.8"/>
<path fill="#E535AB" d="M200,74c-19.3,0-34.9-15.6-34.9-34.9c0-19.3,15.6-34.9,34.9-34.9c19.3,0,34.9,15.6,34.9,34.9 C234.9,58.4,219.3,74,200,74"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 77.62745 102.5">
<path fill="#516baa" d="m31.05548,54.44523v24.1773c.00065.04512-.03164.084-.07611.09164l-23.27949,3.99047c-.05091.0076-.09834-.02751-.10594-.07841-.00256-.01712-.0003-.03461.00653-.05051L30.87996,30.58635c.02242-.04633.07815-.06572.12449-.04331.0316.01529.05193.04704.05259.08214l-.00156,23.82005Zm3.92367-13.93321v38.21148c.00046.04691.03573.08617.08232.09164l34.87031,3.89415c.0512.00527.09698-.03196.10226-.08316.00167-.01616-.00092-.03247-.00751-.04732L35.15623,4.70041c-.02237-.04636-.07809-.0658-.12444-.04343-.03117.01504-.05144.04612-.05264.08071v35.77433Zm34.68546,45.76213l-38.57341,11.57218c-.02155.00797-.04524.00797-.06679,0l-23.309-11.57217c-.04636-.0203-.06749-.07435-.04719-.12071.01513-.03455.04988-.0563.08757-.05481h61.88241c.0508.00825.08531.05613.07706.10693-.00482.0297-.02369.05525-.05066.06859Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 901 B

View File

@@ -1,3 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor" d="M.113 10.27A13.026 13.026 0 000 11.48h18.23c-.064-.125-.15-.237-.235-.347-3.117-4.027-4.793-3.677-7.19-3.78-.8-.034-1.34-.048-4.524-.048-1.704 0-3.555.005-5.358.01-.234.63-.459 1.24-.567 1.737h9.342v1.216H.113v.002zm18.26 2.426H.009c.02.326.05.645.094.961h16.955c.754 0 1.179-.429 1.315-.96zm-17.318 4.28s2.81 6.902 10.93 7.024c4.855 0 9.027-2.883 10.92-7.024H1.056zM11.988 0C7.5 0 3.593 2.466 1.531 6.108l4.75-.005v-.002c3.71 0 3.849.016 4.573.047l.448.016c1.563.052 3.485.22 4.996 1.364.82.621 2.007 1.99 2.712 2.965.654.902.842 1.94.396 2.934-.408.914-1.289 1.458-2.353 1.458H.391s.099.42.249.886h22.748A12.026 12.026 0 0024 12.005C24 5.377 18.621 0 11.988 0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 776 B

View File

@@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 590 270">
<path d="M30.36,109.14v.48h0A3.73,3.73,0,0,1,30.36,109.14Z" fill="currentColor" fill-rule="evenodd"/>
<path d="M138.66,28.78C107.2,37.87,57.29,43,30.4,43h0V94.35a.8.8,0,0,0,.19.48c18.35,0,75-6,109.18-15.4a129,129,0,0,0,17.49-5.81c4.18-1.88,6.88-3.86,6.88-5.92V15.91C164.1,20.79,151.39,25.11,138.66,28.78Z" fill="#de3423" fill-rule="evenodd"/>
<path d="M138.66,95.37c-18.83,5.43-44.24,9.47-67.39,11.83-15.54,1.59-30.06,2.42-40.87,2.42h0v51.31a.8.8,0,0,0,.19.48c18.35,0,75-6,109.18-15.39a130.38,130.38,0,0,0,17.49-5.81c4.18-1.89,6.88-3.86,6.88-5.92V82.5C164.1,87.37,151.39,91.69,138.66,95.37Z" fill="#de3423" fill-rule="evenodd"/>
<path d="M138.66,162c-18.83,5.43-44.24,9.46-67.39,11.83-15.56,1.59-30.1,2.42-40.91,2.42V228c18.16,0,75.1-5.95,109.37-15.39,12.63-3.48,24.37-7.44,24.37-11.74V149.08C164.1,154,151.39,158.28,138.66,162Z" fill="#de3423" fill-rule="evenodd"/>
<path d="M30.55,94.83C32.4,97.38,48,102.19,71.27,107.2c23.27,4.46,47.47,22.07,66.29,16.64,12.73-3.68,26.54-36.47,26.54-41.34V82c0-3.4-2.55-6.13-6.88-8.4-17.75-9.07-21.11-12.41-27.69-10.6C95.37,72.43,35.06,67.61,30.55,94.83Z" fill="currentColor" fill-rule="evenodd"/>
<path d="M30.55,161.41C32.4,164,48,168.77,71.27,173.79c26,4.74,48.61,20.19,67.44,14.75,12.73-3.68,25.39-34.58,25.39-39.46v-.48c0-3.39-2.55-6.13-6.88-8.39-13.54-7.2-31.43-15.13-38-13.32C85,136.3,39.26,138.37,30.55,161.41Z" fill="currentColor" fill-rule="evenodd"/>
<path d="M200.7,142.39c6,11.79,15.6,17.6,29.05,17.6,14.44,0,19.59-7.64,19.59-15.11,0-5.15-1.83-8.63-6.64-11.79-4.82-3.32-8.3-4.81-16.93-8-10.63-4-16.77-7-23.41-12.29-6.64-5.48-9.79-13-9.79-22.74a28.28,28.28,0,0,1,10.29-22.58c7-5.81,15.44-8.63,25.56-8.63,15.77,0,27.72,6.31,35.69,18.76L249.34,87.78c-4.48-6.81-11.29-10.3-20.59-10.3-9.13,0-15.77,5.15-15.77,12.29,0,4.81,2,7.14,4.82,10,1.82,1.33,6.47,3.32,8.63,4.48l6,2.32,6.8,2.66c11,4.48,18.76,9.3,23.57,14.44s7.31,12.12,7.31,20.75c0,20.42-14.11,34.2-40.51,34.2-21.41,0-37.18-10-44.48-26.4Z" fill="currentColor"/>
<path d="M354.25,104.71,342,117.49a28.14,28.14,0,0,0-21.24-9.13,25,25,0,0,0-18.43,7.47,27.76,27.76,0,0,0,0,37.52,25,25,0,0,0,18.43,7.47A28.14,28.14,0,0,0,342,151.69l12.29,12.78c-9,9.63-20.09,14.44-33.53,14.44-12.79,0-23.58-4.15-32.37-12.62s-13.12-19.09-13.12-31.7,4.32-23.08,13.12-31.54,19.58-12.78,32.37-12.78C334.16,90.27,345.28,95.08,354.25,104.71Z" fill="currentColor"/>
<path d="M393.88,125.62C408,124.3,413,122.47,413,116c0-5.15-4.64-9.13-13.94-9.13q-13.44,0-22.41,10.95l-12.28-10.46c8.13-11.45,19.58-17.09,34.36-17.09,20.75,0,33.7,10,33.7,27.05v37c0,5.81,2.15,6.48,7,6.48h.5v15.43c-2,1.17-5.15,1.83-9.3,1.83-4.48,0-8-1.33-10.62-4a14.06,14.06,0,0,1-3-5.48c-5.81,6.8-15.27,10.29-28.39,10.29-18.42,0-30.87-10.13-30.87-25.4C357.7,136.41,369.15,127.78,393.88,125.62ZM391.56,162c13.28,0,21.41-6,21.41-16.6v-9.3a9.75,9.75,0,0,1-4.14,2.49c-3.82,1.33-6.31,1.66-14.28,2.49-11.62,1.33-17.43,5-17.43,10.79C377.12,158.33,382.43,162,391.56,162Z" fill="currentColor"/>
<path d="M444.84,60.88h19.92V149.2c0,8.13,2.66,11.62,10,11.62a21.15,21.15,0,0,0,6-.67v17.76a35.56,35.56,0,0,1-9.47,1c-17.59,0-26.39-9-26.39-27.06Z" fill="currentColor"/>
<path d="M521.71,125.62c14.11-1.32,19.09-3.15,19.09-9.62,0-5.15-4.64-9.13-13.94-9.13q-13.44,0-22.41,10.95l-12.28-10.46c8.13-11.45,19.58-17.09,34.36-17.09,20.75,0,33.7,10,33.7,27.05v37c0,5.81,2.15,6.48,7,6.48h.5v15.43c-2,1.17-5.15,1.83-9.3,1.83-4.48,0-8-1.33-10.62-4a13.94,13.94,0,0,1-3-5.48c-5.81,6.8-15.27,10.29-28.39,10.29-18.42,0-30.87-10.13-30.87-25.4C485.53,136.41,497,127.78,521.71,125.62ZM519.39,162c13.28,0,21.41-6,21.41-16.6v-9.3a9.73,9.73,0,0,1-4.15,2.49c-3.81,1.33-6.3,1.66-14.27,2.49-11.62,1.33-17.43,5-17.43,10.79C505,158.33,510.26,162,519.39,162Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -1,37 +0,0 @@
<svg viewBox="0 0 254.5 225" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<g>
<g>
<path fill="#00ACD7" d="M40.2,101.1c-0.4,0-0.5-0.2-0.3-0.5l2.1-2.7c0.2-0.3,0.7-0.5,1.1-0.5l35.7,0c0.4,0,0.5,0.3,0.3,0.6 l-1.7,2.6c-0.2,0.3-0.7,0.6-1,0.6L40.2,101.1z"/>
</g>
</g>
</g>
<g>
<g>
<g>
<path fill="#00ACD7" d="M25.1,110.3c-0.4,0-0.5-0.2-0.3-0.5l2.1-2.7c0.2-0.3,0.7-0.5,1.1-0.5l45.6,0c0.4,0,0.6,0.3,0.5,0.6 l-0.8,2.4c-0.1,0.4-0.5,0.6-0.9,0.6L25.1,110.3z"/>
</g>
</g>
</g>
<g>
<g>
<g>
<path fill="#00ACD7" d="M49.3,119.5c-0.4,0-0.5-0.3-0.3-0.6l1.4-2.5c0.2-0.3,0.6-0.6,1-0.6l20,0c0.4,0,0.6,0.3,0.6,0.7l-0.2,2.4 c0,0.4-0.4,0.7-0.7,0.7L49.3,119.5z"/>
</g>
</g>
</g>
<g>
<g id="CXHf1q_3_">
<g>
<g>
<path fill="#00ACD7" d="M153.1,99.3c-6.3,1.6-10.6,2.8-16.8,4.4c-1.5,0.4-1.6,0.5-2.9-1c-1.5-1.7-2.6-2.8-4.7-3.8 c-6.3-3.1-12.4-2.2-18.1,1.5c-6.8,4.4-10.3,10.9-10.2,19c0.1,8,5.6,14.6,13.5,15.7c6.8,0.9,12.5-1.5,17-6.6 c0.9-1.1,1.7-2.3,2.7-3.7c-3.6,0-8.1,0-19.3,0c-2.1,0-2.6-1.3-1.9-3c1.3-3.1,3.7-8.3,5.1-10.9c0.3-0.6,1-1.6,2.5-1.6 c5.1,0,23.9,0,36.4,0c-0.2,2.7-0.2,5.4-0.6,8.1c-1.1,7.2-3.8,13.8-8.2,19.6c-7.2,9.5-16.6,15.4-28.5,17 c-9.8,1.3-18.9-0.6-26.9-6.6c-7.4-5.6-11.6-13-12.7-22.2c-1.3-10.9,1.9-20.7,8.5-29.3c7.1-9.3,16.5-15.2,28-17.3 c9.4-1.7,18.4-0.6,26.5,4.9c5.3,3.5,9.1,8.3,11.6,14.1C154.7,98.5,154.3,99,153.1,99.3z"/>
</g>
<g>
<path fill="#00ACD7" d="M186.2,154.6c-9.1-0.2-17.4-2.8-24.4-8.8c-5.9-5.1-9.6-11.6-10.8-19.3c-1.8-11.3,1.3-21.3,8.1-30.2 c7.3-9.6,16.1-14.6,28-16.7c10.2-1.8,19.8-0.8,28.5,5.1c7.9,5.4,12.8,12.7,14.1,22.3c1.7,13.5-2.2,24.5-11.5,33.9 c-6.6,6.7-14.7,10.9-24,12.8C191.5,154.2,188.8,154.3,186.2,154.6z M210,114.2c-0.1-1.3-0.1-2.3-0.3-3.3 c-1.8-9.9-10.9-15.5-20.4-13.3c-9.3,2.1-15.3,8-17.5,17.4c-1.8,7.8,2,15.7,9.2,18.9c5.5,2.4,11,2.1,16.3-0.6 C205.2,129.2,209.5,122.8,210,114.2z"/>
</g>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,12 +1,12 @@
import { useCallback, useMemo, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { Row } from 'antd';
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
import { Row, Select, Spin } from 'antd';
import {
getValuesFromQueryParams,
setQueryParamsFromOptions,
} from 'components/CeleryTask/CeleryUtils';
import { useCeleryFilterOptions } from 'components/CeleryTask/useCeleryFilterOptions';
import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon';
import { QueryParams } from 'constants/query';
import useUrlQuery from 'hooks/useUrlQuery';
@@ -48,7 +48,7 @@ export function FilterSelect({
: getValuesFromQueryParams(queryParam, urlQuery) || [];
// Memoize options to include the typed value if not present
const mergedOptions = useMemo<ComboboxSimpleItem[]>(() => {
const mergedOptions = useMemo(() => {
if (
!!searchValue.trim().length &&
!options.some((opt) => opt.value === searchValue)
@@ -84,16 +84,35 @@ export function FilterSelect({
],
);
// Update searchValue on user input
const handleSearchInput = (input: string): void => {
setSearchValue(input);
handleSearch(input);
};
return (
<ComboboxSimple
<Select
key={filterType.toString()}
placeholder={placeholder}
multiple={isMultiple}
items={mergedOptions}
showSearch
{...(isMultiple ? { mode: 'multiple' } : {})}
options={mergedOptions}
loading={isFetching}
className="config-select-option"
onSearch={handleSearchInput}
maxTagCount={4}
allowClear
maxTagPlaceholder={SelectMaxTagPlaceholder}
value={selectValue}
emptyPlaceholder={`No ${placeholder} found`}
notFoundContent={
isFetching ? (
<span>
<Spin size="small" /> Loading...
</span>
) : (
<span>No {placeholder} found</span>
)
}
onChange={handleSelectChange}
/>
);

View File

@@ -51,6 +51,13 @@
background: var(--l1-background);
}
.progress-container {
.ant-progress-bg {
height: 8px !important;
border-radius: 4px;
}
}
.ant-table-tbody > tr:hover > td {
background: color-mix(in srgb, var(--l1-foreground) 4%, transparent);
}

View File

@@ -9,13 +9,13 @@ import {
Flex,
Input,
InputRef,
Progress,
Space,
Spin,
TableColumnsType,
TableColumnType,
Tooltip,
} from 'antd';
import { Progress } from '@signozhq/ui/progress';
import { Typography } from '@signozhq/ui/typography';
import type { FilterDropdownProps } from 'antd/lib/table/interface';
import logEvent from 'api/common/logEvent';
@@ -59,7 +59,7 @@ function ProgressRender(item: string | number): JSX.Element {
<Progress
percent={percent}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const cpuPercent = percent;
if (cpuPercent >= 90) {

View File

@@ -1,6 +1,7 @@
import { useHistory, useLocation } from 'react-router-dom';
import { ComboboxSimple } from '@signozhq/ui/combobox';
import { Select, Spin } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon';
import { QueryParams } from 'constants/query';
import useUrlQuery from 'hooks/useUrlQuery';
@@ -26,18 +27,30 @@ function CeleryTaskConfigOptions(): JSX.Element {
<Typography.Text style={{ whiteSpace: 'nowrap' }}>
Task Name
</Typography.Text>
<ComboboxSimple
<Select
placeholder="Task Name"
multiple
items={options}
showSearch
mode="multiple"
options={options}
loading={isFetching}
className="config-select-option"
onSearch={handleSearch}
maxTagCount={4}
maxTagPlaceholder={SelectMaxTagPlaceholder}
value={getValuesFromQueryParams(QueryParams.taskName, urlQuery) || []}
emptyPlaceholder="No Task Name found"
notFoundContent={
isFetching ? (
<span>
<Spin size="small" /> Loading...
</span>
) : (
<span>No Task Name found</span>
)
}
onChange={(value): void => {
handleSearch('');
setQueryParamsFromOptions(
value as string[],
value,
urlQuery,
history,
location,

View File

@@ -1,7 +1,7 @@
import { useQuery } from 'react-query';
// eslint-disable-next-line no-restricted-imports
import { useSelector } from 'react-redux';
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import type { DefaultOptionType } from 'antd/es/select';
import { getAttributesValues } from 'api/queryBuilder/getAttributesValues';
import { DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY } from 'constants/queryBuilder';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
@@ -21,7 +21,7 @@ export interface Filters {
}
export interface GetAllFiltersResponse {
options: ComboboxSimpleItem[];
options: DefaultOptionType[];
isFetching: boolean;
}

View File

@@ -1,5 +1,5 @@
import { useState } from 'react';
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import type { DefaultOptionType } from 'antd/es/select';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder';
@@ -17,7 +17,7 @@ export const useCeleryFilterOptions = (
searchText: string;
handleSearch: (value: string) => void;
isFetching: boolean;
options: ComboboxSimpleItem[];
options: DefaultOptionType[];
} => {
const [searchText, setSearchText] = useState<string>('');
const { isFetching, options } = useGetAllFilters({

View File

@@ -5,25 +5,17 @@ import {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { Color } from '@signozhq/design-tokens';
import {
Combobox,
ComboboxCommand,
ComboboxContent,
ComboboxEmpty,
ComboboxItem,
ComboboxList,
ComboboxMultiTrigger,
ComboboxPill,
} from '@signozhq/ui/combobox';
import { Tag, Tooltip } from 'antd';
import { Select, Tag, Tooltip } from 'antd';
import {
OPERATORS,
QUERY_BUILDER_OPERATORS_BY_TYPES,
QUERY_BUILDER_SEARCH_VALUES,
} from 'constants/queryBuilder';
import { CustomTagProps } from 'container/QueryBuilder/filters/QueryBuilderSearch';
import { selectStyle } from 'container/QueryBuilder/filters/QueryBuilderSearch/config';
import { PLACEHOLDER } from 'container/QueryBuilder/filters/QueryBuilderSearch/constant';
import { TypographyText } from 'container/QueryBuilder/filters/QueryBuilderSearch/style';
@@ -46,6 +38,7 @@ import { operatorTypeMapper } from 'hooks/queryBuilder/useOperatorType';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { isArray, isEmpty, isEqual, isObject } from 'lodash-es';
import { ChevronDown, ChevronUp } from '@signozhq/icons';
import type { BaseSelectRef } from 'rc-select';
import {
BaseAutocompleteData,
DataTypes,
@@ -54,6 +47,7 @@ import {
IBuilderQuery,
TagFilter,
} from 'types/api/queryBuilder/queryBuilderData';
import { popupContainer } from 'utils/selectPopupContainer';
import { v4 as uuid } from 'uuid';
import './ClientSideQBSearch.styles.scss';
@@ -99,6 +93,8 @@ function ClientSideQBSearch(
const isDarkMode = useIsDarkMode();
const selectRef = useRef<BaseSelectRef>(null);
const [isOpen, setIsOpen] = useState<boolean>(false);
// create the tags from the initial query here, this should only be computed on the first load as post that tags and query will be always in sync.
@@ -218,7 +214,7 @@ function ClientSideQBSearch(
}, []);
const onInputKeyDownHandler = useCallback(
(event: KeyboardEvent<HTMLInputElement>): void => {
(event: KeyboardEvent<Element>): void => {
if (event.key === 'Backspace' && !searchValue) {
event.stopPropagation();
setTags((prev) => prev.slice(0, -1));
@@ -520,23 +516,29 @@ function ClientSideQBSearch(
[tags],
);
const renderPill = (value: string, index: number): React.ReactElement => {
const onTagRender = ({
value,
closable,
onClose,
}: CustomTagProps): React.ReactElement => {
const { tagOperator } = getTagToken(value);
const isInNin = isInNInOperator(tagOperator);
const chipValue = isInNin
? value?.trim()?.replace(/,\s*$/, '')
: value?.trim();
const tagDetails = tags[index];
const indexInQueryTags = queryTags.findIndex((qTag) => isEqual(qTag, value));
const tagDetails = tags[indexInQueryTags];
const onCloseHandler = (): void => {
onClose();
setSearchValue('');
setTags((prev) => prev.filter((t) => !isEqual(t, tagDetails)));
};
const tagEditHandler = (next: string): void => {
const tagEditHandler = (value: string): void => {
setCurrentFilterItem(tagDetails);
setSearchValue(next);
setSearchValue(value);
setCurrentState(DropdownState.ATTRIBUTE_VALUE);
setTags((prev) => prev.filter((t) => !isEqual(t, tagDetails)));
};
@@ -544,13 +546,12 @@ function ClientSideQBSearch(
const isDisabled = !!searchValue;
return (
<ComboboxPill
key={`${value}-${index}`}
value={value}
onRemove={onCloseHandler}
className="qb-search-bar-tokenised-tags"
>
<Tag closable={false} className={tagDetails?.key?.type || ''}>
<span className="qb-search-bar-tokenised-tags">
<Tag
closable={!searchValue && closable}
onClose={onCloseHandler}
className={tagDetails?.key?.type || ''}
>
<Tooltip title={chipValue}>
<TypographyText
$isInNin={isInNin}
@@ -566,7 +567,7 @@ function ClientSideQBSearch(
</TypographyText>
</Tooltip>
</Tag>
</ComboboxPill>
</span>
);
};
@@ -587,73 +588,59 @@ function ClientSideQBSearch(
);
}, [isDarkMode, isOpen, suffixIcon]);
const handleItemSelect = (rawValue: string): void => {
handleDropdownSelect(rawValue);
setIsOpen(true);
};
const handleInputKeyDownWrapper = (
e: KeyboardEvent<HTMLInputElement>,
): void => {
onInputKeyDownHandler(e);
};
return (
<div className="query-builder-search-v2" style={selectStyle}>
<Combobox open={isOpen} onOpenChange={setIsOpen}>
<ComboboxMultiTrigger
id="client-side-qb-search-trigger"
testId="client-side-qb-search"
className={className ?? 'query-builder-search client-side-qb-search'}
placeholder={placeholder ?? PLACEHOLDER}
inputValue={searchValue}
onInputChange={handleSearch}
onKeyDown={handleInputKeyDownWrapper}
onFocus={(): void => setIsOpen(true)}
disabled={!attributeKeys.length}
>
{queryTags.map((tagValue, idx) => renderPill(tagValue, idx))}
</ComboboxMultiTrigger>
<ComboboxContent
onCloseAutoFocus={(): void => {
handleOnBlur();
}}
>
<ComboboxCommand shouldFilter={false}>
<ComboboxList>
{dropdownOptions.map((option) => {
let val = option.value as unknown as string;
try {
if (isObject(option.value)) {
val = JSON.stringify(option.value);
}
} catch {
val = String(option.value);
}
const itemKey = isObject(val) ? `select-option` : String(val);
return (
<ComboboxItem
key={itemKey}
value={String(val)}
onSelect={(): void => handleItemSelect(String(val))}
>
<Suggestions
label={option.label}
value={option.value}
option={currentState}
searchValue={searchValue}
/>
</ComboboxItem>
);
})}
<ComboboxEmpty>No results found.</ComboboxEmpty>
</ComboboxList>
</ComboboxCommand>
</ComboboxContent>
</Combobox>
<div className="qb-search-suffix" aria-hidden>
{suffixIconContent}
</div>
<div className="query-builder-search-v2 ">
<Select
ref={selectRef}
getPopupContainer={popupContainer}
virtual={false}
showSearch
tagRender={onTagRender}
transitionName=""
choiceTransitionName=""
filterOption={false}
open={isOpen}
suffixIcon={suffixIconContent}
onDropdownVisibleChange={setIsOpen}
autoClearSearchValue={false}
mode="multiple"
placeholder={placeholder}
value={queryTags}
searchValue={searchValue}
className={className}
rootClassName="query-builder-search client-side-qb-search"
disabled={!attributeKeys.length}
style={selectStyle}
onSearch={handleSearch}
onSelect={handleDropdownSelect}
onInputKeyDown={onInputKeyDownHandler}
notFoundContent={null}
showAction={['focus']}
onBlur={handleOnBlur}
>
{dropdownOptions.map((option) => {
let val = option.value;
try {
if (isObject(option.value)) {
val = JSON.stringify(option.value);
} else {
val = option.value;
}
} catch {
val = option.value;
}
return (
<Select.Option key={isObject(val) ? `select-option` : val} value={val}>
<Suggestions
label={option.label}
value={option.value}
option={currentState}
searchValue={searchValue}
/>
</Select.Option>
);
})}
</Select>
</div>
);
}

View File

@@ -137,6 +137,7 @@ function CreateServiceAccountModal(): JSX.Element {
<AuthZTooltip checks={[SACreatePermission]}>
<Button
type="submit"
// @ts-expect-error -- form prop not in @signozhq/ui Button type - TODO: Fix this - @SagarRajput
form="create-sa-form"
variant="solid"
color="primary"

View File

@@ -1,7 +1,15 @@
import { useMemo, useState } from 'react';
import { useState } from 'react';
import { useCopyToClipboard } from 'react-use';
import { Button, Col, Dropdown, MenuProps, Popover, Row, Space } from 'antd';
import { ComboboxSimple } from '@signozhq/ui/combobox';
import {
Button,
Col,
Dropdown,
MenuProps,
Popover,
Row,
Select,
Space,
} from 'antd';
import { Typography } from '@signozhq/ui/typography';
import axios from 'axios';
import TextToolTip from 'components/TextToolTip';
@@ -23,7 +31,11 @@ import { popupContainer } from 'utils/selectPopupContainer';
import { ExploreHeaderToolTip, SaveButtonText } from './constants';
import MenuItemGenerator from './MenuItemGenerator';
import SaveViewWithName from './SaveViewWithName';
import { ExplorerCardHeadContainer, OffSetCol } from './styles';
import {
DropDownOverlay,
ExplorerCardHeadContainer,
OffSetCol,
} from './styles';
import { ExplorerCardProps } from './types';
import { deleteViewHandler } from './utils';
import { Ellipsis, Save, Share2, Trash2 } from '@signozhq/icons';
@@ -152,26 +164,6 @@ function ExplorerCard({
const showSaveView = false;
const viewItems = useMemo(
() =>
(viewsData?.data.data ?? []).map((view) => ({
value: view.name,
label: (
<MenuItemGenerator
viewName={view.name}
viewKey={viewKey}
createdBy={view.createdBy}
uuid={view.id}
refetchAllView={refetchAllView}
viewData={viewsData?.data.data ?? []}
sourcePage={sourcepage}
/>
),
displayValue: view.name,
})),
[refetchAllView, sourcepage, viewKey, viewsData?.data.data],
);
return (
<>
{showSaveView && (
@@ -191,12 +183,30 @@ function ExplorerCard({
<Space size="large">
{viewsData?.data.data && viewsData?.data.data.length && (
<Space>
<ComboboxSimple
<Select
getPopupContainer={popupContainer}
loading={isLoading || isRefetching}
showSearch
placeholder="Select a view"
items={viewItems}
dropdownStyle={DropDownOverlay}
dropdownMatchSelectWidth={false}
optionLabelProp="value"
value={viewName || undefined}
/>
>
{viewsData?.data.data.map((view) => (
<Select.Option key={view.id} value={view.name}>
<MenuItemGenerator
viewName={view.name}
viewKey={viewKey}
createdBy={view.createdBy}
uuid={view.id}
refetchAllView={refetchAllView}
viewData={viewsData.data.data}
sourcePage={sourcepage}
/>
</Select.Option>
))}
</Select>
</Space>
)}
{isQueryUpdated && (

View File

@@ -11,6 +11,9 @@ import { GuardAuthZ } from './GuardAuthZ';
describe('GuardAuthZ', () => {
const TestChild = (): ReactElement => <div>Protected Content</div>;
const LoadingFallback = (): ReactElement => <div>Loading...</div>;
const ErrorFallback = (error: Error): ReactElement => (
<div>Error occurred: {error.message}</div>
);
const NoPermissionFallback = (_response: {
requiredPermissionName: BrandedPermission;
}): ReactElement => <div>Access denied</div>;
@@ -87,28 +90,40 @@ describe('GuardAuthZ', () => {
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
});
it('should render children when API error occurs and no fallbackOnError provided (fail open)', async () => {
it('should render fallbackOnError when API error occurs', async () => {
const errorMessage = 'Internal Server Error';
server.use(
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
return res(ctx.status(500), ctx.json({ error: errorMessage }));
}),
);
render(
<GuardAuthZ relation="read" object="role:*">
<GuardAuthZ relation="read" object="role:*" fallbackOnError={ErrorFallback}>
<TestChild />
</GuardAuthZ>,
);
await waitFor(() => {
expect(screen.getByText('Protected Content')).toBeInTheDocument();
expect(screen.getByText(/Error occurred:/)).toBeInTheDocument();
});
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
});
it('should render fallbackOnError when API error occurs and fallbackOnError is provided', async () => {
it('should pass error object to fallbackOnError function', async () => {
const errorMessage = 'Network request failed';
let receivedError: Error | null = null;
const errorFallbackWithCapture = (error: Error): ReactElement => {
receivedError = error;
return <div>Captured error: {error.message}</div>;
};
server.use(
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
return res(ctx.status(500), ctx.json({ error: errorMessage }));
}),
);
@@ -116,14 +131,35 @@ describe('GuardAuthZ', () => {
<GuardAuthZ
relation="read"
object="role:*"
fallbackOnError={<div>Custom error fallback</div>}
fallbackOnError={errorFallbackWithCapture}
>
<TestChild />
</GuardAuthZ>,
);
await waitFor(() => {
expect(screen.getByText('Custom error fallback')).toBeInTheDocument();
expect(receivedError).not.toBeNull();
});
expect(receivedError).toBeInstanceOf(Error);
expect(screen.getByText(/Captured error:/)).toBeInTheDocument();
});
it('should render null when error occurs and no fallbackOnError provided', async () => {
server.use(
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
}),
);
const { container } = render(
<GuardAuthZ relation="read" object="role:*">
<TestChild />
</GuardAuthZ>,
);
await waitFor(() => {
expect(container.firstChild).toBeNull();
});
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();

View File

@@ -12,7 +12,7 @@ export type GuardAuthZProps<R extends AuthZRelation> = {
relation: R;
object: AuthZObject<R>;
fallbackOnLoading?: JSX.Element;
fallbackOnError?: JSX.Element;
fallbackOnError?: (error: Error) => JSX.Element;
fallbackOnNoPermissions?: (response: {
requiredPermissionName: BrandedPermission;
}) => JSX.Element;
@@ -35,7 +35,7 @@ export function GuardAuthZ<R extends AuthZRelation>({
}
if (error) {
return fallbackOnError ?? children;
return fallbackOnError?.(error) ?? null;
}
if (!permissions?.[permission]?.isGranted) {

View File

@@ -4,8 +4,7 @@ import { useSelector } from 'react-redux';
import { matchPath, useLocation } from 'react-router-dom';
import { useCopyToClipboard } from 'react-use';
import { Color } from '@signozhq/design-tokens';
import { Button } from 'antd';
import { Switch } from '@signozhq/ui/switch';
import { Button, Switch } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import logEvent from 'api/common/logEvent';
import { QueryParams } from 'constants/query';
@@ -126,8 +125,9 @@ function ShareURLModal(): JSX.Element {
<Info size={14} color={Color.BG_AMBER_600} />
)}
<Switch
value={enableAbsoluteTime}
checked={enableAbsoluteTime}
disabled={!isValidateRelativeTime}
size="small"
onChange={(): void => {
setEnableAbsoluteTime((prev) => !prev);
}}

View File

@@ -20,9 +20,9 @@
padding: 0px 8px;
border-radius: 2px 0px 0px 2px;
border: 1px solid var(--input-with-label-border-color, var(--l2-border));
background: var(--input-with-label-background-color, var(--l2-background));
color: var(--input-with-label-color, var(--l2-foreground));
border: 1px solid var(--l2-border);
background: var(--l2-background);
color: var(--l2-foreground);
display: flex;
justify-content: flex-start;
@@ -35,28 +35,21 @@
min-width: 150px;
font-family: 'Space Mono', monospace !important;
border-radius: 2px;
border: 1px solid var(--input-with-label-border-color, var(--l2-border));
background: var(--input-with-label-background-color, var(--l2-background));
color: var(--input-with-label-color, var(--l2-foreground));
border-radius: 2px 0px 0px 2px;
border: 1px solid var(--l1-border);
background: var(--l2-background);
border-right: none;
border-left: none;
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
font-size: 12px !important;
line-height: 25px;
&.input__has-label-after {
border-left: none;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
&.input__has-close-button {
border-right: none;
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
line-height: 27px;
&::placeholder {
color: var(--input-with-label-color, var(--l3-foreground)) !important;
color: var(--l2-foreground) !important;
font-size: 12px !important;
}
&[type='number']::-webkit-inner-spin-button,
@@ -70,24 +63,25 @@
.close-btn {
border-radius: 0px 2px 2px 0px;
border: 1px solid var(--input-with-label-border-color, var(--l2-border));
background: var(--input-with-label-background-color, var(--l2-background));
height: 100%;
border: 1px solid var(--l2-border);
background: var(--l2-background);
height: 38px;
width: 38px;
}
&.labelAfter {
.input {
border-radius: 2px;
border: 1px solid var(--input-with-label-border-color, var(--l2-border));
background: var(--input-with-label-background-color, var(--l2-background));
border-radius: 0px 2px 2px 0px;
border: 1px solid var(--l1-border);
background: var(--l2-background);
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
.label {
border-left: none;
border-radius: 0px 2px 2px 0px;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
}
}

View File

@@ -44,10 +44,7 @@ function InputWithLabel({
>
{!labelAfter && <Typography.Text className="label">{label}</Typography.Text>}
<Input
className={cx('input', {
'input__has-label-after': !labelAfter,
'input__has-close-button': !!onClose,
})}
className="input"
placeholder={placeholder}
type={type}
value={inputValue}

View File

@@ -1,12 +1,12 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { Style } from '@signozhq/design-tokens';
import { Plus, Trash2, X } from '@signozhq/icons';
import { ChevronDown, Plus, Trash2, X } from '@signozhq/icons';
import { Button } from '@signozhq/ui/button';
import { Callout } from '@signozhq/ui/callout';
import { DialogFooter, DialogWrapper } from '@signozhq/ui/dialog';
import { Input } from '@signozhq/ui/input';
import { SelectSimple } from '@signozhq/ui/select';
import { toast } from '@signozhq/ui/sonner';
import { Select } from 'antd';
import inviteUsers from 'api/v1/invite/bulk/create';
import sendInvite from 'api/v1/invite/create';
import { cloneDeep, debounce } from 'lodash-es';
@@ -15,6 +15,7 @@ import APIError from 'types/api/error';
import { ROLES } from 'types/roles';
import { EMAIL_REGEX } from 'utils/app';
import { getBaseUrl } from 'utils/basePath';
import { popupContainer } from 'utils/selectPopupContainer';
import { v4 as uuid } from 'uuid';
import './InviteMembersModal.styles.scss';
@@ -253,17 +254,18 @@ function InviteMembersModal({
)}
</div>
<div className="team-member-cell role-cell">
<SelectSimple
<Select
value={row.role || undefined}
onChange={(role): void => updateRole(row.id, role as ROLES)}
className="team-member-role-select"
placeholder="Select roles"
items={[
{ value: 'VIEWER', label: 'Viewer' },
{ value: 'EDITOR', label: 'Editor' },
{ value: 'ADMIN', label: 'Admin' },
]}
/>
suffixIcon={<ChevronDown size={14} />}
getPopupContainer={popupContainer}
>
<Select.Option value="VIEWER">Viewer</Select.Option>
<Select.Option value="EDITOR">Editor</Select.Option>
<Select.Option value="ADMIN">Admin</Select.Option>
</Select>
</div>
<div className="team-member-cell action-cell">
{rows.length > 1 && (

View File

@@ -1,7 +1,7 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { Button, Input, InputNumber, Popover, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import type { DefaultOptionType } from 'antd/es/select';
import cx from 'classnames';
import { LogViewMode } from 'container/LogsTable';
import { FontSize, OptionsMenuConfig } from 'container/OptionsMenu/types';
@@ -113,11 +113,15 @@ function OptionsMenu({
function handleColumnSelection(
currentIndex: number,
optionsData: ComboboxSimpleItem[],
optionsData: DefaultOptionType[],
): void {
const currentItem = optionsData[currentIndex];
const itemLength = optionsData.length;
if (addColumn && addColumn?.onSelect && selectedValue) {
addColumn?.onSelect(selectedValue);
if (addColumn && addColumn?.onSelect) {
addColumn?.onSelect(selectedValue, {
label: currentItem.label,
disabled: false,
});
// if the last element is selected then select the previous one
if (currentIndex === itemLength - 1) {
@@ -171,7 +175,7 @@ function OptionsMenu({
}
case 'Enter':
e.preventDefault();
handleColumnSelection(currentIndex, optionsData as ComboboxSimpleItem[]);
handleColumnSelection(currentIndex, optionsData);
break;
default:
break;
@@ -313,10 +317,7 @@ function OptionsMenu({
}}
onClick={(eve): void => {
eve.stopPropagation();
handleColumnSelection(
index,
(addColumn?.options || []) as ComboboxSimpleItem[],
);
handleColumnSelection(index, addColumn?.options || []);
}}
>
<div className="name">

View File

@@ -10,8 +10,7 @@ import {
Loader,
X,
} from '@signozhq/icons';
import { Modal, Spin, Tooltip, Tree, TreeDataNode } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Modal, Select, Spin, Tooltip, Tree, TreeDataNode } from 'antd';
import { OnboardingStatusResponse } from 'api/messagingQueues/onboarding/getOnboardingStatus';
import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes';
@@ -182,8 +181,8 @@ function AttributeCheckList({
const [filter, setFilter] = useState<AttributesFilters>(AttributesFilters.ALL);
const [treeData, setTreeData] = useState<TreeDataNode[]>([]);
const handleFilterChange = (value: string | string[]): void => {
setFilter(value as AttributesFilters);
const handleFilterChange = (value: AttributesFilters): void => {
setFilter(value);
};
const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
const history = useHistory();
@@ -238,11 +237,11 @@ function AttributeCheckList({
</div>
) : (
<div className="modal-content">
<SelectSimple
<Select
defaultValue={AttributesFilters.ALL}
className="attribute-select"
onChange={handleFilterChange}
items={[
options={[
{
value: AttributesFilters.ALL,
label: AttributeLabels({ title: 'Attributes: All' }),

View File

@@ -1,6 +1,6 @@
import { Color } from '@signozhq/design-tokens';
import { Tooltip } from 'antd';
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import type { DefaultOptionType } from 'antd/es/select';
import { Info } from '@signozhq/icons';
import './MQCommon.styles.scss';
@@ -35,7 +35,7 @@ export function ComingSoon(): JSX.Element {
}
export function SelectMaxTagPlaceholder(
omittedValues: Partial<ComboboxSimpleItem>[],
omittedValues: Partial<DefaultOptionType>[],
): JSX.Element {
return (
<Tooltip title={omittedValues.map(({ value }) => value).join(', ')}>

View File

@@ -18,9 +18,7 @@ import {
RefreshCw,
} from '@signozhq/icons';
import { Color } from '@signozhq/design-tokens';
// oxlint-disable-next-line signoz/no-antd-components This component for now is too complex to be migrated in one PR
import { Select } from 'antd';
import { Button, Checkbox } from 'antd';
import { Button, Checkbox, Select } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import cx from 'classnames';
import TextToolTip from 'components/TextToolTip/TextToolTip';

View File

@@ -16,7 +16,6 @@ import {
X,
} from '@signozhq/icons';
import { Color } from '@signozhq/design-tokens';
// oxlint-disable-next-line signoz/no-antd-components This component for now is too complex to be migrated in one PR
import { Select } from 'antd';
import cx from 'classnames';
import TextToolTip from 'components/TextToolTip';

View File

@@ -1,13 +0,0 @@
.banner {
height: var(--spacing-20);
a {
color: var(--callout-warning-title);
text-decoration: underline;
&:hover {
color: var(--callout-warning-title);
opacity: 0.8;
}
}
}

View File

@@ -1,26 +0,0 @@
import { PersistedAnnouncementBanner } from '@signozhq/ui/announcement-banner';
import styles from './NoAuthBanner.module.scss';
export function NoAuthBanner(): JSX.Element {
return (
<PersistedAnnouncementBanner
type="warning"
storageKey="no-auth-banner-v1"
testId="no-auth-banner"
className={styles.banner}
>
Impersonation mode: authentication is disabled. Anyone with access to this
instance has admin privileges.{' '}
<a
href="https://signoz.io/docs/manage/administrator-guide/configuration/impersonation-mode/"
target="_blank"
rel="noreferrer"
>
Learn more
</a>
</PersistedAnnouncementBanner>
);
}
export default NoAuthBanner;

View File

@@ -1,24 +0,0 @@
import { render, screen } from 'tests/test-utils';
import { NoAuthBanner } from '../NoAuthBanner';
describe('NoAuthBanner', () => {
it('renders the no-auth message', () => {
render(<NoAuthBanner />);
expect(
screen.getByText(/Impersonation mode: authentication is disabled/i),
).toBeInTheDocument();
});
it('renders with the warning test id', () => {
render(<NoAuthBanner />);
expect(screen.getByTestId('no-auth-banner')).toBeInTheDocument();
});
it('renders a docs link that opens in a new tab', () => {
render(<NoAuthBanner />);
const link = screen.getByRole('link', { name: /learn more/i });
expect(link).toHaveAttribute('target', '_blank');
expect(link).toHaveAttribute('rel', 'noreferrer');
});
});

View File

@@ -1,6 +1,6 @@
import { useEffect, useMemo, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useQuery } from 'react-query';
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
import { Select, Spin } from 'antd';
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
import { QueryKeyDataSuggestionsProps } from 'types/api/querySuggestions/types';
import { DataSource } from 'types/common/queryBuilder';
@@ -13,25 +13,48 @@ interface ListViewOrderByProps {
dataSource: DataSource;
}
// Loader component for the dropdown when loading or no results
function Loader({ isLoading }: { isLoading: boolean }): JSX.Element {
return (
<div className="order-by-loading-container">
{isLoading ? <Spin size="default" /> : 'No results found'}
</div>
);
}
function ListViewOrderBy({
value,
onChange,
dataSource,
}: ListViewOrderByProps): JSX.Element {
const [selectOptions, setSelectOptions] = useState<ComboboxSimpleItem[]>([]);
const [searchInput, setSearchInput] = useState('');
const [debouncedInput, setDebouncedInput] = useState('');
const [selectOptions, setSelectOptions] = useState<
{ label: string; value: string }[]
>([]);
const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
// Fetch key suggestions once; ComboboxSimple handles local filtering.
// Fetch key suggestions based on debounced input
const { data, isLoading } = useQuery({
queryKey: ['orderByKeySuggestions', dataSource],
queryKey: ['orderByKeySuggestions', dataSource, debouncedInput],
queryFn: async () => {
const response = await getKeySuggestions({
signal: dataSource,
searchText: '',
searchText: debouncedInput,
});
return response.data;
},
});
useEffect(
() => (): void => {
if (debounceTimer.current) {
clearTimeout(debounceTimer.current);
}
},
[],
);
// Update options when API data changes
useEffect(() => {
const rawKeys: QueryKeyDataSuggestionsProps[] = data?.data?.keys
@@ -39,33 +62,52 @@ function ListViewOrderBy({
: [];
const keyNames = rawKeys.map((key) => key.name);
const uniqueKeys = [...new Set(['timestamp', ...keyNames])];
const uniqueKeys = [
...new Set(searchInput ? keyNames : ['timestamp', ...keyNames]),
];
const updatedOptions: ComboboxSimpleItem[] = uniqueKeys.flatMap((key) => [
const updatedOptions = uniqueKeys.flatMap((key) => [
{ label: `${key} (desc)`, value: `${key}:desc` },
{ label: `${key} (asc)`, value: `${key}:asc` },
]);
setSelectOptions(updatedOptions);
}, [data]);
}, [data, searchInput]);
const handleChange = useMemo(
() =>
(val: string | string[]): void => {
onChange(val as string);
},
[onChange],
);
// Handle search input with debounce
const handleSearch = (input: string): void => {
setSearchInput(input);
// Filter current options for instant client-side match
const filteredOptions = selectOptions.filter((option) =>
option.value.toLowerCase().includes(input.trim().toLowerCase()),
);
// If no match found or input is empty, trigger debounced fetch
if (filteredOptions.length === 0 || input === '') {
if (debounceTimer.current) {
clearTimeout(debounceTimer.current);
}
debounceTimer.current = setTimeout(() => {
setDebouncedInput(input);
}, 100);
}
};
return (
<ComboboxSimple
<Select
showSearch
value={value}
onChange={handleChange}
loading={isLoading}
onChange={onChange}
onSearch={handleSearch}
notFoundContent={<Loader isLoading={isLoading} />}
placeholder="Select a field"
style={{ width: 200 }}
items={selectOptions}
emptyPlaceholder="No results found"
options={selectOptions}
filterOption={(input, option): boolean =>
(option?.value ?? '').toLowerCase().includes(input.trim().toLowerCase())
}
/>
);
}

View File

@@ -22,37 +22,6 @@
border-right: none;
border-left: none;
--select-trigger-height: 2.25rem;
--select-trigger-background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
);
--select-trigger-border-color: var(
--query-builder-v2-border-color,
var(--l2-border)
);
--combobox-trigger-height: 2.25rem;
--combobox-trigger-padding: 7px var(--spacing-6);
--combobox-trigger-background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
);
--combobox-trigger-border-color: var(
--query-builder-v2-border-color,
var(--l2-border)
);
[data-slot='combobox-trigger'],
[data-slot='select-trigger'] {
color: var(--query-builder-v2-color, var(--l2-foreground));
}
[data-slot='combobox-placeholder'],
[data-slot='select-placeholder'] {
color: var(--query-builder-v2-placeholder-color, var(--l3-foreground));
}
.qb-content-container {
display: flex;
flex-direction: column;
@@ -111,8 +80,8 @@
width: 1px;
background: repeating-linear-gradient(
to bottom,
var(--query-builder-v2-border-color, var(--l2-border)),
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
var(--l1-border),
var(--l1-border) 4px,
transparent 4px,
transparent 8px
);
@@ -132,8 +101,7 @@
top: 12px;
width: 6px;
height: 6px;
border-left: 6px dotted
var(--query-builder-v2-border-color, var(--l2-border));
border-left: 6px dotted var(--l1-border);
}
/* Horizontal line pointing from vertical to the item */
@@ -146,8 +114,8 @@
height: 1px;
background: repeating-linear-gradient(
to right,
var(--query-builder-v2-border-color, var(--l2-border)),
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
var(--l1-border),
var(--l1-border) 4px,
transparent 4px,
transparent 8px
);
@@ -273,8 +241,7 @@
top: 12px;
width: 6px;
height: 6px;
border-left: 6px dotted
var(--query-builder-v2-border-color, var(--l2-border));
border-left: 6px dotted var(--l1-border);
}
/* Horizontal line pointing from vertical to the item */
@@ -287,8 +254,8 @@
height: 1px;
background: repeating-linear-gradient(
to right,
var(--query-builder-v2-border-color, var(--l2-border)),
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
var(--l1-border),
var(--l1-border) 4px,
transparent 4px,
transparent 8px
);
@@ -306,16 +273,6 @@
line-height: 16px; /* 128.571% */
resize: none;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
);
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
&:placeholder {
color: var(--query-builder-v2-placeholder-color, var(--l3-foreground));
}
}
.formula-legend {
@@ -325,30 +282,15 @@
.ant-input-group-addon {
border-top-left-radius: 0px !important;
border-top-right-radius: 0px !important;
background: var(
--query-builder-v2-background-color,
var(--l2-background)
);
color: var(--query-builder-v2-color, var(--l2-foreground));
background: var(--l2-background);
color: var(--l2-foreground);
font-size: 12px;
font-weight: 300;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
}
.ant-input {
border-top-left-radius: 0px !important;
border-top-right-radius: 0px !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
);
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
&:placeholder {
color: var(--query-builder-v2-placeholder-color, var(--l3-foreground));
}
}
}
}
@@ -381,8 +323,8 @@
width: 1px;
background: repeating-linear-gradient(
to bottom,
var(--query-builder-v2-border-color, var(--l2-border)),
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
var(--l1-border),
var(--l1-border) 4px,
transparent 4px,
transparent 8px
);
@@ -453,8 +395,8 @@
width: 1px;
background: repeating-linear-gradient(
to bottom,
var(--query-builder-v2-border-color, var(--l2-border)),
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
var(--l1-border),
var(--l1-border) 4px,
transparent 4px,
transparent 8px
);
@@ -470,7 +412,7 @@
min-width: 120px;
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
background: var(--l1-background);
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
@@ -515,7 +457,7 @@
.ant-select-selector {
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border)) !important;
border: 1px solid var(--l1-border) !important;
background: var(--l1-background) !important;
height: 34px !important;
box-sizing: border-box !important;

View File

@@ -57,7 +57,6 @@
.group-by-filter-container {
min-width: 340px !important;
--combobox-trigger-height: auto;
}
.metrics-aggregation-section-content-item {
@@ -147,3 +146,17 @@
}
}
}
.metrics-operators-select {
border-radius: 2px;
border: 1.005px solid var(--l1-border);
background: var(--l1-background);
color: var(--l1-foreground);
font-family: 'Geist Mono';
font-size: 13px;
font-style: normal;
font-weight: 400;
line-height: 20px; /* 142.857% */
letter-spacing: -0.07px;
}

View File

@@ -118,6 +118,7 @@ const MetricsAggregateSection = memo(function MetricsAggregateSection({
value={queryAggregation.timeAggregation || ''}
onChange={handleChangeOperator}
operators={operators}
className="metrics-operators-select"
/>
</div>
</div>

View File

@@ -6,13 +6,11 @@
gap: 8px;
width: 100%;
--select-trigger-width: auto;
.ant-select-selection-search-input {
font-size: 12px !important;
line-height: 25px;
line-height: 27px;
&::placeholder {
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
color: var(--l2-foreground) !important;
font-size: 12px !important;
}
}
@@ -24,9 +22,9 @@
.ant-select-selector {
width: 100%;
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border)) !important;
background: var(--query-builder-v2-background-color, var(--l2-background));
color: var(--query-builder-v2-color, var(--l2-foreground));
border: 1px solid var(--l1-border) !important;
background: var(--l1-background);
color: var(--l1-foreground);
font-family: 'Geist Mono';
font-size: 13px;
font-style: normal;
@@ -35,23 +33,20 @@
min-height: 36px;
.ant-select-selection-placeholder {
color: var(
--query-builder-v2-placeholder-color,
var(--l3-foreground)
) !important;
color: var(--l2-foreground) !important;
font-size: 12px !important;
}
}
.ant-select-dropdown {
border-radius: 4px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
background: var(--query-builder-v2-background-color, var(--l2-background));
border: 1px solid var(--l1-border);
background: var(--l1-background);
box-shadow: 4px 10px 16px 2px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(20px);
.ant-select-item {
color: var(--query-builder-v2-color, var(--l2-foreground));
color: var(--l1-foreground);
font-family: 'Geist Mono';
font-size: 13px;
font-style: normal;
@@ -60,18 +55,12 @@
&:hover,
&.ant-select-item-option-active {
background: var(
--query-builder-v2-selected-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
}
&.ant-select-item-option-selected {
background: var(
--query-builder-v2-selected-background-color,
var(--l3-background)
) !important;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
background: var(--l3-background) !important;
border: 1px solid var(--l1-border);
font-weight: 600;
}
}

View File

@@ -1,5 +1,5 @@
import { memo, useCallback, useMemo } from 'react';
import { SelectSimple, type SelectSimpleItem } from '@signozhq/ui/select';
import { Select } from 'antd';
import {
initialQueriesMap,
initialQueryMeterWithType,
@@ -10,6 +10,7 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useQueryOperations } from 'hooks/queryBuilder/useQueryBuilderOperations';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { SelectOption } from 'types/common/select';
import {
getPreviousQueryFromKey,
@@ -20,7 +21,7 @@ import {
import './MetricsSelect.styles.scss';
export const SOURCE_OPTIONS: SelectSimpleItem[] = [
export const SOURCE_OPTIONS: SelectOption<string, string>[] = [
{ value: 'metrics', label: 'Metrics' },
{ value: 'meter', label: 'Meter' },
];
@@ -139,14 +140,14 @@ export const MetricsSelect = memo(function MetricsSelect({
return (
<div className="metrics-source-select-container">
{signalSourceChangeEnabled && (
<SelectSimple
<Select
className="source-selector"
placeholder="Source"
items={SOURCE_OPTIONS}
options={SOURCE_OPTIONS}
value={source}
defaultValue="metrics"
testId={`metrics-source-selector-${index}`}
onChange={(value): void => handleSignalSourceChange(value as string)}
data-testid={`metrics-source-selector-${index}`}
onChange={handleSignalSourceChange}
/>
)}

View File

@@ -22,35 +22,34 @@
font-style: normal;
font-weight: var(--font-weight-normal);
color: var(--query-builder-v2-color, var(--l2-foreground));
color: var(--l2-foreground);
}
.tab {
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
border-left: none;
min-width: 120px;
height: 36px;
line-height: 36px;
&:first-child {
border-left: 1px solid
var(--query-builder-v2-border-color, var(--l2-border));
border-left: 1px solid var(--l1-border);
}
}
.tab::before {
background: var(--query-builder-v2-border-color, var(--l2-border));
background: var(--l1-border);
}
.selected-view {
color: var(--text-robin-500);
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
display: none;
}
.selected-view::before {
background: var(--query-builder-v2-border-color, var(--l2-border));
background: var(--l1-border);
}
}
@@ -59,7 +58,7 @@
height: 30px;
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
background: var(--l3-background);
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
}
@@ -72,13 +71,10 @@
align-items: center;
.having-filter-select-container {
position: relative;
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
background: var(--query-builder-v2-background-color, var(--l2-background));
padding-right: 38px;
align-items: center;
.having-filter-select-editor {
border-radius: 2px;
@@ -103,17 +99,15 @@
}
.cm-content {
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border-left-width: 0px;
border-right-width: 0px;
border-radius: 2px;
border: 1px solid var(--l1-border);
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
padding: 0px !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
background-color: var(--l2-background) !important;
&:focus-within {
border-color: var(--query-builder-v2-border-color, var(--l2-border));
border-color: var(--l1-border);
}
}
@@ -217,32 +211,17 @@
}
.cm-line {
min-height: 34px;
line-height: 32px !important;
line-height: 36px !important;
font-family: 'Space Mono', monospace !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
&,
.ͼ1a {
color: var(--query-builder-v2-color, var(--l2-foreground));
}
background-color: var(--l2-background) !important;
::-moz-selection {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
::selection {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
@@ -251,11 +230,8 @@
}
.chip-decorator {
background: var(
--query-builder-v2-chip-decorator-background-color,
var(--l3-background)
) !important;
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
background: var(--l3-background) !important;
color: var(--l1-foreground) !important;
border-radius: 4px;
padding: 2px 4px;
margin-right: 4px;
@@ -263,36 +239,24 @@
}
.cm-selectionBackground {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
.cm-activeLine > span {
font-size: 12px !important;
}
.cm-placeholder {
color: var(
--query-builder-v2-placeholder-color,
var(--l3-foreground)
) !important;
}
}
}
.close-btn {
position: absolute;
top: 0;
right: 0;
border-radius: 0px 2px 2px 0px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
background: var(--query-builder-v2-background-color, var(--l2-background));
height: 100%;
border: 1px solid var(--l2-border);
background: var(--l2-background);
height: 38px;
width: 38px;
border-left: transparent;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}

View File

@@ -23,7 +23,7 @@
flex: 1;
min-width: 0;
font-size: 12px;
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
color: var(--l2-foreground) !important;
&.error {
.cm-editor {
@@ -51,15 +51,14 @@
.cm-content {
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
padding: 0px !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
background-color: var(--l1-background) !important;
&:focus-within {
border-color: var(--query-builder-v2-border-color, var(--l2-border));
border-color: var(--l1-border);
}
}
@@ -75,7 +74,7 @@
right: 0px !important;
border-radius: 4px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
background: linear-gradient(
139deg,
color-mix(in srgb, var(--card) 80%, transparent) 0%,
@@ -119,7 +118,7 @@
box-sizing: border-box;
overflow: hidden;
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
color: var(--l2-foreground) !important;
font-family: 'Space Mono', monospace !important;
.cm-completionIcon {
@@ -128,10 +127,7 @@
&:hover,
&[aria-selected='true'] {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
color: var(--l1-foreground) !important;
font-weight: 600 !important;
}
@@ -146,24 +142,15 @@
.cm-line {
line-height: 36px !important;
font-family: 'Space Mono', monospace !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
background-color: var(--l2-background) !important;
::-moz-selection {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
::selection {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
@@ -172,11 +159,8 @@
}
.chip-decorator {
background: var(
--query-builder-v2-chip-decorator-background-color,
var(--l3-background)
) !important;
color: var(--query-builder-v2-color, var(--l1-foreground)) !important;
background: var(--l3-background) !important;
color: var(--l1-foreground) !important;
border-radius: 4px;
padding: 2px 4px;
margin-right: 4px;
@@ -184,10 +168,7 @@
}
.cm-selectionBackground {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
}
@@ -220,11 +201,12 @@
.close-btn {
border-radius: 0px 2px 2px 0px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
background: var(--query-builder-v2-background-color, var(--l2-background));
height: 100%;
border: 1px solid var(--l1-border);
background: var(--l1-background);
height: 38px;
width: 38px;
border-left: transparent;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
@@ -235,13 +217,13 @@
height: 36px;
line-height: 36px;
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
font-family: 'Space Mono', monospace !important;
&::placeholder {
color: var(--query-builder-v2-color, var(--l2-foreground));
color: var(--l1-foreground);
opacity: 0.5;
}
}
@@ -258,7 +240,7 @@
input {
max-width: 120px;
&::placeholder {
color: var(--query-builder-v2-color, var(--l2-foreground));
color: var(--l2-foreground);
}
}
}
@@ -269,8 +251,8 @@
.query-aggregation-error-popover {
.ant-popover-inner {
background-color: var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
background-color: var(--l1-border);
border: 1px solid var(--l1-border);
border-radius: 4px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
}

View File

@@ -1,7 +1,7 @@
.add-trace-operator-button,
.add-new-query-button,
.add-formula-button {
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
background: var(--query-builder-v2-background-color, var(--l2-background));
border: 1px solid var(--l1-border);
background: var(--l2-background);
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
}

View File

@@ -34,14 +34,11 @@
.query-status-container {
width: 32px;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
background-color: var(--l1-background) !important;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
border-radius: 2px;
border-top-left-radius: 0px !important;
border-bottom-left-radius: 0px !important;
@@ -80,16 +77,16 @@
.cm-content {
border-radius: 2px;
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
border: 1px solid var(--l1-border);
padding: 0px !important;
&:focus-within {
border-color: var(--query-builder-v2-border-color, var(--l2-border));
border-color: var(--l1-border);
}
}
&.cm-focused {
outline: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
outline: 1px solid var(--l1-border);
}
.cm-tooltip-autocomplete {
@@ -151,17 +148,11 @@
font-family: 'Space Mono', monospace !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
background-color: var(--l1-background) !important;
color: var(--l2-foreground) !important;
&:hover {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
}
.cm-completionIcon {
@@ -169,10 +160,7 @@
}
&[aria-selected='true'] {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
font-weight: 600 !important;
}
}
@@ -184,49 +172,25 @@
}
.cm-line {
line-height: 36px !important;
line-height: 34px !important;
font-family: 'Space Mono', monospace !important;
background-color: var(
--query-builder-v2-background-color,
var(--l2-background)
) !important;
&,
.ͼ1a {
color: var(--query-builder-v2-color, var(--l2-foreground));
}
background-color: var(--l2-background) !important;
::-moz-selection {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
::selection {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
}
.cm-selectionBackground {
background: var(
--query-builder-v2-selection-background-color,
var(--l3-background)
) !important;
background: var(--l3-background) !important;
opacity: 0.5 !important;
}
.cm-placeholder {
color: var(
--query-builder-v2-placeholder-color,
var(--l3-foreground)
) !important;
}
}
.cursor-position {

View File

@@ -14,8 +14,7 @@ import {
ComboboxList,
ComboboxTrigger,
} from '@signozhq/ui/combobox';
import { Skeleton, Tooltip } from 'antd';
import { Switch } from '@signozhq/ui/switch';
import { Skeleton, Switch, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import getLocalStorageKey from 'api/browser/localstorage/get';
import setLocalStorageKey from 'api/browser/localstorage/set';
@@ -282,8 +281,9 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
<div className="api-quick-filters-header">
<Typography.Text>Show IP addresses</Typography.Text>
<Switch
size="small"
style={{ marginLeft: 'auto' }}
value={showIP ?? true}
checked={showIP ?? true}
onChange={(checked): void => {
logEvent('API Monitoring: Show IP addresses clicked', {
showIP: checked,

View File

@@ -4,8 +4,7 @@ import type {
TableColumnsType as ColumnsType,
TableColumnType as ColumnType,
} from 'antd';
import { Button, Dropdown, Flex, MenuProps } from 'antd';
import { Switch } from '@signozhq/ui/switch';
import { Button, Dropdown, Flex, MenuProps, Switch } from 'antd';
import logEvent from 'api/common/logEvent';
import LaunchChatSupport from 'components/LaunchChatSupport/LaunchChatSupport';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
@@ -61,7 +60,9 @@ function DynamicColumnTable({
const onToggleHandler =
(index: number, column: ColumnGroupType<any> | ColumnType<any>) =>
(checked: boolean): void => {
(checked: boolean, event: React.MouseEvent<HTMLButtonElement>): void => {
event.stopPropagation();
if (shouldSendAlertsLogEvent) {
logEvent('Alert: Column toggled', {
column: column?.title,
@@ -87,14 +88,10 @@ function DynamicColumnTable({
const items: MenuProps['items'] =
dynamicColumns?.map((column, index) => ({
label: (
<div
className="dynamicColumnsTable-items"
onClick={(e): void => e.stopPropagation()}
role="presentation"
>
<div className="dynamicColumnsTable-items">
<div>{column.title?.toString()}</div>
<Switch
value={columnsData?.findIndex((c) => c.key === column.key) !== -1}
checked={columnsData?.findIndex((c) => c.key === column.key) !== -1}
onChange={onToggleHandler(index, column)}
/>
</div>

View File

@@ -1,10 +1,11 @@
import { CircleAlert, RefreshCw } from '@signozhq/icons';
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
import { Checkbox, Select } from 'antd';
import { convertToApiError } from 'api/ErrorResponseHandlerForGeneratedAPIs';
import { useListRoles } from 'api/generated/services/role';
import type { AuthtypesRoleDTO } from 'api/generated/services/sigNoz.schemas';
import cx from 'classnames';
import APIError from 'types/api/error';
import { popupContainer } from 'utils/selectPopupContainer';
import './RolesSelect.styles.scss';
@@ -73,6 +74,7 @@ interface BaseProps {
id?: string;
placeholder?: string;
className?: string;
getPopupContainer?: (trigger: HTMLElement) => HTMLElement;
roles?: AuthtypesRoleDTO[];
loading?: boolean;
isError?: boolean;
@@ -110,13 +112,14 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
});
const roles = externalRoles ?? data?.data ?? [];
const items: ComboboxSimpleItem[] = getRoleOptions(roles);
const options = getRoleOptions(roles);
const {
mode,
id,
placeholder = 'Select role',
className,
getPopupContainer = popupContainer,
loading = internalLoading,
isError = internalError,
error = convertToApiError(internalErrorObj),
@@ -124,47 +127,55 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
disabled,
} = props;
const emptyPlaceholder = isError
? error?.message || 'Failed to load roles'
: 'No roles available';
const notFoundContent = isError ? (
<ErrorContent error={error} onRefetch={onRefetch} />
) : undefined;
if (mode === 'multiple') {
const { value = [], onChange } = props as MultipleProps;
return (
<>
<ComboboxSimple
id={id}
multiple
value={value}
onChange={(v): void => onChange?.(v as string[])}
placeholder={placeholder}
className={cx('roles-select', className)}
loading={loading}
emptyPlaceholder={emptyPlaceholder}
items={items}
style={disabled ? { pointerEvents: 'none', opacity: 0.5 } : undefined}
/>
{isError && <ErrorContent error={error} onRefetch={onRefetch} />}
</>
<Select
id={id}
mode="multiple"
value={value}
onChange={onChange}
placeholder={placeholder}
className={cx('roles-select', className)}
loading={loading}
notFoundContent={notFoundContent}
options={options}
optionFilterProp="label"
optionRender={(option): JSX.Element => (
<Checkbox
checked={value.includes(option.value as string)}
style={{ pointerEvents: 'none' }}
>
{option.label}
</Checkbox>
)}
getPopupContainer={getPopupContainer}
disabled={disabled}
/>
);
}
const { value, onChange } = props as SingleProps;
const { value, onChange, allowClear = true } = props as SingleProps;
return (
<>
<ComboboxSimple
id={id}
value={value || undefined}
onChange={(v): void => onChange?.((v as string) || undefined)}
placeholder={placeholder}
className={cx('roles-single-select', className)}
loading={loading}
emptyPlaceholder={emptyPlaceholder}
items={items}
style={disabled ? { pointerEvents: 'none', opacity: 0.5 } : undefined}
/>
{isError && <ErrorContent error={error} onRefetch={onRefetch} />}
</>
<Select
id={id}
showSearch
value={value || undefined}
onChange={onChange}
placeholder={placeholder}
allowClear={allowClear}
className={cx('roles-single-select', className)}
loading={loading}
notFoundContent={notFoundContent}
options={options}
optionFilterProp="label"
getPopupContainer={getPopupContainer}
disabled={disabled}
/>
);
}

View File

@@ -127,6 +127,7 @@ function KeyFormPhase({
>
<Button
type="submit"
// @ts-expect-error -- form prop not in @signozhq/ui Button type - TODO: Fix this - @SagarRajput
form={FORM_ID}
variant="solid"
color="primary"

View File

@@ -190,6 +190,7 @@ function EditKeyForm({
>
<Button
type="submit"
// @ts-expect-error -- form prop not in @signozhq/ui Button type - TODO: Fix this - @SagarRajput
form={FORM_ID}
variant="solid"
color="primary"

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo } from 'react';
import { KeyRound, X } from '@signozhq/icons';
import { Button } from '@signozhq/ui/button';
import { Skeleton, Table, Tooltip } from 'antd';
import { Skeleton, Table } from 'antd';
import type { ColumnsType } from 'antd/es/table/interface';
import type { ServiceaccounttypesGettableFactorAPIKeyDTO } from 'api/generated/services/sigNoz.schemas';
import AuthZTooltip from 'components/AuthZTooltip/AuthZTooltip';
@@ -110,34 +110,28 @@ function buildColumns({
onClick: (e): void => e.stopPropagation(),
style: { cursor: 'default' },
}),
render: (_, record): JSX.Element => {
const tooltipTitle = isDisabled ? 'Service account disabled' : 'Revoke Key';
return (
<AuthZTooltip
checks={[
buildAPIKeyDeletePermission(record.id),
buildSADetachPermission(accountId),
]}
enabled={!isDisabled && !!accountId}
render: (_, record): JSX.Element => (
<AuthZTooltip
checks={[
buildAPIKeyDeletePermission(record.id),
buildSADetachPermission(accountId),
]}
enabled={!isDisabled && !!accountId}
>
<Button
variant="ghost"
size="sm"
color="destructive"
disabled={isDisabled}
onClick={(): void => {
onRevokeClick(record.id);
}}
className="keys-tab__revoke-btn"
>
<Tooltip title={tooltipTitle}>
<Button
variant="ghost"
size="sm"
color="destructive"
disabled={isDisabled}
onClick={(e): void => {
e.stopPropagation();
onRevokeClick(record.id);
}}
className="keys-tab__revoke-btn"
>
<X size={12} />
</Button>
</Tooltip>
</AuthZTooltip>
);
},
<X size={12} />
</Button>
</AuthZTooltip>
),
},
];
}

View File

@@ -1,11 +1,7 @@
import { useMemo } from 'react';
import { SolidAlertTriangle } from '@signozhq/icons';
import {
ComboboxSimple,
ComboboxSimpleGroup,
ComboboxSimpleItem,
} from '@signozhq/ui/combobox';
import { Tooltip } from 'antd';
import { Select, Tooltip } from 'antd';
import type { DefaultOptionType } from 'antd/es/select';
import classNames from 'classnames';
import { UniversalYAxisUnitMappings } from './constants';
@@ -46,53 +42,69 @@ function YAxisUnitSelector({
return '';
}, [initialValue, value, loading]);
const categoriesToRender = useMemo(
() => categoriesOverride || getYAxisCategories(source),
[categoriesOverride, source],
);
const handleSearch = (
searchTerm: string,
currentOption: DefaultOptionType | undefined,
): boolean => {
if (!currentOption?.value) {
return false;
}
const groups: ComboboxSimpleGroup[] = useMemo(
() =>
categoriesToRender.map((category) => ({
heading: category.name,
items: category.units.map((unit): ComboboxSimpleItem => {
const aliases = Array.from(
UniversalYAxisUnitMappings[unit.id as UniversalYAxisUnit] ?? [],
);
return {
value: unit.id,
label: unit.name,
keywords: aliases,
};
}),
})),
[categoriesToRender],
);
const search = searchTerm.toLowerCase();
const unitId = currentOption.value.toString().toLowerCase();
const unitLabel = currentOption.children?.toString().toLowerCase() || '';
const handleChange = (val: string | string[]): void => {
onChange(val as UniversalYAxisUnit);
// Check label and id
if (unitId.includes(search) || unitLabel.includes(search)) {
return true;
}
// Check aliases (from the mapping) using array iteration
const aliases = Array.from(
UniversalYAxisUnitMappings[currentOption.value as UniversalYAxisUnit] ?? [],
);
return aliases.some((alias) => alias.toLowerCase().includes(search));
};
const categoriesToRender = useMemo(() => {
return categoriesOverride || getYAxisCategories(source);
}, [categoriesOverride, source]);
return (
<div
className={classNames('y-axis-unit-selector-component', containerClassName)}
>
<ComboboxSimple
value={universalUnit ?? undefined}
onChange={handleChange}
<Select
showSearch
value={universalUnit}
onChange={onChange}
placeholder={placeholder}
filterOption={(input, option): boolean => handleSearch(input, option)}
loading={loading}
suffixIcon={
incompatibleUnitMessage ? (
<Tooltip title={incompatibleUnitMessage}>
<SolidAlertTriangle role="img" aria-label="warning" size="md" />
</Tooltip>
) : undefined
}
className={classNames({
'warning-state': !!incompatibleUnitMessage,
'warning-state': incompatibleUnitMessage,
})}
testId={dataTestId}
groups={groups}
/>
{incompatibleUnitMessage && (
<Tooltip title={incompatibleUnitMessage}>
<SolidAlertTriangle role="img" aria-label="warning" size="md" />
</Tooltip>
)}
data-testid={dataTestId}
allowClear
>
{categoriesToRender.map((category) => (
<Select.OptGroup key={category.name} label={category.name}>
{category.units.map((unit) => (
<Select.Option key={unit.id} value={unit.id}>
{unit.name}
</Select.Option>
))}
</Select.OptGroup>
))}
</Select>
</div>
);
}

View File

@@ -1,8 +1,5 @@
.y-axis-unit-selector-component {
--combobox-trigger-background-color: var(--l2-background);
--combobox-trigger-border-color: var(--l2-border);
[data-slot='combobox-trigger'] {
.ant-select {
width: 220px;
}
}

View File

@@ -204,7 +204,7 @@ describe('createGuardedRoute', () => {
).not.toBeInTheDocument();
});
it('should render the component when API error occurs (fail open)', async () => {
it('should render error fallback when API error occurs', async () => {
server.use(
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
@@ -230,8 +230,12 @@ describe('createGuardedRoute', () => {
render(<GuardedComponent {...props} />);
await waitFor(() => {
expect(screen.getByText('Test Component: test-value')).toBeInTheDocument();
expect(screen.getByText(/Something went wrong/i)).toBeInTheDocument();
});
expect(
screen.queryByText('Test Component: test-value'),
).not.toBeInTheDocument();
});
it('should render no permissions fallback when permission is denied', async () => {

View File

@@ -9,11 +9,14 @@ import { parsePermission } from 'hooks/useAuthZ/utils';
import noDataUrl from '@/assets/Icons/no-data.svg';
import ErrorBoundaryFallback from '../../pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import AppLoading from '../AppLoading/AppLoading';
import { GuardAuthZ } from '../GuardAuthZ/GuardAuthZ';
import './createGuardedRoute.styles.scss';
const onErrorFallback = (): JSX.Element => <ErrorBoundaryFallback />;
function OnNoPermissionsFallback(response: {
requiredPermissionName: BrandedPermission;
}): ReactElement {
@@ -60,6 +63,7 @@ export function createGuardedRoute<P extends object, R extends AuthZRelation>(
relation={relation}
object={resolvedObject}
fallbackOnLoading={<AppLoading />}
fallbackOnError={onErrorFallback}
fallbackOnNoPermissions={(response): ReactElement => (
<OnNoPermissionsFallback {...response} />
)}

View File

@@ -45,10 +45,6 @@
.contributors-row {
height: 80px;
}
.top-contributors-progress {
--progress-background: transparent;
}
&__content {
.ant-table {
&-cell {

View File

@@ -1,7 +1,6 @@
import { HTMLAttributes } from 'react';
import { Color } from '@signozhq/design-tokens';
import { Table, TableColumnsType as ColumnsType } from 'antd';
import { Progress } from '@signozhq/ui/progress';
import { Progress, Table, TableColumnsType as ColumnsType } from 'antd';
import logEvent from 'api/common/logEvent';
import { ConditionalAlertPopover } from 'container/AlertHistory/AlertPopover/AlertPopover';
import AlertLabels from 'pages/AlertDetails/AlertHeader/AlertLabels/AlertLabels';
@@ -52,8 +51,8 @@ function TopContributorsRows({
<Progress
percent={(count / totalCurrentTriggers) * 100}
showInfo={false}
trailColor="rgba(255, 255, 255, 0)"
strokeColor={Color.BG_ROBIN_500}
className="top-contributors-progress"
/>
</ConditionalAlertPopover>
),

View File

@@ -1,5 +1,5 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { ComboboxSimple } from '@signozhq/ui/combobox';
import { Select } from 'antd';
import { ENTITY_VERSION_V5 } from 'constants/app';
import { initialQueriesMap } from 'constants/queryBuilder';
import {
@@ -115,11 +115,11 @@ function AllEndPoints({
// --- GROUP BY STATE SYNC (existing) ---
const handleGroupByChange = useCallback(
(value: string[]) => {
(value: IBuilderQuery['groupBy']) => {
const newGroupBy = [];
for (let index = 0; index < value.length; index++) {
const element = value[index];
const element = value[index] as unknown as string;
// Check if the key exists in our cached options first
if (allAvailableGroupByOptions[element]) {
@@ -242,14 +242,17 @@ function AllEndPoints({
</div>
<div className="group-by-container">
<div className="group-by-label"> Group by </div>
<ComboboxSimple
<Select
className="group-by-select"
loading={isLoadingGroupByFilters}
multiple
value={groupBy.map((g) => g.key)}
mode="multiple"
value={groupBy}
allowClear
maxTagCount="responsive"
placeholder="Search for attribute"
items={groupByOptions}
onChange={(value): void => handleGroupByChange(value as string[])}
options={groupByOptions}
onChange={handleGroupByChange}
onSearch={(value: string): void => setGroupBySearchValue(value)}
/>{' '}
</div>
<div className="endpoints-table-container">

View File

@@ -141,9 +141,12 @@
.progress-container {
width: 158px;
.ant-progress {
margin: 0;
span {
font-weight: 600;
.ant-progress-text {
font-weight: 600;
}
}
}
@@ -211,14 +214,14 @@
.group-by-label {
display: flex;
padding: 4px 15px;
padding: 6px 15px;
justify-content: center;
align-items: center;
gap: 4px;
flex-shrink: 0;
border-radius: 2px 0px 0px 2px;
border: 1px solid var(--l2-border);
border: 1px solid var(--l1-border);
border-right: none;
background: var(--l3-background);
@@ -227,15 +230,18 @@
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
line-height: 18px;
letter-spacing: -0.07px;
}
.group-by-select {
width: 100%;
box-sizing: border-box;
--combobox-trigger-border-radius: 0px;
.ant-select-selector {
font-size: 14px;
border-radius: 2px 0px 0px 2px;
border: 1px solid var(--l1-border);
background: var(--l3-background);
}
}
}
// Add border-bottom to table cells when pagination is not present
@@ -458,13 +464,14 @@
}
.endpoint-details-filters-container-dropdown {
width: 150px;
width: 120px;
border-right: 1px solid var(--l1-border);
height: 36px;
display: flex;
align-items: center;
--combobox-trigger-border-color: transparent;
.ant-select-single {
height: 32px;
}
}
.endpoint-details-filters-container-search {

View File

@@ -263,6 +263,7 @@ function EndPointDetails({
setSelectedEndPointName={setSelectedEndPointName}
endPointDropDownDataQuery={endPointDropDownDataQuery}
parentContainerDiv=".endpoint-details-filters-container"
dropdownStyle={{ width: 'calc(100% - 36px)' }}
/>
</div>
<div className="endpoint-details-filters-container-search">

View File

@@ -1,8 +1,7 @@
import { useMemo, useState } from 'react';
import { QueryFunctionContext, useQueries, useQuery } from 'react-query';
import { Spin, Table, Tooltip } from 'antd';
import { Spin, Switch, Table, Tooltip } from 'antd';
import { Info, Loader } from '@signozhq/icons';
import { Switch } from '@signozhq/ui/switch';
import { Typography } from '@signozhq/ui/typography';
import { getQueryRangeV5 } from 'api/v5/queryRange/getQueryRange';
import { MetricRangePayloadV5, ScalarData } from 'api/v5/v5';
@@ -171,7 +170,11 @@ function TopErrors({
/>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<Switch value={showStatusCodeErrors} onChange={setShowStatusCodeErrors} />
<Switch
checked={showStatusCodeErrors}
onChange={setShowStatusCodeErrors}
size="small"
/>
<span style={{ color: 'white', fontSize: '14px' }}>
Status Message Exists
</span>

View File

@@ -1,8 +1,7 @@
import { useMemo } from 'react';
import { useQueries } from 'react-query';
import { Color } from '@signozhq/design-tokens';
import { Skeleton, Tooltip } from 'antd';
import { Progress } from '@signozhq/ui/progress';
import { Progress, Skeleton, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { ENTITY_VERSION_V5 } from 'constants/app';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
@@ -137,11 +136,12 @@ function DomainMetrics({
<Tooltip title={formattedDomainMetricsData.errorRate}>
{formattedDomainMetricsData.errorRate !== '-' ? (
<Progress
status="active"
percent={Number(
Number(formattedDomainMetricsData.errorRate).toFixed(2),
)}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const errorRatePercent = Number(
Number(formattedDomainMetricsData.errorRate).toFixed(2),

View File

@@ -1,8 +1,7 @@
import { useMemo } from 'react';
import { UseQueryResult } from 'react-query';
import { Color } from '@signozhq/design-tokens';
import { Skeleton, Tooltip } from 'antd';
import { Progress } from '@signozhq/ui/progress';
import { Progress, Skeleton, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import {
getDisplayValue,
@@ -81,9 +80,10 @@ function EndPointMetrics({
<Tooltip title={metricsData?.errorRate}>
{metricsData?.errorRate !== '-' ? (
<Progress
status="active"
percent={Number(Number(metricsData?.errorRate ?? 0).toFixed(2))}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const errorRatePercent = Number(
Number(metricsData?.errorRate ?? 0).toFixed(2),

View File

@@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { UseQueryResult } from 'react-query';
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
import { Select } from 'antd';
import { getFormattedEndPointDropDownData } from 'container/ApiMonitoring/utils';
import { SuccessResponse } from 'types/api';
@@ -22,33 +22,40 @@ function EndPointsDropDown({
selectedEndPointName,
setSelectedEndPointName,
endPointDropDownDataQuery,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
parentContainerDiv: _parentContainerDiv,
parentContainerDiv,
dropdownStyle,
}: EndPointsDropDownProps): JSX.Element {
const { data, isLoading, isFetching } = endPointDropDownDataQuery;
const handleChange = (value: string | string[]): void => {
setSelectedEndPointName(value as string);
const handleChange = (value: string): void => {
setSelectedEndPointName(value);
};
const formattedData = useMemo(
() =>
getFormattedEndPointDropDownData(
data?.payload.data.result[0].table.rows,
) as ComboboxSimpleItem[],
getFormattedEndPointDropDownData(data?.payload.data.result[0].table.rows),
[data?.payload.data.result],
);
return (
<ComboboxSimple
<Select
value={selectedEndPointName || undefined}
placeholder="Select endpoint"
loading={isLoading || isFetching}
style={{ width: '100%', ...dropdownStyle }}
style={{ width: '100%' }}
onChange={handleChange}
items={formattedData}
virtualized
options={formattedData}
getPopupContainer={
parentContainerDiv
? (): HTMLElement =>
document.querySelector(parentContainerDiv) as HTMLElement
: (triggerNode): HTMLElement => triggerNode.parentNode as HTMLElement
}
dropdownStyle={dropdownStyle}
allowClear
onClear={(): void => {
setSelectedEndPointName('');
}}
/>
);
}

View File

@@ -1,7 +1,6 @@
import { ReactNode } from 'react';
import { Color } from '@signozhq/design-tokens';
import { TableColumnType as ColumnType, Tag, Tooltip } from 'antd';
import { Progress } from '@signozhq/ui/progress';
import { Progress, TableColumnType as ColumnType, Tag, Tooltip } from 'antd';
import { convertFiltersToExpressionWithExistingQuery } from 'components/QueryBuilderV2/utils';
import {
FiltersType,
@@ -258,9 +257,10 @@ export const columnsConfig: ColumnType<APIDomainsRowData>[] = [
errorRate === 'n/a' || errorRate === '-' ? 0 : errorRate;
return (
<Progress
status="active"
percent={Number((errorRateValue as number).toFixed(2))}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const errorRatePercent = Number((errorRateValue as number).toFixed(2));
if (errorRatePercent >= 90) {
@@ -1022,13 +1022,14 @@ export const getEndPointsColumnsConfig = (
className: `column`,
render: (errorRate: number | string): React.ReactNode => (
<Progress
status="active"
percent={Number(
(
(errorRate === 'n/a' || errorRate === '-' ? 0 : errorRate) as number
).toFixed(1),
)}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const errorRatePercent = Number((errorRate as number).toFixed(1));
if (errorRatePercent >= 90) {
@@ -2513,9 +2514,10 @@ export const dependentServicesColumns: ColumnType<DependentServicesData>[] = [
render: (errorPercentage: number | string): React.ReactNode =>
errorPercentage !== '-' ? (
<Progress
status="active"
percent={Number((errorPercentage as number).toFixed(2))}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const errorPercentagePercent = Number(
(errorPercentage as number).toFixed(2),
@@ -3020,13 +3022,14 @@ export const getAllEndpointsWidgetData = (
),
F1: (errorRate: any): ReactNode => (
<Progress
status="active"
percent={Number(
(
(errorRate === 'n/a' || errorRate === '-' ? 0 : errorRate) as number
).toFixed(2),
)}
strokeLinecap="butt"
showInfo
size="small"
strokeColor={((): string => {
const errorRatePercent = Number(
(

View File

@@ -1,8 +1,8 @@
import { memo, useMemo } from 'react';
import { ChevronLeft, ChevronRight } from '@signozhq/icons';
import { SelectSimple } from '@signozhq/ui/select';
import { Button, Flex } from 'antd';
import { Button, Flex, Select } from 'antd';
import { DEFAULT_PER_PAGE_OPTIONS, Pagination } from 'hooks/queryPagination';
import { popupContainer } from 'utils/selectPopupContainer';
import { defaultSelectStyle } from './config';
import { Container } from './styles';
@@ -59,18 +59,20 @@ function Controls({
</Button>
{showSizeChanger && (
<SelectSimple
<Select<Pagination['limit']>
style={defaultSelectStyle}
disabled={isLoading}
value={String(countPerPage)}
onChange={(value): void =>
handleCountItemsPerPageChange(Number(value) as Pagination['limit'])
}
items={perPageOptions.map((count) => ({
value: String(count),
label: `${count} / page`,
}))}
/>
loading={isLoading}
value={countPerPage}
onChange={handleCountItemsPerPageChange}
getPopupContainer={popupContainer}
>
{perPageOptions.map((count) => (
<Select.Option
key={count}
value={count}
>{`${count} / page`}</Select.Option>
))}
</Select>
)}
</Container>
);

View File

@@ -61,6 +61,10 @@
margin-left: 16px;
}
&:not(:first-of-type) {
margin-left: 24px !important;
}
[aria-selected='false'] {
.periscope-tab {
color: var(--l2-foreground);

View File

@@ -1,6 +1,5 @@
import { useEffect } from 'react';
import { Button, Tooltip } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Button, Select, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import classNames from 'classnames';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
@@ -232,18 +231,15 @@ function AlertThreshold({
<Typography.Text className="sentence-text">
Send a notification when
</Typography.Text>
<SelectSimple
<Select
value={thresholdState.selectedQuery}
onChange={(value): void => handleSelectedQueryChange(value as string)}
onChange={handleSelectedQueryChange}
style={{ width: 80 }}
items={queryNames.map((q) => ({
value: String(q.value),
label: q.label as React.ReactNode,
}))}
options={queryNames}
data-testid="alert-threshold-query-select"
/>
<Typography.Text className="sentence-text">is</Typography.Text>
<SelectSimple
<Select
value={
(normalizeOperator(thresholdState.operator) ??
thresholdState.operator) as AlertThresholdOperator
@@ -251,17 +247,17 @@ function AlertThreshold({
onChange={(value): void => {
setThresholdState({
type: 'SET_OPERATOR',
payload: value as AlertThresholdOperator,
payload: value,
});
}}
style={{ width: 180 }}
items={THRESHOLD_OPERATOR_OPTIONS}
options={THRESHOLD_OPERATOR_OPTIONS}
data-testid="alert-threshold-operator-select"
/>
<Typography.Text className="sentence-text">
the threshold(s)
</Typography.Text>
<SelectSimple
<Select
value={
(normalizeMatchType(thresholdState.matchType) ??
thresholdState.matchType) as AlertThresholdMatchType
@@ -269,11 +265,11 @@ function AlertThreshold({
onChange={(value): void => {
setThresholdState({
type: 'SET_MATCH_TYPE',
payload: value as AlertThresholdMatchType,
payload: value,
});
}}
style={{ width: 180 }}
items={matchTypeOptionsWithTooltips}
options={matchTypeOptionsWithTooltips}
data-testid="alert-threshold-match-type-select"
/>
<Typography.Text className="sentence-text">

View File

@@ -1,8 +1,8 @@
import { useMemo } from 'react';
import { ComboboxSimple } from '@signozhq/ui/combobox';
import { SelectSimple } from '@signozhq/ui/select';
import { Select } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useAppContext } from 'providers/App/App';
import { useCreateAlertState } from '../context';
import {
@@ -18,13 +18,19 @@ import {
} from '../context/types';
import { normalizeMatchType, normalizeOperator } from '../utils';
import { AnomalyAndThresholdProps } from './types';
import { getQueryNames, RoutingPolicyBanner } from './utils';
import {
getQueryNames,
NotificationChannelsNotFoundContent,
RoutingPolicyBanner,
} from './utils';
function AnomalyThreshold({
channels,
isLoadingChannels,
isErrorChannels,
refreshChannels,
}: AnomalyAndThresholdProps): JSX.Element {
const { user } = useAppContext();
const {
thresholdState,
setThresholdState,
@@ -36,14 +42,13 @@ function AnomalyThreshold({
const queryNames = getQueryNames(currentQuery);
const deviationOptions = useMemo(
() =>
Array.from({ length: 7 }, (_, i) => ({
label: (i + 1).toString(),
value: (i + 1).toString(),
})),
[],
);
const deviationOptions = useMemo(() => {
const options = [];
for (let i = 1; i <= 7; i++) {
options.push({ label: i.toString(), value: i });
}
return options;
}, []);
const updateThreshold = (
id: string,
@@ -66,16 +71,16 @@ function AnomalyThreshold({
<Typography.Text data-testid="notification-text" className="sentence-text">
Send notification when the observed value for
</Typography.Text>
<SelectSimple
<Select
value={thresholdState.selectedQuery}
testId="query-select"
data-testid="query-select"
onChange={(value): void => {
setThresholdState({
type: 'SET_SELECTED_QUERY',
payload: value as string,
payload: value,
});
}}
items={queryNames}
options={queryNames}
/>
<Typography.Text
data-testid="evaluation-window-text"
@@ -83,16 +88,16 @@ function AnomalyThreshold({
>
during the last
</Typography.Text>
<SelectSimple
<Select
value={thresholdState.evaluationWindow}
testId="evaluation-window-select"
data-testid="evaluation-window-select"
onChange={(value): void => {
setThresholdState({
type: 'SET_EVALUATION_WINDOW',
payload: value as string,
payload: value,
});
}}
items={ANOMALY_TIME_DURATION_OPTIONS}
options={ANOMALY_TIME_DURATION_OPTIONS}
/>
</div>
<div className="alert-condition-sentence">
@@ -100,34 +105,34 @@ function AnomalyThreshold({
<Typography.Text data-testid="threshold-text" className="sentence-text">
is
</Typography.Text>
<SelectSimple
value={thresholdState.thresholds[0].thresholdValue?.toString()}
testId="threshold-value-select"
<Select
value={thresholdState.thresholds[0].thresholdValue}
data-testid="threshold-value-select"
onChange={(value): void => {
updateThreshold(
thresholdState.thresholds[0].id,
'thresholdValue',
(value as string).toString(),
value.toString(),
);
}}
items={deviationOptions}
options={deviationOptions}
/>
<Typography.Text data-testid="deviations-text" className="sentence-text">
deviations
</Typography.Text>
<SelectSimple
<Select
value={
(normalizeOperator(thresholdState.operator) ??
thresholdState.operator) as AlertThresholdOperator
}
testId="operator-select"
data-testid="operator-select"
onChange={(value): void => {
setThresholdState({
type: 'SET_OPERATOR',
payload: value as AlertThresholdOperator,
payload: value,
});
}}
items={ANOMALY_THRESHOLD_OPERATOR_OPTIONS}
options={ANOMALY_THRESHOLD_OPERATOR_OPTIONS}
/>
<Typography.Text
data-testid="predicted-data-text"
@@ -135,19 +140,19 @@ function AnomalyThreshold({
>
the predicted data
</Typography.Text>
<SelectSimple
<Select
value={
(normalizeMatchType(thresholdState.matchType) ??
thresholdState.matchType) as AlertThresholdMatchType
}
testId="match-type-select"
data-testid="match-type-select"
onChange={(value): void => {
setThresholdState({
type: 'SET_MATCH_TYPE',
payload: value as AlertThresholdMatchType,
payload: value,
});
}}
items={ANOMALY_THRESHOLD_MATCH_TYPE_OPTIONS}
options={ANOMALY_THRESHOLD_MATCH_TYPE_OPTIONS}
/>
</div>
{/* Sentence 3 */}
@@ -155,16 +160,16 @@ function AnomalyThreshold({
<Typography.Text data-testid="using-the-text" className="sentence-text">
using the
</Typography.Text>
<SelectSimple
<Select
value={thresholdState.algorithm}
testId="algorithm-select"
data-testid="algorithm-select"
onChange={(value): void => {
setThresholdState({
type: 'SET_ALGORITHM',
payload: value as string,
payload: value,
});
}}
items={ANOMALY_ALGORITHM_OPTIONS}
options={ANOMALY_ALGORITHM_OPTIONS}
/>
<Typography.Text
data-testid="algorithm-with-text"
@@ -172,16 +177,16 @@ function AnomalyThreshold({
>
algorithm with
</Typography.Text>
<SelectSimple
<Select
value={thresholdState.seasonality}
testId="seasonality-select"
data-testid="seasonality-select"
onChange={(value): void => {
setThresholdState({
type: 'SET_SEASONALITY',
payload: value as string,
payload: value,
});
}}
items={ANOMALY_SEASONALITY_OPTIONS}
options={ANOMALY_SEASONALITY_OPTIONS}
/>
{notificationSettings.routingPolicies ? (
<>
@@ -191,25 +196,35 @@ function AnomalyThreshold({
>
seasonality to
</Typography.Text>
<ComboboxSimple
<Select
value={thresholdState.thresholds[0].channels}
onChange={(value): void =>
updateThreshold(
thresholdState.thresholds[0].id,
'channels',
value as string[],
)
updateThreshold(thresholdState.thresholds[0].id, 'channels', value)
}
style={{ width: 350 }}
items={channels.map((channel) => ({
options={channels.map((channel) => ({
value: channel.id,
label: channel.name,
}))}
multiple
mode="multiple"
placeholder="Select notification channels"
loading={isLoadingChannels}
className={isErrorChannels ? 'error' : undefined}
emptyPlaceholder="No channels found"
showSearch
maxTagCount={2}
maxTagPlaceholder={(omittedValues): string =>
`+${omittedValues.length} more`
}
maxTagTextLength={10}
filterOption={(input, option): boolean =>
option?.label?.toLowerCase().includes(input.toLowerCase()) || false
}
status={isErrorChannels ? 'error' : undefined}
disabled={isLoadingChannels}
notFoundContent={
<NotificationChannelsNotFoundContent
user={user}
refreshChannels={refreshChannels}
/>
}
/>
</>
) : (

View File

@@ -1,14 +1,14 @@
import { useMemo, useState } from 'react';
import { Button, Input, Tooltip } from 'antd';
import { ComboboxSimple } from '@signozhq/ui/combobox';
import { SelectSimple } from '@signozhq/ui/select';
import { Button, Input, Select, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { CircleX, Trash } from '@signozhq/icons';
import { useAppContext } from 'providers/App/App';
import { useCreateAlertState } from '../context';
import { AlertThresholdOperator } from '../context/types';
import { normalizeOperator } from '../utils';
import { ThresholdItemProps } from './types';
import { NotificationChannelsNotFoundContent } from './utils';
function ThresholdItem({
threshold,
@@ -18,38 +18,36 @@ function ThresholdItem({
channels,
units,
isErrorChannels,
refreshChannels,
isLoadingChannels,
}: ThresholdItemProps): JSX.Element {
const { user } = useAppContext();
const { thresholdState, notificationSettings } = useCreateAlertState();
const [showRecoveryThreshold, setShowRecoveryThreshold] = useState(false);
const yAxisUnitSelect = useMemo(() => {
let component = (
<SelectSimple
<Select
placeholder="Unit"
value={threshold.unit ? threshold.unit : undefined}
onChange={(value): void =>
updateThreshold(threshold.id, 'unit', value as string)
}
value={threshold.unit ? threshold.unit : null}
onChange={(value): void => updateThreshold(threshold.id, 'unit', value)}
style={{ width: 150 }}
items={units}
options={units}
disabled={units.length === 0}
testId="threshold-unit-select"
data-testid="threshold-unit-select"
/>
);
if (units.length === 0) {
component = (
<Tooltip trigger="hover" title="No compatible units available">
<SelectSimple
<Select
placeholder="Unit"
value={threshold.unit ? threshold.unit : undefined}
onChange={(value): void =>
updateThreshold(threshold.id, 'unit', value as string)
}
value={threshold.unit ? threshold.unit : null}
onChange={(value): void => updateThreshold(threshold.id, 'unit', value)}
style={{ width: 150 }}
items={units}
options={units}
disabled={units.length === 0}
testId="threshold-unit-select"
data-testid="threshold-unit-select"
/>
</Tooltip>
);
@@ -119,22 +117,37 @@ function ThresholdItem({
{!notificationSettings.routingPolicies && (
<>
<Typography.Text className="sentence-text">send to</Typography.Text>
<ComboboxSimple
<Select
value={threshold.channels}
onChange={(value): void =>
updateThreshold(threshold.id, 'channels', value as string[])
updateThreshold(threshold.id, 'channels', value)
}
testId="threshold-notification-channel-select"
data-testid="threshold-notification-channel-select"
style={{ width: 350 }}
items={channels.map((channel) => ({
options={channels.map((channel) => ({
value: channel.name,
label: channel.name,
'data-testid': `threshold-notification-channel-option-${threshold.label}`,
}))}
multiple
mode="multiple"
placeholder="Select notification channels"
loading={isLoadingChannels}
className={isErrorChannels ? 'error' : undefined}
emptyPlaceholder="No channels found"
showSearch
maxTagCount={2}
maxTagPlaceholder={(omittedValues): string =>
`+${omittedValues.length} more`
}
maxTagTextLength={10}
filterOption={(input, option): boolean =>
option?.label?.toLowerCase().includes(input.toLowerCase()) || false
}
status={isErrorChannels ? 'error' : undefined}
disabled={isLoadingChannels}
notFoundContent={
<NotificationChannelsNotFoundContent
user={user}
refreshChannels={refreshChannels}
/>
}
/>
</>
)}

View File

@@ -1,5 +1,5 @@
import { fireEvent, render, screen } from '@testing-library/react';
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import type { DefaultOptionType } from 'antd/es/select';
import { createMockAlertContextState } from 'container/CreateAlertV2/EvaluationSettings/__tests__/testUtils';
import { getAppContextMockState } from 'container/RoutingPolicies/__tests__/testUtils';
import * as appHooks from 'providers/App/App';
@@ -66,7 +66,7 @@ const mockChannels: Channels[] = [
{ id: TEST_CONSTANTS.CHANNEL_3, name: 'PagerDuty Channel' } as any,
];
const mockUnits: ComboboxSimpleItem[] = [
const mockUnits: DefaultOptionType[] = [
{ label: 'Bytes', value: 'bytes' },
{ label: 'KB', value: 'kb' },
{ label: 'MB', value: 'mb' },

View File

@@ -11,7 +11,7 @@
.alert-condition-tabs {
display: flex;
border-radius: 2px;
border: 1px solid var(--l2-border);
border: 1px solid var(--l1-border);
background: var(--l2-background);
flex-direction: row;
border-bottom: none;
@@ -26,19 +26,19 @@
padding: 9px;
box-shadow: none;
border-radius: 0px;
border-left: 0.5px solid var(--l2-border);
border-bottom: 0.5px solid var(--l2-border);
border-left: 0.5px solid var(--l1-border);
border-bottom: 0.5px solid var(--l1-border);
width: 120px;
height: 36px;
gap: 8px;
&.active-tab {
background-color: var(--l2-background);
background-color: var(--l1-background);
border-bottom: none;
&:hover {
background-color: var(--l2-background-hover) !important;
background-color: var(--l1-background) !important;
}
}
@@ -54,7 +54,7 @@
&:hover {
background-color: transparent !important;
border-left: 1px solid transparent !important;
color: var(--l3-foreground);
color: var(--l1-foreground);
}
}
}
@@ -65,16 +65,10 @@
.anomaly-threshold-container {
padding: 24px;
padding-right: 72px;
background-color: var(--l2-background);
border: 1px solid var(--l2-border);
background-color: var(--l1-background);
border: 1px solid var(--l1-border);
width: 100%;
--select-trigger-background-color: var(--l3-background);
--select-trigger-border-color: var(--l3-border);
--combobox-trigger-background-color: var(--l3-background);
--combobox-trigger-border-color: var(--l3-border);
.alert-condition-sentences {
display: flex;
flex-direction: column;
@@ -94,6 +88,34 @@
align-items: center;
gap: 8px;
}
.ant-select {
width: 240px;
.ant-select-selector {
background-color: var(--l2-background);
border: 1px solid var(--l1-border);
color: var(--muted-foreground);
font-family: 'Space Mono';
&:hover {
border-color: var(--l1-border);
}
&:focus {
border-color: var(--l1-border);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}
}
.ant-select-selection-item {
color: var(--l1-foreground);
}
.ant-select-arrow {
color: var(--muted-foreground);
}
}
}
}
@@ -129,9 +151,9 @@
flex-wrap: wrap;
.ant-input {
background-color: var(--l3-background);
border: 1px solid var(--l3-border);
color: var(--l2-foreground);
background-color: var(--card);
border: 1px solid var(--l1-border);
color: var(--l1-foreground);
height: 32px;
&::placeholder {
@@ -139,28 +161,28 @@
}
&:hover {
border-color: var(--l3-border);
border-color: var(--l1-border);
}
&:focus {
border-color: var(--l3-border);
border-color: var(--l1-border);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}
}
.ant-select {
.ant-select-selector {
background-color: var(--l3-background);
border: 1px solid var(--l3-border);
color: var(--l2-foreground);
background-color: var(--card);
border: 1px solid var(--l1-border);
color: var(--l1-foreground);
height: 32px;
&:hover {
border-color: var(--l2-border);
border-color: var(--l1-border);
}
&:focus {
border-color: var(--l2-border);
border-color: var(--l1-border);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}
@@ -170,23 +192,21 @@
}
.ant-select-selection-item {
color: var(--l2-foreground);
color: var(--l1-foreground);
}
.ant-select-arrow {
color: var(--l2-foreground);
color: var(--muted-foreground);
}
}
.icon-btn {
color: var(--l2-foreground);
border: 1px solid var(--l3-border);
background-color: var(--l3-background);
color: var(--muted-foreground);
border: 1px solid var(--l1-border);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: none;
}
}
}
@@ -206,8 +226,8 @@
pointer-events: none;
cursor: default;
color: var(--muted-foreground);
background-color: var(--l3-background) !important;
border: 1px solid var(--l3-border);
background-color: var(--card) !important;
border: 1px solid var(--l1-border);
border-radius: 4px;
display: flex;
align-items: center;
@@ -215,9 +235,9 @@
}
.ant-input {
background-color: var(--l3-background);
border: 1px solid var(--l3-border);
color: var(--l2-foreground);
background-color: var(--card);
border: 1px solid var(--l1-border);
color: var(--l1-foreground);
height: 32px;
&::placeholder {
@@ -225,11 +245,11 @@
}
&:hover {
border-color: var(--l3-border);
border-color: var(--l1-border);
}
&:focus {
border-color: var(--l2-border);
border-color: var(--l1-border);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}
}
@@ -238,7 +258,7 @@
.add-threshold-btn {
margin-top: 8px;
border: 1px dashed var(--l3-border);
border: 1px dashed var(--l1-border);
color: var(--l2-foreground);
background-color: transparent;
border-radius: 4px;
@@ -247,11 +267,10 @@
display: flex;
align-items: center;
justify-content: center;
box-shadow: none;
&:hover {
border-color: var(--l2-border);
color: var(--l3-foreground);
border-color: var(--l1-border);
color: var(--l1-foreground);
}
.anticon {
@@ -320,9 +339,8 @@
min-width: 240px;
width: auto;
justify-content: space-between;
background-color: var(--l3-background);
border: 1px solid var(--l3-border);
box-shadow: none;
background-color: var(--l2-background);
border: 1px solid var(--l1-border);
.evaluate-alert-conditions-button-left {
color: var(--l2-foreground);
@@ -340,7 +358,7 @@
.evaluate-alert-conditions-button-right-text {
font-size: 12px;
font-weight: 500;
background-color: var(--l3-border);
background-color: var(--l1-border);
padding: 1px 4px;
}
}

View File

@@ -1,4 +1,4 @@
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import type { DefaultOptionType } from 'antd/es/select';
import { Channels } from 'types/api/channels/getAll';
import {
@@ -23,7 +23,7 @@ export interface ThresholdItemProps {
showRemoveButton: boolean;
channels: Channels[];
isLoadingChannels: boolean;
units: ComboboxSimpleItem[];
units: DefaultOptionType[];
isErrorChannels: boolean;
refreshChannels: () => void;
}

View File

@@ -1,7 +1,6 @@
import { Button, Flex } from 'antd';
import { Switch } from '@signozhq/ui/switch';
import { ComboboxSimpleItem } from '@signozhq/ui/combobox';
import { Button, Flex, SelectProps, Switch } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import type { BaseOptionType, DefaultOptionType } from 'antd/es/select';
import { getInvolvedQueriesInTraceOperator } from 'components/QueryBuilderV2/QueryV2/TraceOperator/utils/utils';
import { YAxisSource } from 'components/YAxisUnitSelector/types';
import { getYAxisCategories } from 'components/YAxisUnitSelector/utils';
@@ -22,11 +21,11 @@ import { openInNewTab } from 'utils/navigation';
import { ROUTING_POLICIES_ROUTE } from './constants';
import { RoutingPolicyBannerProps } from './types';
export function getQueryNames(currentQuery: Query): ComboboxSimpleItem[] {
export function getQueryNames(currentQuery: Query): BaseOptionType[] {
const involvedQueriesInTraceOperator = getInvolvedQueriesInTraceOperator(
currentQuery.builder.queryTraceOperator,
);
const queryConfig: Record<EQueryType, () => ComboboxSimpleItem[]> = {
const queryConfig: Record<EQueryType, () => SelectProps['options']> = {
[EQueryType.QUERY_BUILDER]: () => [
...(getSelectedQueryOptions(currentQuery.builder.queryData)?.filter(
(option) =>
@@ -52,7 +51,7 @@ export function getCategoryByOptionId(id: string): string | undefined {
export function getCategorySelectOptionByName(
name: string | undefined,
): ComboboxSimpleItem[] {
): DefaultOptionType[] {
if (!name) {
return [];
}
@@ -68,6 +67,7 @@ export function getCategorySelectOptionByName(
?.units.map((unit) => ({
label: unit.name,
value: unit.id,
'data-testid': `threshold-unit-select-option-${unit.id}`,
})) || []
);
}
@@ -419,8 +419,8 @@ export function RoutingPolicyBanner({
</Typography.Text>
<div className="routing-policies-info-banner-right">
<Switch
value={notificationSettings.routingPolicies}
testId="routing-policies-switch"
checked={notificationSettings.routingPolicies}
data-testid="routing-policies-switch"
onChange={(value): void => {
setNotificationSettings({
type: 'SET_ROUTING_POLICIES',

View File

@@ -3,7 +3,6 @@ import { X } from '@signozhq/icons';
import { useNotifications } from 'hooks/useNotifications';
import { LabelInputState, LabelsInputProps } from './types';
import { Button } from '@signozhq/ui/button';
function LabelsInput({
labels,
@@ -145,16 +144,14 @@ function LabelsInput({
)}
{!isAdding ? (
<Button
<button
className="labels-input__add-button"
type="button"
variant="outlined"
color="secondary"
onClick={handleAddLabelsClick}
data-testid="alert-add-label-button"
>
+ Add labels
</Button>
</button>
) : (
<div className="labels-input__input-container">
<input

View File

@@ -39,14 +39,9 @@
&__input.title {
background-color: transparent;
background: var(--l2-background);
color: var(--l2-foreground);
color: var(--l1-foreground);
width: 100%;
min-width: 300px;
&:hover {
background: var(--l2-background);
}
}
&__input.description {
@@ -54,6 +49,15 @@
background-color: transparent;
color: var(--l2-foreground);
}
.ant-btn {
display: flex;
gap: 4px;
align-items: center;
color: var(--l1-foreground);
border: 1px solid var(--l1-border);
margin-right: 16px;
}
}
.labels-input {
@@ -62,7 +66,19 @@
gap: 8px;
&__add-button {
width: 80px;
width: fit-content;
font-size: 13px;
color: var(--l2-foreground);
border: 1px solid var(--l1-border);
background-color: transparent;
cursor: pointer;
padding: 4px 8px;
border-radius: 4px;
&:hover {
border-color: var(--l1-border);
color: var(--l1-foreground);
}
}
&__existing-labels {
@@ -105,7 +121,6 @@
align-items: center;
background-color: transparent;
border: none;
border: 1px solid var(--l2-border);
}
&__input {

View File

@@ -1,6 +1,5 @@
import { useEffect, useState } from 'react';
import { Tooltip } from 'antd';
import { Switch } from '@signozhq/ui/switch';
import { Switch, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { Info } from '@signozhq/icons';
@@ -50,7 +49,7 @@ function AdvancedOptionItem({
>
{input}
</div>
<Switch onChange={handleOnToggle} value={showInput} />
<Switch onChange={handleOnToggle} checked={showInput} />
</div>
</div>
);

View File

@@ -93,16 +93,16 @@
gap: 8px;
.ant-input {
background-color: var(--l3-background);
border: 1px solid var(--l3-border);
color: var(--l2-foreground);
background-color: var(--l2-background);
border: 1px solid var(--l1-border);
color: var(--l1-foreground);
&:hover {
border-color: var(--l3-border);
border-color: var(--l1-border);
}
&:focus {
border-color: var(--l3-border);
border-color: var(--l1-border);
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
}
}

View File

@@ -1,6 +1,5 @@
import { useEffect, useState } from 'react';
import { Input, Tooltip } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Input, Select, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { Info } from '@signozhq/icons';
@@ -80,8 +79,8 @@ function EvaluationCadence(): JSX.Element {
}
data-testid="evaluation-cadence-duration-input"
/>
<SelectSimple
items={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
<Select
options={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
placeholder="Select time unit"
style={{ width: 120 }}
value={advancedOptions.evaluationCadence.default.timeUnit}
@@ -92,7 +91,7 @@ function EvaluationCadence(): JSX.Element {
...advancedOptions.evaluationCadence,
default: {
...advancedOptions.evaluationCadence.default,
timeUnit: value as string,
timeUnit: value,
},
},
})

View File

@@ -1,6 +1,5 @@
import { useEffect, useMemo, useState } from 'react';
import { Button, DatePicker, Input } from 'antd';
import { ComboboxSimple } from '@signozhq/ui/combobox';
import { Button, DatePicker, Input, Select } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import classNames from 'classnames';
import { useCreateAlertState } from 'container/CreateAlertV2/context';
@@ -43,6 +42,10 @@ function EvaluationCadenceDetails({
},
});
const [searchTimezoneString, setSearchTimezoneString] = useState('');
const [occurenceSearchString, setOccurenceSearchString] = useState('');
const [repeatEverySearchString, setRepeatEverySearchString] = useState('');
const tabs = [
{
label: 'Editor',
@@ -90,39 +93,45 @@ function EvaluationCadenceDetails({
<div className="editor-view" data-testid="editor-view">
<div className="select-group">
<Typography.Text>REPEAT EVERY</Typography.Text>
<ComboboxSimple
items={EVALUATION_CADENCE_REPEAT_EVERY_OPTIONS}
value={evaluationCadence.custom.repeatEvery || undefined}
<Select
options={EVALUATION_CADENCE_REPEAT_EVERY_OPTIONS}
value={evaluationCadence.custom.repeatEvery || null}
onChange={(value): void =>
setEvaluationCadence({
...evaluationCadence,
custom: {
...evaluationCadence.custom,
repeatEvery: value as string,
repeatEvery: value,
occurence: [],
},
})
}
placeholder="Select repeat every"
showSearch
searchValue={repeatEverySearchString}
onSearch={setRepeatEverySearchString}
/>
</div>
{evaluationCadence.custom.repeatEvery !== 'day' && (
<div className="select-group">
<Typography.Text>ON DAY(S)</Typography.Text>
<ComboboxSimple
items={occurenceOptions}
value={evaluationCadence.custom.occurence || []}
multiple
<Select
options={occurenceOptions}
value={evaluationCadence.custom.occurence || null}
mode="multiple"
onChange={(value): void =>
setEvaluationCadence({
...evaluationCadence,
custom: {
...evaluationCadence.custom,
occurence: value as string[],
occurence: value,
},
})
}
placeholder="Select day(s)"
showSearch
searchValue={occurenceSearchString}
onSearch={setOccurenceSearchString}
/>
</div>
)}
@@ -143,19 +152,22 @@ function EvaluationCadenceDetails({
</div>
<div className="select-group">
<Typography.Text>TIMEZONE</Typography.Text>
<ComboboxSimple
items={TIMEZONE_DATA}
value={evaluationCadence.custom.timezone || undefined}
<Select
options={TIMEZONE_DATA}
value={evaluationCadence.custom.timezone || null}
onChange={(value): void =>
setEvaluationCadence({
...evaluationCadence,
custom: {
...evaluationCadence.custom,
timezone: value as string,
timezone: value,
},
})
}
placeholder="Select timezone"
onSearch={setSearchTimezoneString}
searchValue={searchTimezoneString}
showSearch
/>
</div>
</div>

View File

@@ -1,9 +1,5 @@
.evaluation-cadence-container {
border-bottom: 1px solid var(--l1-border);
--select-trigger-background-color: var(--l3-background);
--select-trigger-border-color: var(--l3-border);
.evaluation-cadence-item {
border-bottom: none !important;
}
@@ -161,6 +157,24 @@
font-weight: 500;
}
.ant-select {
border: 1px solid var(--l1-border);
.ant-select-selector {
background-color: var(--l2-background);
border: 1px solid var(--l1-border);
color: var(--l1-foreground);
&:hover {
border-color: var(--l1-border);
}
&:focus {
border-color: var(--l1-border);
}
}
}
.ant-picker {
background-color: var(--l2-background);
border: 1px solid var(--l1-border);

View File

@@ -1,6 +1,5 @@
import { useMemo } from 'react';
import { Input } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Input, Select } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { ADVANCED_OPTIONS_TIME_UNIT_OPTIONS } from '../../context/constants';
@@ -20,7 +19,7 @@ function EvaluationWindowDetails({
const currentHourOptions = useMemo(() => {
const options = [];
for (let i = 0; i < 60; i++) {
options.push({ label: i.toString(), value: i.toString() });
options.push({ label: i.toString(), value: i });
}
return options;
}, []);
@@ -28,7 +27,7 @@ function EvaluationWindowDetails({
const currentMonthOptions = useMemo(() => {
const options = [];
for (let i = 1; i <= 31; i++) {
options.push({ label: i.toString(), value: i.toString() });
options.push({ label: i.toString(), value: i });
}
return options;
}, []);
@@ -124,10 +123,10 @@ function EvaluationWindowDetails({
<Typography.Text>{displayText}</Typography.Text>
<div className="select-group">
<Typography.Text>STARTING AT MINUTE</Typography.Text>
<SelectSimple
items={currentHourOptions}
value={evaluationWindow.startingAt.number || undefined}
onChange={(value): void => handleNumberChange(value as string)}
<Select
options={currentHourOptions}
value={evaluationWindow.startingAt.number || null}
onChange={handleNumberChange}
placeholder="Select starting at"
data-testid="evaluation-window-details-starting-at-select"
/>
@@ -152,10 +151,10 @@ function EvaluationWindowDetails({
</div>
<div className="select-group">
<Typography.Text>SELECT TIMEZONE</Typography.Text>
<SelectSimple
items={TIMEZONE_DATA}
value={evaluationWindow.startingAt.timezone || undefined}
onChange={(value): void => handleTimezoneChange(value as string)}
<Select
options={TIMEZONE_DATA}
value={evaluationWindow.startingAt.timezone || null}
onChange={handleTimezoneChange}
placeholder="Select timezone"
data-testid="evaluation-window-details-timezone-select"
/>
@@ -173,10 +172,10 @@ function EvaluationWindowDetails({
<Typography.Text>{displayText}</Typography.Text>
<div className="select-group">
<Typography.Text>STARTING ON DAY</Typography.Text>
<SelectSimple
items={currentMonthOptions}
value={evaluationWindow.startingAt.number || undefined}
onChange={(value): void => handleNumberChange(value as string)}
<Select
options={currentMonthOptions}
value={evaluationWindow.startingAt.number || null}
onChange={handleNumberChange}
placeholder="Select starting at"
data-testid="evaluation-window-details-starting-at-select"
/>
@@ -190,10 +189,10 @@ function EvaluationWindowDetails({
</div>
<div className="select-group">
<Typography.Text>SELECT TIMEZONE</Typography.Text>
<SelectSimple
items={TIMEZONE_DATA}
value={evaluationWindow.startingAt.timezone || undefined}
onChange={(value): void => handleTimezoneChange(value as string)}
<Select
options={TIMEZONE_DATA}
value={evaluationWindow.startingAt.timezone || null}
onChange={handleTimezoneChange}
placeholder="Select timezone"
data-testid="evaluation-window-details-timezone-select"
/>
@@ -222,10 +221,10 @@ function EvaluationWindowDetails({
</div>
<div className="select-group time-select-group">
<Typography.Text>UNIT</Typography.Text>
<SelectSimple
items={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
value={evaluationWindow.startingAt.unit || undefined}
onChange={(value): void => handleUnitChange(value as string)}
<Select
options={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
value={evaluationWindow.startingAt.unit || null}
onChange={handleUnitChange}
placeholder="Select unit"
data-testid="evaluation-window-details-custom-rolling-window-unit-select"
/>

View File

@@ -1,6 +1,5 @@
import { useCallback, useMemo } from 'react';
import { Tooltip } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Select, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { Info } from '@signozhq/icons';
@@ -88,15 +87,16 @@ function MultipleNotifications(): JSX.Element {
: 'No grouping fields available';
let input = (
<div>
<SelectSimple
items={spaceAggregationOptions}
onChange={(value): void => onSelectChange(value as string[])}
value={notificationSettings.multipleNotifications || []}
multiple
<Select
options={spaceAggregationOptions}
onChange={onSelectChange}
value={notificationSettings.multipleNotifications}
mode="multiple"
placeholder={placeholder}
disabled={!isMultipleNotificationsEnabled}
maxDisplayedPills={3}
testId="multiple-notifications-select"
aria-disabled={!isMultipleNotificationsEnabled}
maxTagCount={3}
data-testid="multiple-notifications-select"
/>
{isMultipleNotificationsEnabled && (
<Typography.Text className="multiple-notifications-select-description">

View File

@@ -1,5 +1,4 @@
import { Input } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Input, Select } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import { useCreateAlertState } from '../context';
@@ -39,31 +38,31 @@ function NotificationSettings(): JSX.Element {
}}
data-testid="repeat-notifications-time-input"
/>
<SelectSimple
value={notificationSettings.reNotification.unit || undefined}
<Select
value={notificationSettings.reNotification.unit || null}
placeholder="Select unit"
disabled={!notificationSettings.reNotification.enabled}
items={RE_NOTIFICATION_TIME_UNIT_OPTIONS}
options={RE_NOTIFICATION_TIME_UNIT_OPTIONS}
onChange={(value): void => {
setNotificationSettings({
type: 'SET_RE_NOTIFICATION',
payload: {
enabled: notificationSettings.reNotification.enabled,
value: notificationSettings.reNotification.value,
unit: value as string,
unit: value,
conditions: notificationSettings.reNotification.conditions,
},
});
}}
testId="repeat-notifications-unit-select"
data-testid="repeat-notifications-unit-select"
/>
<Typography.Text>while</Typography.Text>
<SelectSimple
multiple
value={notificationSettings.reNotification.conditions || []}
<Select
mode="multiple"
value={notificationSettings.reNotification.conditions || null}
placeholder="Select conditions"
disabled={!notificationSettings.reNotification.enabled}
items={RE_NOTIFICATION_CONDITION_OPTIONS}
options={RE_NOTIFICATION_CONDITION_OPTIONS}
onChange={(value): void => {
setNotificationSettings({
type: 'SET_RE_NOTIFICATION',
@@ -71,11 +70,11 @@ function NotificationSettings(): JSX.Element {
enabled: notificationSettings.reNotification.enabled,
value: notificationSettings.reNotification.value,
unit: notificationSettings.reNotification.unit,
conditions: value as ('firing' | 'nodata')[],
conditions: value,
},
});
}}
testId="repeat-notifications-conditions-select"
data-testid="repeat-notifications-conditions-select"
/>
</div>
);

View File

@@ -3,9 +3,6 @@
flex-direction: column;
margin: 0 16px;
--select-trigger-background-color: var(--l3-background);
--select-trigger-border-color: var(--l3-border);
.notification-message-container {
display: flex;
flex-direction: column;
@@ -57,8 +54,8 @@
textarea {
height: 150px;
background: var(--l3-background);
border: 1px solid var(--l3-border);
background: var(--l2-background);
border: 1px solid var(--l1-border);
border-radius: 4px;
color: var(--l2-foreground) !important;
font-family: Inter;
@@ -80,9 +77,8 @@
gap: 8px;
.ant-input {
width: 190px;
border: 1px solid var(--l3-border);
background-color: var(--l3-background);
width: 120px;
border: 1px solid var(--l1-border);
}
.ant-select {

View File

@@ -37,11 +37,11 @@
gap: 8px;
&.active-tab {
background-color: var(--l3-background);
background-color: var(--l1-background);
border-bottom: none;
&:hover {
background-color: var(--l3-background) !important;
background-color: var(--l1-background) !important;
}
}

View File

@@ -7,7 +7,7 @@ import {
useState,
} from 'react';
import { Color } from '@signozhq/design-tokens';
import { SelectSimple } from '@signozhq/ui/select';
import { Select } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import CustomSelect from 'components/NewSelect/CustomSelect';
import TextToolTip from 'components/TextToolTip';
@@ -204,9 +204,10 @@ function DynamicVariable({
}
/>
</span>
<SelectSimple
<Select
placeholder="Source"
items={sources.map((source) => ({ label: source, value: source }))}
defaultValue={AttributeSource.ALL_TELEMETRY}
options={sources.map((source) => ({ label: source, value: source }))}
onChange={(value): void => setAttributeSource(value as AttributeSource)}
value={attributeSource || dynamicVariablesSelectedValue?.value}
/>

View File

@@ -5,9 +5,7 @@ import { useQuery } from 'react-query';
import { useSelector } from 'react-redux';
import { orange } from '@ant-design/colors';
import { Color } from '@signozhq/design-tokens';
import { Switch } from '@signozhq/ui/switch';
import { Button, Collapse, Input, Tag } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Button, Collapse, Input, Select, Switch, Tag } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import dashboardVariablesQuery from 'api/dashboard/variables/dashboardVariablesQuery';
import cx from 'classnames';
@@ -57,11 +55,7 @@ import { WidgetSelector } from './WidgetSelector';
import './VariableItem.styles.scss';
const SORT_ITEMS = [
{ value: VariableSortTypeArr[0], label: 'Disabled' },
{ value: VariableSortTypeArr[1], label: 'Ascending' },
{ value: VariableSortTypeArr[2], label: 'Descending' },
];
const { Option } = Select;
interface VariableItemProps {
variableData: IDashboardVariable;
@@ -748,14 +742,19 @@ function VariableItem({
<Typography className="typography-variables">Sort Values</Typography>
</LabelContainer>
<SelectSimple
<Select
defaultActiveFirstOption
defaultValue={VariableSortTypeArr[0]}
value={variableSortType}
onChange={(value): void =>
setVariableSortType(value as TSortVariableValuesType)
onChange={(value: TSortVariableValuesType): void =>
setVariableSortType(value)
}
className="sort-input"
items={SORT_ITEMS}
/>
>
<Option value={VariableSortTypeArr[0]}>Disabled</Option>
<Option value={VariableSortTypeArr[1]}>Ascending</Option>
<Option value={VariableSortTypeArr[2]}>Descending</Option>
</Select>
</VariableItemRow>
<VariableItemRow className="multiple-values-section">
<LabelContainer>
@@ -764,7 +763,7 @@ function VariableItem({
</Typography>
</LabelContainer>
<Switch
value={variableMultiSelect}
checked={variableMultiSelect}
onChange={(e): void => {
setVariableMultiSelect(e);
if (!e) {
@@ -781,7 +780,7 @@ function VariableItem({
</Typography>
</LabelContainer>
<Switch
value={variableShowALLOption}
checked={variableShowALLOption}
onChange={(e): void => setVariableShowALLOption(e)}
/>
</VariableItemRow>
@@ -798,10 +797,10 @@ function VariableItem({
<CustomSelect
placeholder="Select a default value"
value={variableDefaultValue}
onChange={(value): void => setVariableDefaultValue(value ?? '')}
options={previewValues.map((val) => ({
label: val,
value: val,
onChange={(value): void => setVariableDefaultValue(value)}
options={previewValues.map((value) => ({
label: value,
value,
}))}
/>
</VariableItemRow>

View File

@@ -98,14 +98,6 @@
.nameIconInput {
display: flex;
--select-trigger-width: 40px;
--select-trigger-background-color: var(--l3-background);
--select-trigger-border-color: var(--l1-border);
[data-slot='select-trigger'] svg {
display: none;
}
}
.dashboardImageInput {
@@ -116,7 +108,7 @@
padding: 6px;
justify-content: center;
align-items: center;
border-radius: 2var (--l3-border) px 0px 0px 2px;
border-radius: 2px 0px 0px 2px;
border: 1px solid var(--l1-border) !important;
background: var(--l3-background) !important;

View File

@@ -1,7 +1,6 @@
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Col, Input, Radio, Space, Tooltip } from 'antd';
import { SelectSimple } from '@signozhq/ui/select';
import { Col, Input, Radio, Select, Space, Tooltip } from 'antd';
import { Typography } from '@signozhq/ui/typography';
import AddTags from 'container/DashboardContainer/DashboardSettings/General/AddTags';
import { useDashboardCursorSyncMode } from 'hooks/dashboard/useDashboardCursorSyncMode';
@@ -22,6 +21,8 @@ import logEvent from 'api/common/logEvent';
import { Events } from 'constants/events';
import { getAbsoluteUrl } from 'utils/basePath';
const { Option } = Select;
function GeneralDashboardSettings(): JSX.Element {
const { dashboardData, setDashboardData } = useDashboardStore();
@@ -129,22 +130,24 @@ function GeneralDashboardSettings(): JSX.Element {
<div>
<Typography className={styles.dashboardName}>Dashboard Name</Typography>
<section className={styles.nameIconInput}>
<SelectSimple
<Select
defaultActiveFirstOption
data-testid="dashboard-image"
className={styles.dashboardImageInput}
suffixIcon={null}
rootClassName={styles.dashboardImageInput}
value={updatedImage}
onChange={(value): void => setUpdatedImage(value as string)}
items={Base64Icons.map((icon) => ({
value: icon,
label: (
onChange={(value: string): void => setUpdatedImage(value)}
>
{Base64Icons.map((icon) => (
<Option value={icon} key={icon}>
<img
src={icon}
alt="dashboard-icon"
className={styles.listItemImage}
/>
),
}))}
/>
</Option>
))}
</Select>
<Input
data-testid="dashboard-name"
className={styles.dashboardNameInput}

Some files were not shown because too many files have changed in this diff Show More