Compare commits
18 Commits
nv/v2-dash
...
feat/selec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b73b58acc | ||
|
|
f2a18e8b6c | ||
|
|
4da5673e12 | ||
|
|
c3db819d8e | ||
|
|
c83578f211 | ||
|
|
04a4d3fe32 | ||
|
|
27dc996fd8 | ||
|
|
83b25f3e9a | ||
|
|
67e4c4611c | ||
|
|
7274421895 | ||
|
|
9c6656d6b9 | ||
|
|
5c54a2537c | ||
|
|
bf201710a7 | ||
|
|
a5adc52276 | ||
|
|
5ddcf33811 | ||
|
|
c0fe996e7a | ||
|
|
1b6bb78ca4 | ||
|
|
0583f30e35 |
7
.github/CODEOWNERS
vendored
@@ -118,6 +118,9 @@ go.mod @therealpandey
|
||||
|
||||
/tests/integration/ @therealpandey
|
||||
|
||||
# e2e tests
|
||||
/tests/e2e/ @AshwinBhatkal
|
||||
|
||||
# Flagger Owners
|
||||
|
||||
/pkg/flagger/ @therealpandey
|
||||
@@ -162,3 +165,7 @@ 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
|
||||
|
||||
@@ -2689,7 +2689,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesClusterRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2759,7 +2758,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesDaemonSetRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2829,7 +2827,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesDeploymentRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2908,7 +2905,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesHostRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -2984,7 +2980,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesJobRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3032,7 +3027,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesNamespaceRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3110,7 +3104,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesNodeRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3209,7 +3202,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesPodRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3554,7 +3546,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesStatefulSetRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
@@ -3615,7 +3606,6 @@ components:
|
||||
records:
|
||||
items:
|
||||
$ref: '#/components/schemas/InframonitoringtypesVolumeRecord'
|
||||
nullable: true
|
||||
type: array
|
||||
requiredMetricsCheck:
|
||||
$ref: '#/components/schemas/InframonitoringtypesRequiredMetricsCheck'
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"@signozhq/design-tokens": "2.1.4",
|
||||
"@signozhq/icons": "0.4.0",
|
||||
"@signozhq/resizable": "0.0.2",
|
||||
"@signozhq/ui": "0.0.19",
|
||||
"@signozhq/ui": "0.0.21",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
"@tanstack/react-virtual": "3.13.22",
|
||||
"@uiw/codemirror-theme-copilot": "4.23.11",
|
||||
|
||||
@@ -14,8 +14,13 @@
|
||||
*/
|
||||
|
||||
const BANNED_COMPONENTS = {
|
||||
Typography: 'Use @signozhq/ui Typography instead of antd Typography.',
|
||||
Typography:
|
||||
'Use @signozhq/ui/typography Typography instead of antd Typography.',
|
||||
Switch: 'Use @signozhq/ui/switch Switch instead of antd Switch.',
|
||||
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 {
|
||||
|
||||
31
frontend/pnpm-lock.yaml
generated
@@ -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.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)
|
||||
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)
|
||||
'@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.19':
|
||||
resolution: {integrity: sha512-2q6aRxN/PR4PlR2xJZAREEuvLPiDFggfFKzCW2Z5vHVVbrgnvZHWD1jPUuwszfEg0ceH3UvkwqceO7wN4uRJAA==}
|
||||
'@signozhq/ui@0.0.21':
|
||||
resolution: {integrity: sha512-uLM3Vqwxlk2USXbwtb3qRLpjZR9b9QSHFQq/jtcfYNMDmIE/sNjSj0nRkEhX4RqqRgsLRt2PVA33aeWxDOLO3g==}
|
||||
peerDependencies:
|
||||
'@signozhq/icons': 0.3.0
|
||||
react: ^18.2.0
|
||||
@@ -3851,27 +3851,6 @@ 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'}
|
||||
@@ -12034,7 +12013,7 @@ snapshots:
|
||||
- react-dom
|
||||
- tailwindcss
|
||||
|
||||
'@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)':
|
||||
'@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)':
|
||||
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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -166,6 +166,7 @@ function createMockAppContext(
|
||||
userPreferences: [],
|
||||
hostsData: null,
|
||||
isLoggedIn: true,
|
||||
isPreflightLoading: false,
|
||||
org: [{ createdAt: 0, id: 'org-id', displayName: 'Test Org' }],
|
||||
isFetchingUser: false,
|
||||
isFetchingActiveLicense: false,
|
||||
|
||||
@@ -59,6 +59,7 @@ function App(): JSX.Element {
|
||||
isLoggedIn: isLoggedInState,
|
||||
featureFlags,
|
||||
org,
|
||||
isPreflightLoading,
|
||||
} = useAppContext();
|
||||
const [routes, setRoutes] = useState<AppRoutes[]>(defaultRoutes);
|
||||
const isAIAssistantEnabled = useIsAIAssistantEnabled();
|
||||
@@ -386,6 +387,10 @@ 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
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
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();
|
||||
});
|
||||
});
|
||||
@@ -3488,9 +3488,9 @@ export interface InframonitoringtypesClustersDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesClusterRecordDTO[] | null;
|
||||
records: InframonitoringtypesClusterRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3566,9 +3566,9 @@ export interface InframonitoringtypesDaemonSetsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesDaemonSetRecordDTO[] | null;
|
||||
records: InframonitoringtypesDaemonSetRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3644,9 +3644,9 @@ export interface InframonitoringtypesDeploymentsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesDeploymentRecordDTO[] | null;
|
||||
records: InframonitoringtypesDeploymentRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3730,9 +3730,9 @@ export interface InframonitoringtypesHostsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesHostRecordDTO[] | null;
|
||||
records: InframonitoringtypesHostRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3816,9 +3816,9 @@ export interface InframonitoringtypesJobsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesJobRecordDTO[] | null;
|
||||
records: InframonitoringtypesJobRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3866,9 +3866,9 @@ export interface InframonitoringtypesNamespacesDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesNamespaceRecordDTO[] | null;
|
||||
records: InframonitoringtypesNamespaceRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3933,9 +3933,9 @@ export interface InframonitoringtypesNodesDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesNodeRecordDTO[] | null;
|
||||
records: InframonitoringtypesNodeRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -4017,9 +4017,9 @@ export interface InframonitoringtypesPodsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesPodRecordDTO[] | null;
|
||||
records: InframonitoringtypesPodRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -4437,9 +4437,9 @@ export interface InframonitoringtypesStatefulSetsDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesStatefulSetRecordDTO[] | null;
|
||||
records: InframonitoringtypesStatefulSetRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
@@ -4506,9 +4506,9 @@ export interface InframonitoringtypesVolumesDTO {
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array,null
|
||||
* @type array
|
||||
*/
|
||||
records: InframonitoringtypesVolumeRecordDTO[] | null;
|
||||
records: InframonitoringtypesVolumeRecordDTO[];
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
|
||||
@@ -13,6 +13,7 @@ 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';
|
||||
@@ -108,7 +109,10 @@ 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' &&
|
||||
@@ -140,16 +144,20 @@ export const interceptorRejected = async (
|
||||
return await Promise.resolve(reResponse);
|
||||
} catch (error) {
|
||||
if ((error as AxiosError)?.response?.status === 401) {
|
||||
Logout();
|
||||
void Logout();
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
Logout();
|
||||
void Logout();
|
||||
}
|
||||
}
|
||||
|
||||
if (response.status === 401 && response.config.url === '/sessions/rotate') {
|
||||
Logout();
|
||||
if (
|
||||
!isNoAuthMode &&
|
||||
response.status === 401 &&
|
||||
response.config.url === '/sessions/rotate'
|
||||
) {
|
||||
void Logout();
|
||||
}
|
||||
}
|
||||
return await Promise.reject(value);
|
||||
|
||||
3
frontend/src/assets/Logos/apache-druid.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
7
frontend/src/assets/Logos/aspnet.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
15
frontend/src/assets/Logos/azure-cdn-frontdoor.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 877 B |
15
frontend/src/assets/Logos/cert-manager.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
55
frontend/src/assets/Logos/graphql.svg
Normal file
@@ -0,0 +1,55 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
3
frontend/src/assets/Logos/istio.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 901 B |
3
frontend/src/assets/Logos/railway.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 776 B |
13
frontend/src/assets/Logos/scala.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
37
frontend/src/assets/Logos/slog.svg
Normal file
@@ -0,0 +1,37 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1,12 +1,12 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import { Row, Select, Spin } from 'antd';
|
||||
import { Row } from 'antd';
|
||||
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
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(() => {
|
||||
const mergedOptions = useMemo<ComboboxSimpleItem[]>(() => {
|
||||
if (
|
||||
!!searchValue.trim().length &&
|
||||
!options.some((opt) => opt.value === searchValue)
|
||||
@@ -84,35 +84,16 @@ export function FilterSelect({
|
||||
],
|
||||
);
|
||||
|
||||
// Update searchValue on user input
|
||||
const handleSearchInput = (input: string): void => {
|
||||
setSearchValue(input);
|
||||
handleSearch(input);
|
||||
};
|
||||
|
||||
return (
|
||||
<Select
|
||||
<ComboboxSimple
|
||||
key={filterType.toString()}
|
||||
placeholder={placeholder}
|
||||
showSearch
|
||||
{...(isMultiple ? { mode: 'multiple' } : {})}
|
||||
options={mergedOptions}
|
||||
multiple={isMultiple}
|
||||
items={mergedOptions}
|
||||
loading={isFetching}
|
||||
className="config-select-option"
|
||||
onSearch={handleSearchInput}
|
||||
maxTagCount={4}
|
||||
allowClear
|
||||
maxTagPlaceholder={SelectMaxTagPlaceholder}
|
||||
value={selectValue}
|
||||
notFoundContent={
|
||||
isFetching ? (
|
||||
<span>
|
||||
<Spin size="small" /> Loading...
|
||||
</span>
|
||||
) : (
|
||||
<span>No {placeholder} found</span>
|
||||
)
|
||||
}
|
||||
emptyPlaceholder={`No ${placeholder} found`}
|
||||
onChange={handleSelectChange}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -51,13 +51,6 @@
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const cpuPercent = percent;
|
||||
if (cpuPercent >= 90) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import { Select, Spin } from 'antd';
|
||||
import { ComboboxSimple } from '@signozhq/ui/combobox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
|
||||
@@ -27,30 +26,18 @@ function CeleryTaskConfigOptions(): JSX.Element {
|
||||
<Typography.Text style={{ whiteSpace: 'nowrap' }}>
|
||||
Task Name
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<ComboboxSimple
|
||||
placeholder="Task Name"
|
||||
showSearch
|
||||
mode="multiple"
|
||||
options={options}
|
||||
multiple
|
||||
items={options}
|
||||
loading={isFetching}
|
||||
className="config-select-option"
|
||||
onSearch={handleSearch}
|
||||
maxTagCount={4}
|
||||
maxTagPlaceholder={SelectMaxTagPlaceholder}
|
||||
value={getValuesFromQueryParams(QueryParams.taskName, urlQuery) || []}
|
||||
notFoundContent={
|
||||
isFetching ? (
|
||||
<span>
|
||||
<Spin size="small" /> Loading...
|
||||
</span>
|
||||
) : (
|
||||
<span>No Task Name found</span>
|
||||
)
|
||||
}
|
||||
emptyPlaceholder="No Task Name found"
|
||||
onChange={(value): void => {
|
||||
handleSearch('');
|
||||
setQueryParamsFromOptions(
|
||||
value,
|
||||
value as string[],
|
||||
urlQuery,
|
||||
history,
|
||||
location,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useQuery } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
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: DefaultOptionType[];
|
||||
options: ComboboxSimpleItem[];
|
||||
isFetching: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
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: DefaultOptionType[];
|
||||
options: ComboboxSimpleItem[];
|
||||
} => {
|
||||
const [searchText, setSearchText] = useState<string>('');
|
||||
const { isFetching, options } = useGetAllFilters({
|
||||
|
||||
@@ -5,17 +5,25 @@ import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Select, Tag, Tooltip } from 'antd';
|
||||
import {
|
||||
Combobox,
|
||||
ComboboxCommand,
|
||||
ComboboxContent,
|
||||
ComboboxEmpty,
|
||||
ComboboxItem,
|
||||
ComboboxList,
|
||||
ComboboxMultiTrigger,
|
||||
ComboboxPill,
|
||||
} from '@signozhq/ui/combobox';
|
||||
import { 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';
|
||||
@@ -38,7 +46,6 @@ 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,
|
||||
@@ -47,7 +54,6 @@ import {
|
||||
IBuilderQuery,
|
||||
TagFilter,
|
||||
} from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import './ClientSideQBSearch.styles.scss';
|
||||
@@ -93,8 +99,6 @@ 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.
|
||||
@@ -214,7 +218,7 @@ function ClientSideQBSearch(
|
||||
}, []);
|
||||
|
||||
const onInputKeyDownHandler = useCallback(
|
||||
(event: KeyboardEvent<Element>): void => {
|
||||
(event: KeyboardEvent<HTMLInputElement>): void => {
|
||||
if (event.key === 'Backspace' && !searchValue) {
|
||||
event.stopPropagation();
|
||||
setTags((prev) => prev.slice(0, -1));
|
||||
@@ -516,29 +520,23 @@ function ClientSideQBSearch(
|
||||
[tags],
|
||||
);
|
||||
|
||||
const onTagRender = ({
|
||||
value,
|
||||
closable,
|
||||
onClose,
|
||||
}: CustomTagProps): React.ReactElement => {
|
||||
const renderPill = (value: string, index: number): React.ReactElement => {
|
||||
const { tagOperator } = getTagToken(value);
|
||||
const isInNin = isInNInOperator(tagOperator);
|
||||
const chipValue = isInNin
|
||||
? value?.trim()?.replace(/,\s*$/, '')
|
||||
: value?.trim();
|
||||
|
||||
const indexInQueryTags = queryTags.findIndex((qTag) => isEqual(qTag, value));
|
||||
const tagDetails = tags[indexInQueryTags];
|
||||
const tagDetails = tags[index];
|
||||
|
||||
const onCloseHandler = (): void => {
|
||||
onClose();
|
||||
setSearchValue('');
|
||||
setTags((prev) => prev.filter((t) => !isEqual(t, tagDetails)));
|
||||
};
|
||||
|
||||
const tagEditHandler = (value: string): void => {
|
||||
const tagEditHandler = (next: string): void => {
|
||||
setCurrentFilterItem(tagDetails);
|
||||
setSearchValue(value);
|
||||
setSearchValue(next);
|
||||
setCurrentState(DropdownState.ATTRIBUTE_VALUE);
|
||||
setTags((prev) => prev.filter((t) => !isEqual(t, tagDetails)));
|
||||
};
|
||||
@@ -546,12 +544,13 @@ function ClientSideQBSearch(
|
||||
const isDisabled = !!searchValue;
|
||||
|
||||
return (
|
||||
<span className="qb-search-bar-tokenised-tags">
|
||||
<Tag
|
||||
closable={!searchValue && closable}
|
||||
onClose={onCloseHandler}
|
||||
className={tagDetails?.key?.type || ''}
|
||||
>
|
||||
<ComboboxPill
|
||||
key={`${value}-${index}`}
|
||||
value={value}
|
||||
onRemove={onCloseHandler}
|
||||
className="qb-search-bar-tokenised-tags"
|
||||
>
|
||||
<Tag closable={false} className={tagDetails?.key?.type || ''}>
|
||||
<Tooltip title={chipValue}>
|
||||
<TypographyText
|
||||
$isInNin={isInNin}
|
||||
@@ -567,7 +566,7 @@ function ClientSideQBSearch(
|
||||
</TypographyText>
|
||||
</Tooltip>
|
||||
</Tag>
|
||||
</span>
|
||||
</ComboboxPill>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -588,59 +587,73 @@ 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 ">
|
||||
<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 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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -137,7 +137,6 @@ 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"
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
Dropdown,
|
||||
MenuProps,
|
||||
Popover,
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
} from 'antd';
|
||||
import { Button, Col, Dropdown, MenuProps, Popover, Row, Space } from 'antd';
|
||||
import { ComboboxSimple } from '@signozhq/ui/combobox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import axios from 'axios';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
@@ -31,11 +23,7 @@ import { popupContainer } from 'utils/selectPopupContainer';
|
||||
import { ExploreHeaderToolTip, SaveButtonText } from './constants';
|
||||
import MenuItemGenerator from './MenuItemGenerator';
|
||||
import SaveViewWithName from './SaveViewWithName';
|
||||
import {
|
||||
DropDownOverlay,
|
||||
ExplorerCardHeadContainer,
|
||||
OffSetCol,
|
||||
} from './styles';
|
||||
import { ExplorerCardHeadContainer, OffSetCol } from './styles';
|
||||
import { ExplorerCardProps } from './types';
|
||||
import { deleteViewHandler } from './utils';
|
||||
import { Ellipsis, Save, Share2, Trash2 } from '@signozhq/icons';
|
||||
@@ -164,6 +152,26 @@ 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 && (
|
||||
@@ -183,30 +191,12 @@ function ExplorerCard({
|
||||
<Space size="large">
|
||||
{viewsData?.data.data && viewsData?.data.data.length && (
|
||||
<Space>
|
||||
<Select
|
||||
getPopupContainer={popupContainer}
|
||||
<ComboboxSimple
|
||||
loading={isLoading || isRefetching}
|
||||
showSearch
|
||||
placeholder="Select a view"
|
||||
dropdownStyle={DropDownOverlay}
|
||||
dropdownMatchSelectWidth={false}
|
||||
optionLabelProp="value"
|
||||
items={viewItems}
|
||||
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 && (
|
||||
|
||||
@@ -11,9 +11,6 @@ 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>;
|
||||
@@ -90,40 +87,28 @@ describe('GuardAuthZ', () => {
|
||||
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render fallbackOnError when API error occurs', async () => {
|
||||
const errorMessage = 'Internal Server Error';
|
||||
|
||||
it('should render children when API error occurs and no fallbackOnError provided (fail open)', async () => {
|
||||
server.use(
|
||||
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
|
||||
return res(ctx.status(500), ctx.json({ error: errorMessage }));
|
||||
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
|
||||
}),
|
||||
);
|
||||
|
||||
render(
|
||||
<GuardAuthZ relation="read" object="role:*" fallbackOnError={ErrorFallback}>
|
||||
<GuardAuthZ relation="read" object="role:*">
|
||||
<TestChild />
|
||||
</GuardAuthZ>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/Error occurred:/)).toBeInTheDocument();
|
||||
expect(screen.getByText('Protected Content')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
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>;
|
||||
};
|
||||
|
||||
it('should render fallbackOnError when API error occurs and fallbackOnError is provided', async () => {
|
||||
server.use(
|
||||
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
|
||||
return res(ctx.status(500), ctx.json({ error: errorMessage }));
|
||||
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -131,35 +116,14 @@ describe('GuardAuthZ', () => {
|
||||
<GuardAuthZ
|
||||
relation="read"
|
||||
object="role:*"
|
||||
fallbackOnError={errorFallbackWithCapture}
|
||||
fallbackOnError={<div>Custom error fallback</div>}
|
||||
>
|
||||
<TestChild />
|
||||
</GuardAuthZ>,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
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.getByText('Custom error fallback')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(screen.queryByText('Protected Content')).not.toBeInTheDocument();
|
||||
@@ -12,7 +12,7 @@ export type GuardAuthZProps<R extends AuthZRelation> = {
|
||||
relation: R;
|
||||
object: AuthZObject<R>;
|
||||
fallbackOnLoading?: JSX.Element;
|
||||
fallbackOnError?: (error: Error) => JSX.Element;
|
||||
fallbackOnError?: JSX.Element;
|
||||
fallbackOnNoPermissions?: (response: {
|
||||
requiredPermissionName: BrandedPermission;
|
||||
}) => JSX.Element;
|
||||
@@ -35,7 +35,7 @@ export function GuardAuthZ<R extends AuthZRelation>({
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return fallbackOnError?.(error) ?? null;
|
||||
return fallbackOnError ?? children;
|
||||
}
|
||||
|
||||
if (!permissions?.[permission]?.isGranted) {
|
||||
|
||||
@@ -4,7 +4,8 @@ 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, Switch } from 'antd';
|
||||
import { Button } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { QueryParams } from 'constants/query';
|
||||
@@ -125,9 +126,8 @@ function ShareURLModal(): JSX.Element {
|
||||
<Info size={14} color={Color.BG_AMBER_600} />
|
||||
)}
|
||||
<Switch
|
||||
checked={enableAbsoluteTime}
|
||||
value={enableAbsoluteTime}
|
||||
disabled={!isValidateRelativeTime}
|
||||
size="small"
|
||||
onChange={(): void => {
|
||||
setEnableAbsoluteTime((prev) => !prev);
|
||||
}}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
padding: 0px 8px;
|
||||
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
border: 1px solid var(--l2-border);
|
||||
background: var(--l2-background);
|
||||
color: var(--l2-foreground);
|
||||
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));
|
||||
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
@@ -35,21 +35,28 @@
|
||||
min-width: 150px;
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l2-background);
|
||||
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-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: 27px;
|
||||
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;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: var(--l2-foreground) !important;
|
||||
color: var(--input-with-label-color, var(--l3-foreground)) !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
&[type='number']::-webkit-inner-spin-button,
|
||||
@@ -63,25 +70,24 @@
|
||||
|
||||
.close-btn {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
border: 1px solid var(--l2-border);
|
||||
background: var(--l2-background);
|
||||
height: 38px;
|
||||
border: 1px solid var(--input-with-label-border-color, var(--l2-border));
|
||||
background: var(--input-with-label-background-color, var(--l2-background));
|
||||
height: 100%;
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
&.labelAfter {
|
||||
.input {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l2-background);
|
||||
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-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
|
||||
.label {
|
||||
border-left: none;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,10 @@ function InputWithLabel({
|
||||
>
|
||||
{!labelAfter && <Typography.Text className="label">{label}</Typography.Text>}
|
||||
<Input
|
||||
className="input"
|
||||
className={cx('input', {
|
||||
'input__has-label-after': !labelAfter,
|
||||
'input__has-close-button': !!onClose,
|
||||
})}
|
||||
placeholder={placeholder}
|
||||
type={type}
|
||||
value={inputValue}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Style } from '@signozhq/design-tokens';
|
||||
import { ChevronDown, Plus, Trash2, X } from '@signozhq/icons';
|
||||
import { 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,7 +15,6 @@ 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';
|
||||
@@ -254,18 +253,17 @@ function InviteMembersModal({
|
||||
)}
|
||||
</div>
|
||||
<div className="team-member-cell role-cell">
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={row.role || undefined}
|
||||
onChange={(role): void => updateRole(row.id, role as ROLES)}
|
||||
className="team-member-role-select"
|
||||
placeholder="Select roles"
|
||||
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>
|
||||
items={[
|
||||
{ value: 'VIEWER', label: 'Viewer' },
|
||||
{ value: 'EDITOR', label: 'Editor' },
|
||||
{ value: 'ADMIN', label: 'Admin' },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div className="team-member-cell action-cell">
|
||||
{rows.length > 1 && (
|
||||
|
||||
@@ -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 { DefaultOptionType } from 'antd/es/select';
|
||||
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
import cx from 'classnames';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
import { FontSize, OptionsMenuConfig } from 'container/OptionsMenu/types';
|
||||
@@ -113,15 +113,11 @@ function OptionsMenu({
|
||||
|
||||
function handleColumnSelection(
|
||||
currentIndex: number,
|
||||
optionsData: DefaultOptionType[],
|
||||
optionsData: ComboboxSimpleItem[],
|
||||
): void {
|
||||
const currentItem = optionsData[currentIndex];
|
||||
const itemLength = optionsData.length;
|
||||
if (addColumn && addColumn?.onSelect) {
|
||||
addColumn?.onSelect(selectedValue, {
|
||||
label: currentItem.label,
|
||||
disabled: false,
|
||||
});
|
||||
if (addColumn && addColumn?.onSelect && selectedValue) {
|
||||
addColumn?.onSelect(selectedValue);
|
||||
|
||||
// if the last element is selected then select the previous one
|
||||
if (currentIndex === itemLength - 1) {
|
||||
@@ -175,7 +171,7 @@ function OptionsMenu({
|
||||
}
|
||||
case 'Enter':
|
||||
e.preventDefault();
|
||||
handleColumnSelection(currentIndex, optionsData);
|
||||
handleColumnSelection(currentIndex, optionsData as ComboboxSimpleItem[]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -317,7 +313,10 @@ function OptionsMenu({
|
||||
}}
|
||||
onClick={(eve): void => {
|
||||
eve.stopPropagation();
|
||||
handleColumnSelection(index, addColumn?.options || []);
|
||||
handleColumnSelection(
|
||||
index,
|
||||
(addColumn?.options || []) as ComboboxSimpleItem[],
|
||||
);
|
||||
}}
|
||||
>
|
||||
<div className="name">
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
Loader,
|
||||
X,
|
||||
} from '@signozhq/icons';
|
||||
import { Modal, Select, Spin, Tooltip, Tree, TreeDataNode } from 'antd';
|
||||
import { Modal, Spin, Tooltip, Tree, TreeDataNode } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { OnboardingStatusResponse } from 'api/messagingQueues/onboarding/getOnboardingStatus';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
@@ -181,8 +182,8 @@ function AttributeCheckList({
|
||||
const [filter, setFilter] = useState<AttributesFilters>(AttributesFilters.ALL);
|
||||
const [treeData, setTreeData] = useState<TreeDataNode[]>([]);
|
||||
|
||||
const handleFilterChange = (value: AttributesFilters): void => {
|
||||
setFilter(value);
|
||||
const handleFilterChange = (value: string | string[]): void => {
|
||||
setFilter(value as AttributesFilters);
|
||||
};
|
||||
const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
|
||||
const history = useHistory();
|
||||
@@ -237,11 +238,11 @@ function AttributeCheckList({
|
||||
</div>
|
||||
) : (
|
||||
<div className="modal-content">
|
||||
<Select
|
||||
<SelectSimple
|
||||
defaultValue={AttributesFilters.ALL}
|
||||
className="attribute-select"
|
||||
onChange={handleFilterChange}
|
||||
options={[
|
||||
items={[
|
||||
{
|
||||
value: AttributesFilters.ALL,
|
||||
label: AttributeLabels({ title: 'Attributes: All' }),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Tooltip } from 'antd';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
import { Info } from '@signozhq/icons';
|
||||
|
||||
import './MQCommon.styles.scss';
|
||||
@@ -35,7 +35,7 @@ export function ComingSoon(): JSX.Element {
|
||||
}
|
||||
|
||||
export function SelectMaxTagPlaceholder(
|
||||
omittedValues: Partial<DefaultOptionType>[],
|
||||
omittedValues: Partial<ComboboxSimpleItem>[],
|
||||
): JSX.Element {
|
||||
return (
|
||||
<Tooltip title={omittedValues.map(({ value }) => value).join(', ')}>
|
||||
|
||||
@@ -18,7 +18,9 @@ import {
|
||||
RefreshCw,
|
||||
} from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Checkbox, Select } from 'antd';
|
||||
// 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 { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import TextToolTip from 'components/TextToolTip/TextToolTip';
|
||||
|
||||
@@ -16,6 +16,7 @@ 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';
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
.banner {
|
||||
height: var(--spacing-20);
|
||||
|
||||
a {
|
||||
color: var(--callout-warning-title);
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: var(--callout-warning-title);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
frontend/src/components/NoAuthBanner/NoAuthBanner.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
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;
|
||||
@@ -0,0 +1,24 @@
|
||||
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');
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useQuery } from 'react-query';
|
||||
import { Select, Spin } from 'antd';
|
||||
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import { QueryKeyDataSuggestionsProps } from 'types/api/querySuggestions/types';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
@@ -13,48 +13,25 @@ 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 [searchInput, setSearchInput] = useState('');
|
||||
const [debouncedInput, setDebouncedInput] = useState('');
|
||||
const [selectOptions, setSelectOptions] = useState<
|
||||
{ label: string; value: string }[]
|
||||
>([]);
|
||||
const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const [selectOptions, setSelectOptions] = useState<ComboboxSimpleItem[]>([]);
|
||||
|
||||
// Fetch key suggestions based on debounced input
|
||||
// Fetch key suggestions once; ComboboxSimple handles local filtering.
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['orderByKeySuggestions', dataSource, debouncedInput],
|
||||
queryKey: ['orderByKeySuggestions', dataSource],
|
||||
queryFn: async () => {
|
||||
const response = await getKeySuggestions({
|
||||
signal: dataSource,
|
||||
searchText: debouncedInput,
|
||||
searchText: '',
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(
|
||||
() => (): void => {
|
||||
if (debounceTimer.current) {
|
||||
clearTimeout(debounceTimer.current);
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
// Update options when API data changes
|
||||
useEffect(() => {
|
||||
const rawKeys: QueryKeyDataSuggestionsProps[] = data?.data?.keys
|
||||
@@ -62,52 +39,33 @@ function ListViewOrderBy({
|
||||
: [];
|
||||
|
||||
const keyNames = rawKeys.map((key) => key.name);
|
||||
const uniqueKeys = [
|
||||
...new Set(searchInput ? keyNames : ['timestamp', ...keyNames]),
|
||||
];
|
||||
const uniqueKeys = [...new Set(['timestamp', ...keyNames])];
|
||||
|
||||
const updatedOptions = uniqueKeys.flatMap((key) => [
|
||||
const updatedOptions: ComboboxSimpleItem[] = uniqueKeys.flatMap((key) => [
|
||||
{ label: `${key} (desc)`, value: `${key}:desc` },
|
||||
{ label: `${key} (asc)`, value: `${key}:asc` },
|
||||
]);
|
||||
|
||||
setSelectOptions(updatedOptions);
|
||||
}, [data, searchInput]);
|
||||
}, [data]);
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
const handleChange = useMemo(
|
||||
() =>
|
||||
(val: string | string[]): void => {
|
||||
onChange(val as string);
|
||||
},
|
||||
[onChange],
|
||||
);
|
||||
|
||||
return (
|
||||
<Select
|
||||
showSearch
|
||||
<ComboboxSimple
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onSearch={handleSearch}
|
||||
notFoundContent={<Loader isLoading={isLoading} />}
|
||||
onChange={handleChange}
|
||||
loading={isLoading}
|
||||
placeholder="Select a field"
|
||||
style={{ width: 200 }}
|
||||
options={selectOptions}
|
||||
filterOption={(input, option): boolean =>
|
||||
(option?.value ?? '').toLowerCase().includes(input.trim().toLowerCase())
|
||||
}
|
||||
items={selectOptions}
|
||||
emptyPlaceholder="No results found"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,37 @@
|
||||
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;
|
||||
@@ -80,8 +111,8 @@
|
||||
width: 1px;
|
||||
background: repeating-linear-gradient(
|
||||
to bottom,
|
||||
var(--l1-border),
|
||||
var(--l1-border) 4px,
|
||||
var(--query-builder-v2-border-color, var(--l2-border)),
|
||||
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
@@ -101,7 +132,8 @@
|
||||
top: 12px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-left: 6px dotted var(--l1-border);
|
||||
border-left: 6px dotted
|
||||
var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
|
||||
/* Horizontal line pointing from vertical to the item */
|
||||
@@ -114,8 +146,8 @@
|
||||
height: 1px;
|
||||
background: repeating-linear-gradient(
|
||||
to right,
|
||||
var(--l1-border),
|
||||
var(--l1-border) 4px,
|
||||
var(--query-builder-v2-border-color, var(--l2-border)),
|
||||
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
@@ -241,7 +273,8 @@
|
||||
top: 12px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-left: 6px dotted var(--l1-border);
|
||||
border-left: 6px dotted
|
||||
var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
|
||||
/* Horizontal line pointing from vertical to the item */
|
||||
@@ -254,8 +287,8 @@
|
||||
height: 1px;
|
||||
background: repeating-linear-gradient(
|
||||
to right,
|
||||
var(--l1-border),
|
||||
var(--l1-border) 4px,
|
||||
var(--query-builder-v2-border-color, var(--l2-border)),
|
||||
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
@@ -273,6 +306,16 @@
|
||||
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 {
|
||||
@@ -282,15 +325,30 @@
|
||||
.ant-input-group-addon {
|
||||
border-top-left-radius: 0px !important;
|
||||
border-top-right-radius: 0px !important;
|
||||
background: var(--l2-background);
|
||||
color: var(--l2-foreground);
|
||||
background: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
);
|
||||
color: var(--query-builder-v2-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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,8 +381,8 @@
|
||||
width: 1px;
|
||||
background: repeating-linear-gradient(
|
||||
to bottom,
|
||||
var(--l1-border),
|
||||
var(--l1-border) 4px,
|
||||
var(--query-builder-v2-border-color, var(--l2-border)),
|
||||
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
@@ -395,8 +453,8 @@
|
||||
width: 1px;
|
||||
background: repeating-linear-gradient(
|
||||
to bottom,
|
||||
var(--l1-border),
|
||||
var(--l1-border) 4px,
|
||||
var(--query-builder-v2-border-color, var(--l2-border)),
|
||||
var(--query-builder-v2-border-color, var(--l2-border)) 4px,
|
||||
transparent 4px,
|
||||
transparent 8px
|
||||
);
|
||||
@@ -412,7 +470,7 @@
|
||||
min-width: 120px;
|
||||
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: var(--l1-background);
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
|
||||
@@ -457,7 +515,7 @@
|
||||
|
||||
.ant-select-selector {
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border) !important;
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border)) !important;
|
||||
background: var(--l1-background) !important;
|
||||
height: 34px !important;
|
||||
box-sizing: border-box !important;
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
.group-by-filter-container {
|
||||
min-width: 340px !important;
|
||||
--combobox-trigger-height: auto;
|
||||
}
|
||||
|
||||
.metrics-aggregation-section-content-item {
|
||||
@@ -146,17 +147,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,6 @@ const MetricsAggregateSection = memo(function MetricsAggregateSection({
|
||||
value={queryAggregation.timeAggregation || ''}
|
||||
onChange={handleChangeOperator}
|
||||
operators={operators}
|
||||
className="metrics-operators-select"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
|
||||
--select-trigger-width: auto;
|
||||
|
||||
.ant-select-selection-search-input {
|
||||
font-size: 12px !important;
|
||||
line-height: 27px;
|
||||
line-height: 25px;
|
||||
&::placeholder {
|
||||
color: var(--l2-foreground) !important;
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
}
|
||||
@@ -22,9 +24,9 @@
|
||||
.ant-select-selector {
|
||||
width: 100%;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border) !important;
|
||||
background: var(--l1-background);
|
||||
color: var(--l1-foreground);
|
||||
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));
|
||||
font-family: 'Geist Mono';
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
@@ -33,20 +35,23 @@
|
||||
min-height: 36px;
|
||||
|
||||
.ant-select-selection-placeholder {
|
||||
color: var(--l2-foreground) !important;
|
||||
color: var(
|
||||
--query-builder-v2-placeholder-color,
|
||||
var(--l3-foreground)
|
||||
) !important;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select-dropdown {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l1-background);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: var(--query-builder-v2-background-color, var(--l2-background));
|
||||
box-shadow: 4px 10px 16px 2px rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(20px);
|
||||
|
||||
.ant-select-item {
|
||||
color: var(--l1-foreground);
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground));
|
||||
font-family: 'Geist Mono';
|
||||
font-size: 13px;
|
||||
font-style: normal;
|
||||
@@ -55,12 +60,18 @@
|
||||
|
||||
&:hover,
|
||||
&.ant-select-item-option-active {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selected-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
}
|
||||
|
||||
&.ant-select-item-option-selected {
|
||||
background: var(--l3-background) !important;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(
|
||||
--query-builder-v2-selected-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { Select } from 'antd';
|
||||
import { SelectSimple, type SelectSimpleItem } from '@signozhq/ui/select';
|
||||
import {
|
||||
initialQueriesMap,
|
||||
initialQueryMeterWithType,
|
||||
@@ -10,7 +10,6 @@ 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,
|
||||
@@ -21,7 +20,7 @@ import {
|
||||
|
||||
import './MetricsSelect.styles.scss';
|
||||
|
||||
export const SOURCE_OPTIONS: SelectOption<string, string>[] = [
|
||||
export const SOURCE_OPTIONS: SelectSimpleItem[] = [
|
||||
{ value: 'metrics', label: 'Metrics' },
|
||||
{ value: 'meter', label: 'Meter' },
|
||||
];
|
||||
@@ -140,14 +139,14 @@ export const MetricsSelect = memo(function MetricsSelect({
|
||||
return (
|
||||
<div className="metrics-source-select-container">
|
||||
{signalSourceChangeEnabled && (
|
||||
<Select
|
||||
<SelectSimple
|
||||
className="source-selector"
|
||||
placeholder="Source"
|
||||
options={SOURCE_OPTIONS}
|
||||
items={SOURCE_OPTIONS}
|
||||
value={source}
|
||||
defaultValue="metrics"
|
||||
data-testid={`metrics-source-selector-${index}`}
|
||||
onChange={handleSignalSourceChange}
|
||||
testId={`metrics-source-selector-${index}`}
|
||||
onChange={(value): void => handleSignalSourceChange(value as string)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -22,34 +22,35 @@
|
||||
font-style: normal;
|
||||
font-weight: var(--font-weight-normal);
|
||||
|
||||
color: var(--l2-foreground);
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground));
|
||||
}
|
||||
|
||||
.tab {
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
border-left: none;
|
||||
min-width: 120px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
|
||||
&:first-child {
|
||||
border-left: 1px solid var(--l1-border);
|
||||
border-left: 1px solid
|
||||
var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
}
|
||||
|
||||
.tab::before {
|
||||
background: var(--l1-border);
|
||||
background: var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
|
||||
.selected-view {
|
||||
color: var(--text-robin-500);
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
|
||||
display: none;
|
||||
}
|
||||
|
||||
.selected-view::before {
|
||||
background: var(--l1-border);
|
||||
background: var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +59,7 @@
|
||||
height: 30px;
|
||||
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: var(--l3-background);
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@@ -71,10 +72,13 @@
|
||||
align-items: center;
|
||||
|
||||
.having-filter-select-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
background: var(--query-builder-v2-background-color, var(--l2-background));
|
||||
padding-right: 38px;
|
||||
|
||||
.having-filter-select-editor {
|
||||
border-radius: 2px;
|
||||
@@ -99,15 +103,17 @@
|
||||
}
|
||||
|
||||
.cm-content {
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
border-left-width: 0px;
|
||||
border-right-width: 0px;
|
||||
padding: 0px !important;
|
||||
background-color: var(--l2-background) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
|
||||
&:focus-within {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,17 +217,32 @@
|
||||
}
|
||||
|
||||
.cm-line {
|
||||
line-height: 36px !important;
|
||||
min-height: 34px;
|
||||
line-height: 32px !important;
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
background-color: var(--l2-background) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
|
||||
&,
|
||||
.ͼ1a {
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground));
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
@@ -230,8 +251,11 @@
|
||||
}
|
||||
|
||||
.chip-decorator {
|
||||
background: var(--l3-background) !important;
|
||||
color: var(--l1-foreground) !important;
|
||||
background: var(
|
||||
--query-builder-v2-chip-decorator-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
|
||||
border-radius: 4px;
|
||||
padding: 2px 4px;
|
||||
margin-right: 4px;
|
||||
@@ -239,24 +263,36 @@
|
||||
}
|
||||
|
||||
.cm-selectionBackground {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
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(--l2-border);
|
||||
background: var(--l2-background);
|
||||
height: 38px;
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: var(--query-builder-v2-background-color, var(--l2-background));
|
||||
height: 100%;
|
||||
width: 38px;
|
||||
|
||||
border-left: transparent;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
color: var(--l2-foreground) !important;
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
|
||||
|
||||
&.error {
|
||||
.cm-editor {
|
||||
@@ -51,14 +51,15 @@
|
||||
|
||||
.cm-content {
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
padding: 0px !important;
|
||||
background-color: var(--l1-background) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
|
||||
&:focus-within {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@
|
||||
right: 0px !important;
|
||||
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: linear-gradient(
|
||||
139deg,
|
||||
color-mix(in srgb, var(--card) 80%, transparent) 0%,
|
||||
@@ -118,7 +119,7 @@
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
color: var(--l2-foreground) !important;
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
|
||||
.cm-completionIcon {
|
||||
@@ -127,7 +128,10 @@
|
||||
|
||||
&:hover,
|
||||
&[aria-selected='true'] {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
color: var(--l1-foreground) !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
@@ -142,15 +146,24 @@
|
||||
.cm-line {
|
||||
line-height: 36px !important;
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
background-color: var(--l2-background) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
|
||||
::-moz-selection {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
@@ -159,8 +172,11 @@
|
||||
}
|
||||
|
||||
.chip-decorator {
|
||||
background: var(--l3-background) !important;
|
||||
color: var(--l1-foreground) !important;
|
||||
background: var(
|
||||
--query-builder-v2-chip-decorator-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
color: var(--query-builder-v2-color, var(--l1-foreground)) !important;
|
||||
border-radius: 4px;
|
||||
padding: 2px 4px;
|
||||
margin-right: 4px;
|
||||
@@ -168,7 +184,10 @@
|
||||
}
|
||||
|
||||
.cm-selectionBackground {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
}
|
||||
@@ -201,12 +220,11 @@
|
||||
|
||||
.close-btn {
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l1-background);
|
||||
height: 38px;
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: var(--query-builder-v2-background-color, var(--l2-background));
|
||||
height: 100%;
|
||||
width: 38px;
|
||||
|
||||
border-left: transparent;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
}
|
||||
@@ -217,13 +235,13 @@
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--l1-foreground);
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground));
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
@@ -240,7 +258,7 @@
|
||||
input {
|
||||
max-width: 120px;
|
||||
&::placeholder {
|
||||
color: var(--l2-foreground);
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,8 +269,8 @@
|
||||
|
||||
.query-aggregation-error-popover {
|
||||
.ant-popover-inner {
|
||||
background-color: var(--l1-border);
|
||||
border: 1px solid var(--l1-border);
|
||||
background-color: var(--query-builder-v2-border-color, var(--l2-border));
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.add-trace-operator-button,
|
||||
.add-new-query-button,
|
||||
.add-formula-button {
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l2-background);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
background: var(--query-builder-v2-background-color, var(--l2-background));
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
@@ -34,11 +34,14 @@
|
||||
.query-status-container {
|
||||
width: 32px;
|
||||
|
||||
background-color: var(--l1-background) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
border-radius: 2px;
|
||||
border-top-left-radius: 0px !important;
|
||||
border-bottom-left-radius: 0px !important;
|
||||
@@ -77,16 +80,16 @@
|
||||
|
||||
.cm-content {
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
padding: 0px !important;
|
||||
|
||||
&:focus-within {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
}
|
||||
|
||||
&.cm-focused {
|
||||
outline: 1px solid var(--l1-border);
|
||||
outline: 1px solid var(--query-builder-v2-border-color, var(--l2-border));
|
||||
}
|
||||
|
||||
.cm-tooltip-autocomplete {
|
||||
@@ -148,11 +151,17 @@
|
||||
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
|
||||
background-color: var(--l1-background) !important;
|
||||
color: var(--l2-foreground) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground)) !important;
|
||||
|
||||
&:hover {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
}
|
||||
|
||||
.cm-completionIcon {
|
||||
@@ -160,7 +169,10 @@
|
||||
}
|
||||
|
||||
&[aria-selected='true'] {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
@@ -172,25 +184,49 @@
|
||||
}
|
||||
|
||||
.cm-line {
|
||||
line-height: 34px !important;
|
||||
line-height: 36px !important;
|
||||
font-family: 'Space Mono', monospace !important;
|
||||
background-color: var(--l2-background) !important;
|
||||
background-color: var(
|
||||
--query-builder-v2-background-color,
|
||||
var(--l2-background)
|
||||
) !important;
|
||||
|
||||
&,
|
||||
.ͼ1a {
|
||||
color: var(--query-builder-v2-color, var(--l2-foreground));
|
||||
}
|
||||
|
||||
::-moz-selection {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cm-selectionBackground {
|
||||
background: var(--l3-background) !important;
|
||||
background: var(
|
||||
--query-builder-v2-selection-background-color,
|
||||
var(--l3-background)
|
||||
) !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
.cm-placeholder {
|
||||
color: var(
|
||||
--query-builder-v2-placeholder-color,
|
||||
var(--l3-foreground)
|
||||
) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cursor-position {
|
||||
|
||||
@@ -14,7 +14,8 @@ import {
|
||||
ComboboxList,
|
||||
ComboboxTrigger,
|
||||
} from '@signozhq/ui/combobox';
|
||||
import { Skeleton, Switch, Tooltip } from 'antd';
|
||||
import { Skeleton, Tooltip } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
@@ -281,9 +282,8 @@ 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' }}
|
||||
checked={showIP ?? true}
|
||||
value={showIP ?? true}
|
||||
onChange={(checked): void => {
|
||||
logEvent('API Monitoring: Show IP addresses clicked', {
|
||||
showIP: checked,
|
||||
|
||||
@@ -4,7 +4,8 @@ import type {
|
||||
TableColumnsType as ColumnsType,
|
||||
TableColumnType as ColumnType,
|
||||
} from 'antd';
|
||||
import { Button, Dropdown, Flex, MenuProps, Switch } from 'antd';
|
||||
import { Button, Dropdown, Flex, MenuProps } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import LaunchChatSupport from 'components/LaunchChatSupport/LaunchChatSupport';
|
||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||
@@ -60,9 +61,7 @@ function DynamicColumnTable({
|
||||
|
||||
const onToggleHandler =
|
||||
(index: number, column: ColumnGroupType<any> | ColumnType<any>) =>
|
||||
(checked: boolean, event: React.MouseEvent<HTMLButtonElement>): void => {
|
||||
event.stopPropagation();
|
||||
|
||||
(checked: boolean): void => {
|
||||
if (shouldSendAlertsLogEvent) {
|
||||
logEvent('Alert: Column toggled', {
|
||||
column: column?.title,
|
||||
@@ -88,10 +87,14 @@ function DynamicColumnTable({
|
||||
const items: MenuProps['items'] =
|
||||
dynamicColumns?.map((column, index) => ({
|
||||
label: (
|
||||
<div className="dynamicColumnsTable-items">
|
||||
<div
|
||||
className="dynamicColumnsTable-items"
|
||||
onClick={(e): void => e.stopPropagation()}
|
||||
role="presentation"
|
||||
>
|
||||
<div>{column.title?.toString()}</div>
|
||||
<Switch
|
||||
checked={columnsData?.findIndex((c) => c.key === column.key) !== -1}
|
||||
value={columnsData?.findIndex((c) => c.key === column.key) !== -1}
|
||||
onChange={onToggleHandler(index, column)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { CircleAlert, RefreshCw } from '@signozhq/icons';
|
||||
import { Checkbox, Select } from 'antd';
|
||||
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
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';
|
||||
|
||||
@@ -74,7 +73,6 @@ interface BaseProps {
|
||||
id?: string;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
getPopupContainer?: (trigger: HTMLElement) => HTMLElement;
|
||||
roles?: AuthtypesRoleDTO[];
|
||||
loading?: boolean;
|
||||
isError?: boolean;
|
||||
@@ -112,14 +110,13 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
|
||||
});
|
||||
|
||||
const roles = externalRoles ?? data?.data ?? [];
|
||||
const options = getRoleOptions(roles);
|
||||
const items: ComboboxSimpleItem[] = getRoleOptions(roles);
|
||||
|
||||
const {
|
||||
mode,
|
||||
id,
|
||||
placeholder = 'Select role',
|
||||
className,
|
||||
getPopupContainer = popupContainer,
|
||||
loading = internalLoading,
|
||||
isError = internalError,
|
||||
error = convertToApiError(internalErrorObj),
|
||||
@@ -127,55 +124,47 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
|
||||
disabled,
|
||||
} = props;
|
||||
|
||||
const notFoundContent = isError ? (
|
||||
<ErrorContent error={error} onRefetch={onRefetch} />
|
||||
) : undefined;
|
||||
const emptyPlaceholder = isError
|
||||
? error?.message || 'Failed to load roles'
|
||||
: 'No roles available';
|
||||
|
||||
if (mode === 'multiple') {
|
||||
const { value = [], onChange } = props as MultipleProps;
|
||||
return (
|
||||
<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}
|
||||
/>
|
||||
<>
|
||||
<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} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const { value, onChange, allowClear = true } = props as SingleProps;
|
||||
const { value, onChange } = props as SingleProps;
|
||||
return (
|
||||
<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}
|
||||
/>
|
||||
<>
|
||||
<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} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,6 @@ 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"
|
||||
|
||||
@@ -190,7 +190,6 @@ 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"
|
||||
|
||||
@@ -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 } from 'antd';
|
||||
import { Skeleton, Table, Tooltip } 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,28 +110,34 @@ function buildColumns({
|
||||
onClick: (e): void => e.stopPropagation(),
|
||||
style: { cursor: 'default' },
|
||||
}),
|
||||
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"
|
||||
render: (_, record): JSX.Element => {
|
||||
const tooltipTitle = isDisabled ? 'Service account disabled' : 'Revoke Key';
|
||||
return (
|
||||
<AuthZTooltip
|
||||
checks={[
|
||||
buildAPIKeyDeletePermission(record.id),
|
||||
buildSADetachPermission(accountId),
|
||||
]}
|
||||
enabled={!isDisabled && !!accountId}
|
||||
>
|
||||
<X size={12} />
|
||||
</Button>
|
||||
</AuthZTooltip>
|
||||
),
|
||||
<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>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { useMemo } from 'react';
|
||||
import { SolidAlertTriangle } from '@signozhq/icons';
|
||||
import { Select, Tooltip } from 'antd';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import {
|
||||
ComboboxSimple,
|
||||
ComboboxSimpleGroup,
|
||||
ComboboxSimpleItem,
|
||||
} from '@signozhq/ui/combobox';
|
||||
import { Tooltip } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { UniversalYAxisUnitMappings } from './constants';
|
||||
@@ -42,69 +46,53 @@ function YAxisUnitSelector({
|
||||
return '';
|
||||
}, [initialValue, value, loading]);
|
||||
|
||||
const handleSearch = (
|
||||
searchTerm: string,
|
||||
currentOption: DefaultOptionType | undefined,
|
||||
): boolean => {
|
||||
if (!currentOption?.value) {
|
||||
return false;
|
||||
}
|
||||
const categoriesToRender = useMemo(
|
||||
() => categoriesOverride || getYAxisCategories(source),
|
||||
[categoriesOverride, source],
|
||||
);
|
||||
|
||||
const search = searchTerm.toLowerCase();
|
||||
const unitId = currentOption.value.toString().toLowerCase();
|
||||
const unitLabel = currentOption.children?.toString().toLowerCase() || '';
|
||||
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],
|
||||
);
|
||||
|
||||
// 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 handleChange = (val: string | string[]): void => {
|
||||
onChange(val as UniversalYAxisUnit);
|
||||
};
|
||||
|
||||
const categoriesToRender = useMemo(() => {
|
||||
return categoriesOverride || getYAxisCategories(source);
|
||||
}, [categoriesOverride, source]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames('y-axis-unit-selector-component', containerClassName)}
|
||||
>
|
||||
<Select
|
||||
showSearch
|
||||
value={universalUnit}
|
||||
onChange={onChange}
|
||||
<ComboboxSimple
|
||||
value={universalUnit ?? undefined}
|
||||
onChange={handleChange}
|
||||
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,
|
||||
})}
|
||||
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>
|
||||
testId={dataTestId}
|
||||
groups={groups}
|
||||
/>
|
||||
{incompatibleUnitMessage && (
|
||||
<Tooltip title={incompatibleUnitMessage}>
|
||||
<SolidAlertTriangle role="img" aria-label="warning" size="md" />
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
.y-axis-unit-selector-component {
|
||||
.ant-select {
|
||||
--combobox-trigger-background-color: var(--l2-background);
|
||||
--combobox-trigger-border-color: var(--l2-border);
|
||||
|
||||
[data-slot='combobox-trigger'] {
|
||||
width: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ describe('createGuardedRoute', () => {
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render error fallback when API error occurs', async () => {
|
||||
it('should render the component when API error occurs (fail open)', async () => {
|
||||
server.use(
|
||||
rest.post(AUTHZ_CHECK_URL, (_req, res, ctx) => {
|
||||
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
|
||||
@@ -230,12 +230,8 @@ describe('createGuardedRoute', () => {
|
||||
render(<GuardedComponent {...props} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/Something went wrong/i)).toBeInTheDocument();
|
||||
expect(screen.getByText('Test Component: test-value')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.queryByText('Test Component: test-value'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render no permissions fallback when permission is denied', async () => {
|
||||
@@ -9,14 +9,11 @@ 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 {
|
||||
@@ -63,7 +60,6 @@ export function createGuardedRoute<P extends object, R extends AuthZRelation>(
|
||||
relation={relation}
|
||||
object={resolvedObject}
|
||||
fallbackOnLoading={<AppLoading />}
|
||||
fallbackOnError={onErrorFallback}
|
||||
fallbackOnNoPermissions={(response): ReactElement => (
|
||||
<OnNoPermissionsFallback {...response} />
|
||||
)}
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
.contributors-row {
|
||||
height: 80px;
|
||||
}
|
||||
.top-contributors-progress {
|
||||
--progress-background: transparent;
|
||||
}
|
||||
|
||||
&__content {
|
||||
.ant-table {
|
||||
&-cell {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Progress, Table, TableColumnsType as ColumnsType } from 'antd';
|
||||
import { Table, TableColumnsType as ColumnsType } from 'antd';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { ConditionalAlertPopover } from 'container/AlertHistory/AlertPopover/AlertPopover';
|
||||
import AlertLabels from 'pages/AlertDetails/AlertHeader/AlertLabels/AlertLabels';
|
||||
@@ -51,8 +52,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>
|
||||
),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Select } from 'antd';
|
||||
import { ComboboxSimple } from '@signozhq/ui/combobox';
|
||||
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: IBuilderQuery['groupBy']) => {
|
||||
(value: string[]) => {
|
||||
const newGroupBy = [];
|
||||
|
||||
for (let index = 0; index < value.length; index++) {
|
||||
const element = value[index] as unknown as string;
|
||||
const element = value[index];
|
||||
|
||||
// Check if the key exists in our cached options first
|
||||
if (allAvailableGroupByOptions[element]) {
|
||||
@@ -242,17 +242,14 @@ function AllEndPoints({
|
||||
</div>
|
||||
<div className="group-by-container">
|
||||
<div className="group-by-label"> Group by </div>
|
||||
<Select
|
||||
<ComboboxSimple
|
||||
className="group-by-select"
|
||||
loading={isLoadingGroupByFilters}
|
||||
mode="multiple"
|
||||
value={groupBy}
|
||||
allowClear
|
||||
maxTagCount="responsive"
|
||||
multiple
|
||||
value={groupBy.map((g) => g.key)}
|
||||
placeholder="Search for attribute"
|
||||
options={groupByOptions}
|
||||
onChange={handleGroupByChange}
|
||||
onSearch={(value: string): void => setGroupBySearchValue(value)}
|
||||
items={groupByOptions}
|
||||
onChange={(value): void => handleGroupByChange(value as string[])}
|
||||
/>{' '}
|
||||
</div>
|
||||
<div className="endpoints-table-container">
|
||||
|
||||
@@ -141,12 +141,9 @@
|
||||
|
||||
.progress-container {
|
||||
width: 158px;
|
||||
.ant-progress {
|
||||
margin: 0;
|
||||
|
||||
.ant-progress-text {
|
||||
font-weight: 600;
|
||||
}
|
||||
span {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,14 +211,14 @@
|
||||
|
||||
.group-by-label {
|
||||
display: flex;
|
||||
padding: 6px 15px;
|
||||
padding: 4px 15px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--l2-border);
|
||||
border-right: none;
|
||||
background: var(--l3-background);
|
||||
|
||||
@@ -230,18 +227,15 @@
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px;
|
||||
line-height: 22px;
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.group-by-select {
|
||||
width: 100%;
|
||||
.ant-select-selector {
|
||||
font-size: 14px;
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l3-background);
|
||||
}
|
||||
box-sizing: border-box;
|
||||
|
||||
--combobox-trigger-border-radius: 0px;
|
||||
}
|
||||
}
|
||||
// Add border-bottom to table cells when pagination is not present
|
||||
@@ -464,14 +458,13 @@
|
||||
}
|
||||
|
||||
.endpoint-details-filters-container-dropdown {
|
||||
width: 120px;
|
||||
width: 150px;
|
||||
border-right: 1px solid var(--l1-border);
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ant-select-single {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
--combobox-trigger-border-color: transparent;
|
||||
}
|
||||
|
||||
.endpoint-details-filters-container-search {
|
||||
|
||||
@@ -263,7 +263,6 @@ function EndPointDetails({
|
||||
setSelectedEndPointName={setSelectedEndPointName}
|
||||
endPointDropDownDataQuery={endPointDropDownDataQuery}
|
||||
parentContainerDiv=".endpoint-details-filters-container"
|
||||
dropdownStyle={{ width: 'calc(100% - 36px)' }}
|
||||
/>
|
||||
</div>
|
||||
<div className="endpoint-details-filters-container-search">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { QueryFunctionContext, useQueries, useQuery } from 'react-query';
|
||||
import { Spin, Switch, Table, Tooltip } from 'antd';
|
||||
import { Spin, 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';
|
||||
@@ -170,11 +171,7 @@ function TopErrors({
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
<Switch
|
||||
checked={showStatusCodeErrors}
|
||||
onChange={setShowStatusCodeErrors}
|
||||
size="small"
|
||||
/>
|
||||
<Switch value={showStatusCodeErrors} onChange={setShowStatusCodeErrors} />
|
||||
<span style={{ color: 'white', fontSize: '14px' }}>
|
||||
Status Message Exists
|
||||
</span>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useQueries } from 'react-query';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Progress, Skeleton, Tooltip } from 'antd';
|
||||
import { Skeleton, Tooltip } from 'antd';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { ENTITY_VERSION_V5 } from 'constants/app';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
@@ -136,12 +137,11 @@ function DomainMetrics({
|
||||
<Tooltip title={formattedDomainMetricsData.errorRate}>
|
||||
{formattedDomainMetricsData.errorRate !== '-' ? (
|
||||
<Progress
|
||||
status="active"
|
||||
percent={Number(
|
||||
Number(formattedDomainMetricsData.errorRate).toFixed(2),
|
||||
)}
|
||||
strokeLinecap="butt"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const errorRatePercent = Number(
|
||||
Number(formattedDomainMetricsData.errorRate).toFixed(2),
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useMemo } from 'react';
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Progress, Skeleton, Tooltip } from 'antd';
|
||||
import { Skeleton, Tooltip } from 'antd';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import {
|
||||
getDisplayValue,
|
||||
@@ -80,10 +81,9 @@ function EndPointMetrics({
|
||||
<Tooltip title={metricsData?.errorRate}>
|
||||
{metricsData?.errorRate !== '-' ? (
|
||||
<Progress
|
||||
status="active"
|
||||
percent={Number(Number(metricsData?.errorRate ?? 0).toFixed(2))}
|
||||
strokeLinecap="butt"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const errorRatePercent = Number(
|
||||
Number(metricsData?.errorRate ?? 0).toFixed(2),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import { Select } from 'antd';
|
||||
import { ComboboxSimple, ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
import { getFormattedEndPointDropDownData } from 'container/ApiMonitoring/utils';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
|
||||
@@ -22,40 +22,33 @@ function EndPointsDropDown({
|
||||
selectedEndPointName,
|
||||
setSelectedEndPointName,
|
||||
endPointDropDownDataQuery,
|
||||
parentContainerDiv,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
parentContainerDiv: _parentContainerDiv,
|
||||
dropdownStyle,
|
||||
}: EndPointsDropDownProps): JSX.Element {
|
||||
const { data, isLoading, isFetching } = endPointDropDownDataQuery;
|
||||
|
||||
const handleChange = (value: string): void => {
|
||||
setSelectedEndPointName(value);
|
||||
const handleChange = (value: string | string[]): void => {
|
||||
setSelectedEndPointName(value as string);
|
||||
};
|
||||
|
||||
const formattedData = useMemo(
|
||||
() =>
|
||||
getFormattedEndPointDropDownData(data?.payload.data.result[0].table.rows),
|
||||
getFormattedEndPointDropDownData(
|
||||
data?.payload.data.result[0].table.rows,
|
||||
) as ComboboxSimpleItem[],
|
||||
[data?.payload.data.result],
|
||||
);
|
||||
|
||||
return (
|
||||
<Select
|
||||
<ComboboxSimple
|
||||
value={selectedEndPointName || undefined}
|
||||
placeholder="Select endpoint"
|
||||
loading={isLoading || isFetching}
|
||||
style={{ width: '100%' }}
|
||||
style={{ width: '100%', ...dropdownStyle }}
|
||||
onChange={handleChange}
|
||||
options={formattedData}
|
||||
getPopupContainer={
|
||||
parentContainerDiv
|
||||
? (): HTMLElement =>
|
||||
document.querySelector(parentContainerDiv) as HTMLElement
|
||||
: (triggerNode): HTMLElement => triggerNode.parentNode as HTMLElement
|
||||
}
|
||||
dropdownStyle={dropdownStyle}
|
||||
allowClear
|
||||
onClear={(): void => {
|
||||
setSelectedEndPointName('');
|
||||
}}
|
||||
items={formattedData}
|
||||
virtualized
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Progress, TableColumnType as ColumnType, Tag, Tooltip } from 'antd';
|
||||
import { TableColumnType as ColumnType, Tag, Tooltip } from 'antd';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import { convertFiltersToExpressionWithExistingQuery } from 'components/QueryBuilderV2/utils';
|
||||
import {
|
||||
FiltersType,
|
||||
@@ -257,10 +258,9 @@ export const columnsConfig: ColumnType<APIDomainsRowData>[] = [
|
||||
errorRate === 'n/a' || errorRate === '-' ? 0 : errorRate;
|
||||
return (
|
||||
<Progress
|
||||
status="active"
|
||||
percent={Number((errorRateValue as number).toFixed(2))}
|
||||
strokeLinecap="butt"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const errorRatePercent = Number((errorRateValue as number).toFixed(2));
|
||||
if (errorRatePercent >= 90) {
|
||||
@@ -1022,14 +1022,13 @@ 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"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const errorRatePercent = Number((errorRate as number).toFixed(1));
|
||||
if (errorRatePercent >= 90) {
|
||||
@@ -2514,10 +2513,9 @@ export const dependentServicesColumns: ColumnType<DependentServicesData>[] = [
|
||||
render: (errorPercentage: number | string): React.ReactNode =>
|
||||
errorPercentage !== '-' ? (
|
||||
<Progress
|
||||
status="active"
|
||||
percent={Number((errorPercentage as number).toFixed(2))}
|
||||
strokeLinecap="butt"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const errorPercentagePercent = Number(
|
||||
(errorPercentage as number).toFixed(2),
|
||||
@@ -3022,14 +3020,13 @@ export const getAllEndpointsWidgetData = (
|
||||
),
|
||||
F1: (errorRate: any): ReactNode => (
|
||||
<Progress
|
||||
status="active"
|
||||
percent={Number(
|
||||
(
|
||||
(errorRate === 'n/a' || errorRate === '-' ? 0 : errorRate) as number
|
||||
).toFixed(2),
|
||||
)}
|
||||
strokeLinecap="butt"
|
||||
size="small"
|
||||
showInfo
|
||||
strokeColor={((): string => {
|
||||
const errorRatePercent = Number(
|
||||
(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { memo, useMemo } from 'react';
|
||||
import { ChevronLeft, ChevronRight } from '@signozhq/icons';
|
||||
import { Button, Flex, Select } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Button, Flex } 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,20 +59,18 @@ function Controls({
|
||||
</Button>
|
||||
|
||||
{showSizeChanger && (
|
||||
<Select<Pagination['limit']>
|
||||
<SelectSimple
|
||||
style={defaultSelectStyle}
|
||||
loading={isLoading}
|
||||
value={countPerPage}
|
||||
onChange={handleCountItemsPerPageChange}
|
||||
getPopupContainer={popupContainer}
|
||||
>
|
||||
{perPageOptions.map((count) => (
|
||||
<Select.Option
|
||||
key={count}
|
||||
value={count}
|
||||
>{`${count} / page`}</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
disabled={isLoading}
|
||||
value={String(countPerPage)}
|
||||
onChange={(value): void =>
|
||||
handleCountItemsPerPageChange(Number(value) as Pagination['limit'])
|
||||
}
|
||||
items={perPageOptions.map((count) => ({
|
||||
value: String(count),
|
||||
label: `${count} / page`,
|
||||
}))}
|
||||
/>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
|
||||
@@ -61,10 +61,6 @@
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
&:not(:first-of-type) {
|
||||
margin-left: 24px !important;
|
||||
}
|
||||
|
||||
[aria-selected='false'] {
|
||||
.periscope-tab {
|
||||
color: var(--l2-foreground);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Button, Select, Tooltip } from 'antd';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import classNames from 'classnames';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
@@ -231,15 +232,18 @@ function AlertThreshold({
|
||||
<Typography.Text className="sentence-text">
|
||||
Send a notification when
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={thresholdState.selectedQuery}
|
||||
onChange={handleSelectedQueryChange}
|
||||
onChange={(value): void => handleSelectedQueryChange(value as string)}
|
||||
style={{ width: 80 }}
|
||||
options={queryNames}
|
||||
items={queryNames.map((q) => ({
|
||||
value: String(q.value),
|
||||
label: q.label as React.ReactNode,
|
||||
}))}
|
||||
data-testid="alert-threshold-query-select"
|
||||
/>
|
||||
<Typography.Text className="sentence-text">is</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={
|
||||
(normalizeOperator(thresholdState.operator) ??
|
||||
thresholdState.operator) as AlertThresholdOperator
|
||||
@@ -247,17 +251,17 @@ function AlertThreshold({
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_OPERATOR',
|
||||
payload: value,
|
||||
payload: value as AlertThresholdOperator,
|
||||
});
|
||||
}}
|
||||
style={{ width: 180 }}
|
||||
options={THRESHOLD_OPERATOR_OPTIONS}
|
||||
items={THRESHOLD_OPERATOR_OPTIONS}
|
||||
data-testid="alert-threshold-operator-select"
|
||||
/>
|
||||
<Typography.Text className="sentence-text">
|
||||
the threshold(s)
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={
|
||||
(normalizeMatchType(thresholdState.matchType) ??
|
||||
thresholdState.matchType) as AlertThresholdMatchType
|
||||
@@ -265,11 +269,11 @@ function AlertThreshold({
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_MATCH_TYPE',
|
||||
payload: value,
|
||||
payload: value as AlertThresholdMatchType,
|
||||
});
|
||||
}}
|
||||
style={{ width: 180 }}
|
||||
options={matchTypeOptionsWithTooltips}
|
||||
items={matchTypeOptionsWithTooltips}
|
||||
data-testid="alert-threshold-match-type-select"
|
||||
/>
|
||||
<Typography.Text className="sentence-text">
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Select } from 'antd';
|
||||
import { ComboboxSimple } from '@signozhq/ui/combobox';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
import {
|
||||
@@ -18,19 +18,13 @@ import {
|
||||
} from '../context/types';
|
||||
import { normalizeMatchType, normalizeOperator } from '../utils';
|
||||
import { AnomalyAndThresholdProps } from './types';
|
||||
import {
|
||||
getQueryNames,
|
||||
NotificationChannelsNotFoundContent,
|
||||
RoutingPolicyBanner,
|
||||
} from './utils';
|
||||
import { getQueryNames, RoutingPolicyBanner } from './utils';
|
||||
|
||||
function AnomalyThreshold({
|
||||
channels,
|
||||
isLoadingChannels,
|
||||
isErrorChannels,
|
||||
refreshChannels,
|
||||
}: AnomalyAndThresholdProps): JSX.Element {
|
||||
const { user } = useAppContext();
|
||||
const {
|
||||
thresholdState,
|
||||
setThresholdState,
|
||||
@@ -42,13 +36,14 @@ function AnomalyThreshold({
|
||||
|
||||
const queryNames = getQueryNames(currentQuery);
|
||||
|
||||
const deviationOptions = useMemo(() => {
|
||||
const options = [];
|
||||
for (let i = 1; i <= 7; i++) {
|
||||
options.push({ label: i.toString(), value: i });
|
||||
}
|
||||
return options;
|
||||
}, []);
|
||||
const deviationOptions = useMemo(
|
||||
() =>
|
||||
Array.from({ length: 7 }, (_, i) => ({
|
||||
label: (i + 1).toString(),
|
||||
value: (i + 1).toString(),
|
||||
})),
|
||||
[],
|
||||
);
|
||||
|
||||
const updateThreshold = (
|
||||
id: string,
|
||||
@@ -71,16 +66,16 @@ function AnomalyThreshold({
|
||||
<Typography.Text data-testid="notification-text" className="sentence-text">
|
||||
Send notification when the observed value for
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={thresholdState.selectedQuery}
|
||||
data-testid="query-select"
|
||||
testId="query-select"
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_SELECTED_QUERY',
|
||||
payload: value,
|
||||
payload: value as string,
|
||||
});
|
||||
}}
|
||||
options={queryNames}
|
||||
items={queryNames}
|
||||
/>
|
||||
<Typography.Text
|
||||
data-testid="evaluation-window-text"
|
||||
@@ -88,16 +83,16 @@ function AnomalyThreshold({
|
||||
>
|
||||
during the last
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={thresholdState.evaluationWindow}
|
||||
data-testid="evaluation-window-select"
|
||||
testId="evaluation-window-select"
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_EVALUATION_WINDOW',
|
||||
payload: value,
|
||||
payload: value as string,
|
||||
});
|
||||
}}
|
||||
options={ANOMALY_TIME_DURATION_OPTIONS}
|
||||
items={ANOMALY_TIME_DURATION_OPTIONS}
|
||||
/>
|
||||
</div>
|
||||
<div className="alert-condition-sentence">
|
||||
@@ -105,34 +100,34 @@ function AnomalyThreshold({
|
||||
<Typography.Text data-testid="threshold-text" className="sentence-text">
|
||||
is
|
||||
</Typography.Text>
|
||||
<Select
|
||||
value={thresholdState.thresholds[0].thresholdValue}
|
||||
data-testid="threshold-value-select"
|
||||
<SelectSimple
|
||||
value={thresholdState.thresholds[0].thresholdValue?.toString()}
|
||||
testId="threshold-value-select"
|
||||
onChange={(value): void => {
|
||||
updateThreshold(
|
||||
thresholdState.thresholds[0].id,
|
||||
'thresholdValue',
|
||||
value.toString(),
|
||||
(value as string).toString(),
|
||||
);
|
||||
}}
|
||||
options={deviationOptions}
|
||||
items={deviationOptions}
|
||||
/>
|
||||
<Typography.Text data-testid="deviations-text" className="sentence-text">
|
||||
deviations
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={
|
||||
(normalizeOperator(thresholdState.operator) ??
|
||||
thresholdState.operator) as AlertThresholdOperator
|
||||
}
|
||||
data-testid="operator-select"
|
||||
testId="operator-select"
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_OPERATOR',
|
||||
payload: value,
|
||||
payload: value as AlertThresholdOperator,
|
||||
});
|
||||
}}
|
||||
options={ANOMALY_THRESHOLD_OPERATOR_OPTIONS}
|
||||
items={ANOMALY_THRESHOLD_OPERATOR_OPTIONS}
|
||||
/>
|
||||
<Typography.Text
|
||||
data-testid="predicted-data-text"
|
||||
@@ -140,19 +135,19 @@ function AnomalyThreshold({
|
||||
>
|
||||
the predicted data
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={
|
||||
(normalizeMatchType(thresholdState.matchType) ??
|
||||
thresholdState.matchType) as AlertThresholdMatchType
|
||||
}
|
||||
data-testid="match-type-select"
|
||||
testId="match-type-select"
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_MATCH_TYPE',
|
||||
payload: value,
|
||||
payload: value as AlertThresholdMatchType,
|
||||
});
|
||||
}}
|
||||
options={ANOMALY_THRESHOLD_MATCH_TYPE_OPTIONS}
|
||||
items={ANOMALY_THRESHOLD_MATCH_TYPE_OPTIONS}
|
||||
/>
|
||||
</div>
|
||||
{/* Sentence 3 */}
|
||||
@@ -160,16 +155,16 @@ function AnomalyThreshold({
|
||||
<Typography.Text data-testid="using-the-text" className="sentence-text">
|
||||
using the
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={thresholdState.algorithm}
|
||||
data-testid="algorithm-select"
|
||||
testId="algorithm-select"
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_ALGORITHM',
|
||||
payload: value,
|
||||
payload: value as string,
|
||||
});
|
||||
}}
|
||||
options={ANOMALY_ALGORITHM_OPTIONS}
|
||||
items={ANOMALY_ALGORITHM_OPTIONS}
|
||||
/>
|
||||
<Typography.Text
|
||||
data-testid="algorithm-with-text"
|
||||
@@ -177,16 +172,16 @@ function AnomalyThreshold({
|
||||
>
|
||||
algorithm with
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<SelectSimple
|
||||
value={thresholdState.seasonality}
|
||||
data-testid="seasonality-select"
|
||||
testId="seasonality-select"
|
||||
onChange={(value): void => {
|
||||
setThresholdState({
|
||||
type: 'SET_SEASONALITY',
|
||||
payload: value,
|
||||
payload: value as string,
|
||||
});
|
||||
}}
|
||||
options={ANOMALY_SEASONALITY_OPTIONS}
|
||||
items={ANOMALY_SEASONALITY_OPTIONS}
|
||||
/>
|
||||
{notificationSettings.routingPolicies ? (
|
||||
<>
|
||||
@@ -196,35 +191,25 @@ function AnomalyThreshold({
|
||||
>
|
||||
seasonality to
|
||||
</Typography.Text>
|
||||
<Select
|
||||
<ComboboxSimple
|
||||
value={thresholdState.thresholds[0].channels}
|
||||
onChange={(value): void =>
|
||||
updateThreshold(thresholdState.thresholds[0].id, 'channels', value)
|
||||
updateThreshold(
|
||||
thresholdState.thresholds[0].id,
|
||||
'channels',
|
||||
value as string[],
|
||||
)
|
||||
}
|
||||
style={{ width: 350 }}
|
||||
options={channels.map((channel) => ({
|
||||
items={channels.map((channel) => ({
|
||||
value: channel.id,
|
||||
label: channel.name,
|
||||
}))}
|
||||
mode="multiple"
|
||||
multiple
|
||||
placeholder="Select notification channels"
|
||||
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}
|
||||
/>
|
||||
}
|
||||
loading={isLoadingChannels}
|
||||
className={isErrorChannels ? 'error' : undefined}
|
||||
emptyPlaceholder="No channels found"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Button, Input, Select, Tooltip } from 'antd';
|
||||
import { Button, Input, Tooltip } from 'antd';
|
||||
import { ComboboxSimple } from '@signozhq/ui/combobox';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
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,36 +18,38 @@ 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 = (
|
||||
<Select
|
||||
<SelectSimple
|
||||
placeholder="Unit"
|
||||
value={threshold.unit ? threshold.unit : null}
|
||||
onChange={(value): void => updateThreshold(threshold.id, 'unit', value)}
|
||||
value={threshold.unit ? threshold.unit : undefined}
|
||||
onChange={(value): void =>
|
||||
updateThreshold(threshold.id, 'unit', value as string)
|
||||
}
|
||||
style={{ width: 150 }}
|
||||
options={units}
|
||||
items={units}
|
||||
disabled={units.length === 0}
|
||||
data-testid="threshold-unit-select"
|
||||
testId="threshold-unit-select"
|
||||
/>
|
||||
);
|
||||
if (units.length === 0) {
|
||||
component = (
|
||||
<Tooltip trigger="hover" title="No compatible units available">
|
||||
<Select
|
||||
<SelectSimple
|
||||
placeholder="Unit"
|
||||
value={threshold.unit ? threshold.unit : null}
|
||||
onChange={(value): void => updateThreshold(threshold.id, 'unit', value)}
|
||||
value={threshold.unit ? threshold.unit : undefined}
|
||||
onChange={(value): void =>
|
||||
updateThreshold(threshold.id, 'unit', value as string)
|
||||
}
|
||||
style={{ width: 150 }}
|
||||
options={units}
|
||||
items={units}
|
||||
disabled={units.length === 0}
|
||||
data-testid="threshold-unit-select"
|
||||
testId="threshold-unit-select"
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
@@ -117,37 +119,22 @@ function ThresholdItem({
|
||||
{!notificationSettings.routingPolicies && (
|
||||
<>
|
||||
<Typography.Text className="sentence-text">send to</Typography.Text>
|
||||
<Select
|
||||
<ComboboxSimple
|
||||
value={threshold.channels}
|
||||
onChange={(value): void =>
|
||||
updateThreshold(threshold.id, 'channels', value)
|
||||
updateThreshold(threshold.id, 'channels', value as string[])
|
||||
}
|
||||
data-testid="threshold-notification-channel-select"
|
||||
testId="threshold-notification-channel-select"
|
||||
style={{ width: 350 }}
|
||||
options={channels.map((channel) => ({
|
||||
items={channels.map((channel) => ({
|
||||
value: channel.name,
|
||||
label: channel.name,
|
||||
'data-testid': `threshold-notification-channel-option-${threshold.label}`,
|
||||
}))}
|
||||
mode="multiple"
|
||||
multiple
|
||||
placeholder="Select notification channels"
|
||||
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}
|
||||
/>
|
||||
}
|
||||
loading={isLoadingChannels}
|
||||
className={isErrorChannels ? 'error' : undefined}
|
||||
emptyPlaceholder="No channels found"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
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: DefaultOptionType[] = [
|
||||
const mockUnits: ComboboxSimpleItem[] = [
|
||||
{ label: 'Bytes', value: 'bytes' },
|
||||
{ label: 'KB', value: 'kb' },
|
||||
{ label: 'MB', value: 'mb' },
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
.alert-condition-tabs {
|
||||
display: flex;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--l2-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(--l1-border);
|
||||
border-bottom: 0.5px solid var(--l1-border);
|
||||
border-left: 0.5px solid var(--l2-border);
|
||||
border-bottom: 0.5px solid var(--l2-border);
|
||||
width: 120px;
|
||||
height: 36px;
|
||||
|
||||
gap: 8px;
|
||||
|
||||
&.active-tab {
|
||||
background-color: var(--l1-background);
|
||||
background-color: var(--l2-background);
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--l1-background) !important;
|
||||
background-color: var(--l2-background-hover) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
border-left: 1px solid transparent !important;
|
||||
color: var(--l1-foreground);
|
||||
color: var(--l3-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,10 +65,16 @@
|
||||
.anomaly-threshold-container {
|
||||
padding: 24px;
|
||||
padding-right: 72px;
|
||||
background-color: var(--l1-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
background-color: var(--l2-background);
|
||||
border: 1px solid var(--l2-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;
|
||||
@@ -88,34 +94,6 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +129,9 @@
|
||||
flex-wrap: wrap;
|
||||
|
||||
.ant-input {
|
||||
background-color: var(--card);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
background-color: var(--l3-background);
|
||||
border: 1px solid var(--l3-border);
|
||||
color: var(--l2-foreground);
|
||||
height: 32px;
|
||||
|
||||
&::placeholder {
|
||||
@@ -161,28 +139,28 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l3-border);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l3-border);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select {
|
||||
.ant-select-selector {
|
||||
background-color: var(--card);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
background-color: var(--l3-background);
|
||||
border: 1px solid var(--l3-border);
|
||||
color: var(--l2-foreground);
|
||||
height: 32px;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l2-border);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l2-border);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
@@ -192,21 +170,23 @@
|
||||
}
|
||||
|
||||
.ant-select-selection-item {
|
||||
color: var(--l1-foreground);
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
|
||||
.ant-select-arrow {
|
||||
color: var(--muted-foreground);
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
color: var(--muted-foreground);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l2-foreground);
|
||||
border: 1px solid var(--l3-border);
|
||||
background-color: var(--l3-background);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,8 +206,8 @@
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
color: var(--muted-foreground);
|
||||
background-color: var(--card) !important;
|
||||
border: 1px solid var(--l1-border);
|
||||
background-color: var(--l3-background) !important;
|
||||
border: 1px solid var(--l3-border);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -235,9 +215,9 @@
|
||||
}
|
||||
|
||||
.ant-input {
|
||||
background-color: var(--card);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
background-color: var(--l3-background);
|
||||
border: 1px solid var(--l3-border);
|
||||
color: var(--l2-foreground);
|
||||
height: 32px;
|
||||
|
||||
&::placeholder {
|
||||
@@ -245,11 +225,11 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l3-border);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l2-border);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
@@ -258,7 +238,7 @@
|
||||
|
||||
.add-threshold-btn {
|
||||
margin-top: 8px;
|
||||
border: 1px dashed var(--l1-border);
|
||||
border: 1px dashed var(--l3-border);
|
||||
color: var(--l2-foreground);
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
@@ -267,10 +247,11 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
border-color: var(--l2-border);
|
||||
color: var(--l3-foreground);
|
||||
}
|
||||
|
||||
.anticon {
|
||||
@@ -339,8 +320,9 @@
|
||||
min-width: 240px;
|
||||
width: auto;
|
||||
justify-content: space-between;
|
||||
background-color: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
background-color: var(--l3-background);
|
||||
border: 1px solid var(--l3-border);
|
||||
box-shadow: none;
|
||||
|
||||
.evaluate-alert-conditions-button-left {
|
||||
color: var(--l2-foreground);
|
||||
@@ -358,7 +340,7 @@
|
||||
.evaluate-alert-conditions-button-right-text {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
background-color: var(--l1-border);
|
||||
background-color: var(--l3-border);
|
||||
padding: 1px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
|
||||
import {
|
||||
@@ -23,7 +23,7 @@ export interface ThresholdItemProps {
|
||||
showRemoveButton: boolean;
|
||||
channels: Channels[];
|
||||
isLoadingChannels: boolean;
|
||||
units: DefaultOptionType[];
|
||||
units: ComboboxSimpleItem[];
|
||||
isErrorChannels: boolean;
|
||||
refreshChannels: () => void;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Button, Flex, SelectProps, Switch } from 'antd';
|
||||
import { Button, Flex } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { ComboboxSimpleItem } from '@signozhq/ui/combobox';
|
||||
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';
|
||||
@@ -21,11 +22,11 @@ import { openInNewTab } from 'utils/navigation';
|
||||
import { ROUTING_POLICIES_ROUTE } from './constants';
|
||||
import { RoutingPolicyBannerProps } from './types';
|
||||
|
||||
export function getQueryNames(currentQuery: Query): BaseOptionType[] {
|
||||
export function getQueryNames(currentQuery: Query): ComboboxSimpleItem[] {
|
||||
const involvedQueriesInTraceOperator = getInvolvedQueriesInTraceOperator(
|
||||
currentQuery.builder.queryTraceOperator,
|
||||
);
|
||||
const queryConfig: Record<EQueryType, () => SelectProps['options']> = {
|
||||
const queryConfig: Record<EQueryType, () => ComboboxSimpleItem[]> = {
|
||||
[EQueryType.QUERY_BUILDER]: () => [
|
||||
...(getSelectedQueryOptions(currentQuery.builder.queryData)?.filter(
|
||||
(option) =>
|
||||
@@ -51,7 +52,7 @@ export function getCategoryByOptionId(id: string): string | undefined {
|
||||
|
||||
export function getCategorySelectOptionByName(
|
||||
name: string | undefined,
|
||||
): DefaultOptionType[] {
|
||||
): ComboboxSimpleItem[] {
|
||||
if (!name) {
|
||||
return [];
|
||||
}
|
||||
@@ -67,7 +68,6 @@ 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
|
||||
checked={notificationSettings.routingPolicies}
|
||||
data-testid="routing-policies-switch"
|
||||
value={notificationSettings.routingPolicies}
|
||||
testId="routing-policies-switch"
|
||||
onChange={(value): void => {
|
||||
setNotificationSettings({
|
||||
type: 'SET_ROUTING_POLICIES',
|
||||
|
||||
@@ -3,6 +3,7 @@ import { X } from '@signozhq/icons';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
|
||||
import { LabelInputState, LabelsInputProps } from './types';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function LabelsInput({
|
||||
labels,
|
||||
@@ -144,14 +145,16 @@ 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
|
||||
|
||||
@@ -39,9 +39,14 @@
|
||||
|
||||
&__input.title {
|
||||
background-color: transparent;
|
||||
color: var(--l1-foreground);
|
||||
background: var(--l2-background);
|
||||
color: var(--l2-foreground);
|
||||
width: 100%;
|
||||
min-width: 300px;
|
||||
|
||||
&:hover {
|
||||
background: var(--l2-background);
|
||||
}
|
||||
}
|
||||
|
||||
&__input.description {
|
||||
@@ -49,15 +54,6 @@
|
||||
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 {
|
||||
@@ -66,19 +62,7 @@
|
||||
gap: 8px;
|
||||
|
||||
&__add-button {
|
||||
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);
|
||||
}
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
&__existing-labels {
|
||||
@@ -121,6 +105,7 @@
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border: 1px solid var(--l2-border);
|
||||
}
|
||||
|
||||
&__input {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Switch, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Info } from '@signozhq/icons';
|
||||
|
||||
@@ -49,7 +50,7 @@ function AdvancedOptionItem({
|
||||
>
|
||||
{input}
|
||||
</div>
|
||||
<Switch onChange={handleOnToggle} checked={showInput} />
|
||||
<Switch onChange={handleOnToggle} value={showInput} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -93,16 +93,16 @@
|
||||
gap: 8px;
|
||||
|
||||
.ant-input {
|
||||
background-color: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
background-color: var(--l3-background);
|
||||
border: 1px solid var(--l3-border);
|
||||
color: var(--l2-foreground);
|
||||
|
||||
&:hover {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l3-border);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: var(--l1-border);
|
||||
border-color: var(--l3-border);
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Input, Select, Tooltip } from 'antd';
|
||||
import { Input, Tooltip } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Info } from '@signozhq/icons';
|
||||
|
||||
@@ -79,8 +80,8 @@ function EvaluationCadence(): JSX.Element {
|
||||
}
|
||||
data-testid="evaluation-cadence-duration-input"
|
||||
/>
|
||||
<Select
|
||||
options={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
|
||||
<SelectSimple
|
||||
items={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
|
||||
placeholder="Select time unit"
|
||||
style={{ width: 120 }}
|
||||
value={advancedOptions.evaluationCadence.default.timeUnit}
|
||||
@@ -91,7 +92,7 @@ function EvaluationCadence(): JSX.Element {
|
||||
...advancedOptions.evaluationCadence,
|
||||
default: {
|
||||
...advancedOptions.evaluationCadence.default,
|
||||
timeUnit: value,
|
||||
timeUnit: value as string,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Button, DatePicker, Input, Select } from 'antd';
|
||||
import { Button, DatePicker, Input } from 'antd';
|
||||
import { ComboboxSimple } from '@signozhq/ui/combobox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import classNames from 'classnames';
|
||||
import { useCreateAlertState } from 'container/CreateAlertV2/context';
|
||||
@@ -42,10 +43,6 @@ function EvaluationCadenceDetails({
|
||||
},
|
||||
});
|
||||
|
||||
const [searchTimezoneString, setSearchTimezoneString] = useState('');
|
||||
const [occurenceSearchString, setOccurenceSearchString] = useState('');
|
||||
const [repeatEverySearchString, setRepeatEverySearchString] = useState('');
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
label: 'Editor',
|
||||
@@ -93,45 +90,39 @@ function EvaluationCadenceDetails({
|
||||
<div className="editor-view" data-testid="editor-view">
|
||||
<div className="select-group">
|
||||
<Typography.Text>REPEAT EVERY</Typography.Text>
|
||||
<Select
|
||||
options={EVALUATION_CADENCE_REPEAT_EVERY_OPTIONS}
|
||||
value={evaluationCadence.custom.repeatEvery || null}
|
||||
<ComboboxSimple
|
||||
items={EVALUATION_CADENCE_REPEAT_EVERY_OPTIONS}
|
||||
value={evaluationCadence.custom.repeatEvery || undefined}
|
||||
onChange={(value): void =>
|
||||
setEvaluationCadence({
|
||||
...evaluationCadence,
|
||||
custom: {
|
||||
...evaluationCadence.custom,
|
||||
repeatEvery: value,
|
||||
repeatEvery: value as string,
|
||||
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>
|
||||
<Select
|
||||
options={occurenceOptions}
|
||||
value={evaluationCadence.custom.occurence || null}
|
||||
mode="multiple"
|
||||
<ComboboxSimple
|
||||
items={occurenceOptions}
|
||||
value={evaluationCadence.custom.occurence || []}
|
||||
multiple
|
||||
onChange={(value): void =>
|
||||
setEvaluationCadence({
|
||||
...evaluationCadence,
|
||||
custom: {
|
||||
...evaluationCadence.custom,
|
||||
occurence: value,
|
||||
occurence: value as string[],
|
||||
},
|
||||
})
|
||||
}
|
||||
placeholder="Select day(s)"
|
||||
showSearch
|
||||
searchValue={occurenceSearchString}
|
||||
onSearch={setOccurenceSearchString}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -152,22 +143,19 @@ function EvaluationCadenceDetails({
|
||||
</div>
|
||||
<div className="select-group">
|
||||
<Typography.Text>TIMEZONE</Typography.Text>
|
||||
<Select
|
||||
options={TIMEZONE_DATA}
|
||||
value={evaluationCadence.custom.timezone || null}
|
||||
<ComboboxSimple
|
||||
items={TIMEZONE_DATA}
|
||||
value={evaluationCadence.custom.timezone || undefined}
|
||||
onChange={(value): void =>
|
||||
setEvaluationCadence({
|
||||
...evaluationCadence,
|
||||
custom: {
|
||||
...evaluationCadence.custom,
|
||||
timezone: value,
|
||||
timezone: value as string,
|
||||
},
|
||||
})
|
||||
}
|
||||
placeholder="Select timezone"
|
||||
onSearch={setSearchTimezoneString}
|
||||
searchValue={searchTimezoneString}
|
||||
showSearch
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
.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;
|
||||
}
|
||||
@@ -157,24 +161,6 @@
|
||||
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);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Input, Select } from 'antd';
|
||||
import { Input } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { ADVANCED_OPTIONS_TIME_UNIT_OPTIONS } from '../../context/constants';
|
||||
@@ -19,7 +20,7 @@ function EvaluationWindowDetails({
|
||||
const currentHourOptions = useMemo(() => {
|
||||
const options = [];
|
||||
for (let i = 0; i < 60; i++) {
|
||||
options.push({ label: i.toString(), value: i });
|
||||
options.push({ label: i.toString(), value: i.toString() });
|
||||
}
|
||||
return options;
|
||||
}, []);
|
||||
@@ -27,7 +28,7 @@ function EvaluationWindowDetails({
|
||||
const currentMonthOptions = useMemo(() => {
|
||||
const options = [];
|
||||
for (let i = 1; i <= 31; i++) {
|
||||
options.push({ label: i.toString(), value: i });
|
||||
options.push({ label: i.toString(), value: i.toString() });
|
||||
}
|
||||
return options;
|
||||
}, []);
|
||||
@@ -123,10 +124,10 @@ function EvaluationWindowDetails({
|
||||
<Typography.Text>{displayText}</Typography.Text>
|
||||
<div className="select-group">
|
||||
<Typography.Text>STARTING AT MINUTE</Typography.Text>
|
||||
<Select
|
||||
options={currentHourOptions}
|
||||
value={evaluationWindow.startingAt.number || null}
|
||||
onChange={handleNumberChange}
|
||||
<SelectSimple
|
||||
items={currentHourOptions}
|
||||
value={evaluationWindow.startingAt.number || undefined}
|
||||
onChange={(value): void => handleNumberChange(value as string)}
|
||||
placeholder="Select starting at"
|
||||
data-testid="evaluation-window-details-starting-at-select"
|
||||
/>
|
||||
@@ -151,10 +152,10 @@ function EvaluationWindowDetails({
|
||||
</div>
|
||||
<div className="select-group">
|
||||
<Typography.Text>SELECT TIMEZONE</Typography.Text>
|
||||
<Select
|
||||
options={TIMEZONE_DATA}
|
||||
value={evaluationWindow.startingAt.timezone || null}
|
||||
onChange={handleTimezoneChange}
|
||||
<SelectSimple
|
||||
items={TIMEZONE_DATA}
|
||||
value={evaluationWindow.startingAt.timezone || undefined}
|
||||
onChange={(value): void => handleTimezoneChange(value as string)}
|
||||
placeholder="Select timezone"
|
||||
data-testid="evaluation-window-details-timezone-select"
|
||||
/>
|
||||
@@ -172,10 +173,10 @@ function EvaluationWindowDetails({
|
||||
<Typography.Text>{displayText}</Typography.Text>
|
||||
<div className="select-group">
|
||||
<Typography.Text>STARTING ON DAY</Typography.Text>
|
||||
<Select
|
||||
options={currentMonthOptions}
|
||||
value={evaluationWindow.startingAt.number || null}
|
||||
onChange={handleNumberChange}
|
||||
<SelectSimple
|
||||
items={currentMonthOptions}
|
||||
value={evaluationWindow.startingAt.number || undefined}
|
||||
onChange={(value): void => handleNumberChange(value as string)}
|
||||
placeholder="Select starting at"
|
||||
data-testid="evaluation-window-details-starting-at-select"
|
||||
/>
|
||||
@@ -189,10 +190,10 @@ function EvaluationWindowDetails({
|
||||
</div>
|
||||
<div className="select-group">
|
||||
<Typography.Text>SELECT TIMEZONE</Typography.Text>
|
||||
<Select
|
||||
options={TIMEZONE_DATA}
|
||||
value={evaluationWindow.startingAt.timezone || null}
|
||||
onChange={handleTimezoneChange}
|
||||
<SelectSimple
|
||||
items={TIMEZONE_DATA}
|
||||
value={evaluationWindow.startingAt.timezone || undefined}
|
||||
onChange={(value): void => handleTimezoneChange(value as string)}
|
||||
placeholder="Select timezone"
|
||||
data-testid="evaluation-window-details-timezone-select"
|
||||
/>
|
||||
@@ -221,10 +222,10 @@ function EvaluationWindowDetails({
|
||||
</div>
|
||||
<div className="select-group time-select-group">
|
||||
<Typography.Text>UNIT</Typography.Text>
|
||||
<Select
|
||||
options={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
|
||||
value={evaluationWindow.startingAt.unit || null}
|
||||
onChange={handleUnitChange}
|
||||
<SelectSimple
|
||||
items={ADVANCED_OPTIONS_TIME_UNIT_OPTIONS}
|
||||
value={evaluationWindow.startingAt.unit || undefined}
|
||||
onChange={(value): void => handleUnitChange(value as string)}
|
||||
placeholder="Select unit"
|
||||
data-testid="evaluation-window-details-custom-rolling-window-unit-select"
|
||||
/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { Select, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { Info } from '@signozhq/icons';
|
||||
@@ -87,16 +88,15 @@ function MultipleNotifications(): JSX.Element {
|
||||
: 'No grouping fields available';
|
||||
let input = (
|
||||
<div>
|
||||
<Select
|
||||
options={spaceAggregationOptions}
|
||||
onChange={onSelectChange}
|
||||
value={notificationSettings.multipleNotifications}
|
||||
mode="multiple"
|
||||
<SelectSimple
|
||||
items={spaceAggregationOptions}
|
||||
onChange={(value): void => onSelectChange(value as string[])}
|
||||
value={notificationSettings.multipleNotifications || []}
|
||||
multiple
|
||||
placeholder={placeholder}
|
||||
disabled={!isMultipleNotificationsEnabled}
|
||||
aria-disabled={!isMultipleNotificationsEnabled}
|
||||
maxTagCount={3}
|
||||
data-testid="multiple-notifications-select"
|
||||
maxDisplayedPills={3}
|
||||
testId="multiple-notifications-select"
|
||||
/>
|
||||
{isMultipleNotificationsEnabled && (
|
||||
<Typography.Text className="multiple-notifications-select-description">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Input, Select } from 'antd';
|
||||
import { Input } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
@@ -38,31 +39,31 @@ function NotificationSettings(): JSX.Element {
|
||||
}}
|
||||
data-testid="repeat-notifications-time-input"
|
||||
/>
|
||||
<Select
|
||||
value={notificationSettings.reNotification.unit || null}
|
||||
<SelectSimple
|
||||
value={notificationSettings.reNotification.unit || undefined}
|
||||
placeholder="Select unit"
|
||||
disabled={!notificationSettings.reNotification.enabled}
|
||||
options={RE_NOTIFICATION_TIME_UNIT_OPTIONS}
|
||||
items={RE_NOTIFICATION_TIME_UNIT_OPTIONS}
|
||||
onChange={(value): void => {
|
||||
setNotificationSettings({
|
||||
type: 'SET_RE_NOTIFICATION',
|
||||
payload: {
|
||||
enabled: notificationSettings.reNotification.enabled,
|
||||
value: notificationSettings.reNotification.value,
|
||||
unit: value,
|
||||
unit: value as string,
|
||||
conditions: notificationSettings.reNotification.conditions,
|
||||
},
|
||||
});
|
||||
}}
|
||||
data-testid="repeat-notifications-unit-select"
|
||||
testId="repeat-notifications-unit-select"
|
||||
/>
|
||||
<Typography.Text>while</Typography.Text>
|
||||
<Select
|
||||
mode="multiple"
|
||||
value={notificationSettings.reNotification.conditions || null}
|
||||
<SelectSimple
|
||||
multiple
|
||||
value={notificationSettings.reNotification.conditions || []}
|
||||
placeholder="Select conditions"
|
||||
disabled={!notificationSettings.reNotification.enabled}
|
||||
options={RE_NOTIFICATION_CONDITION_OPTIONS}
|
||||
items={RE_NOTIFICATION_CONDITION_OPTIONS}
|
||||
onChange={(value): void => {
|
||||
setNotificationSettings({
|
||||
type: 'SET_RE_NOTIFICATION',
|
||||
@@ -70,11 +71,11 @@ function NotificationSettings(): JSX.Element {
|
||||
enabled: notificationSettings.reNotification.enabled,
|
||||
value: notificationSettings.reNotification.value,
|
||||
unit: notificationSettings.reNotification.unit,
|
||||
conditions: value,
|
||||
conditions: value as ('firing' | 'nodata')[],
|
||||
},
|
||||
});
|
||||
}}
|
||||
data-testid="repeat-notifications-conditions-select"
|
||||
testId="repeat-notifications-conditions-select"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
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;
|
||||
@@ -54,8 +57,8 @@
|
||||
|
||||
textarea {
|
||||
height: 150px;
|
||||
background: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l3-background);
|
||||
border: 1px solid var(--l3-border);
|
||||
border-radius: 4px;
|
||||
color: var(--l2-foreground) !important;
|
||||
font-family: Inter;
|
||||
@@ -77,8 +80,9 @@
|
||||
gap: 8px;
|
||||
|
||||
.ant-input {
|
||||
width: 120px;
|
||||
border: 1px solid var(--l1-border);
|
||||
width: 190px;
|
||||
border: 1px solid var(--l3-border);
|
||||
background-color: var(--l3-background);
|
||||
}
|
||||
|
||||
.ant-select {
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
gap: 8px;
|
||||
|
||||
&.active-tab {
|
||||
background-color: var(--l1-background);
|
||||
background-color: var(--l3-background);
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--l1-background) !important;
|
||||
background-color: var(--l3-background) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Select } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import CustomSelect from 'components/NewSelect/CustomSelect';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
@@ -204,10 +204,9 @@ function DynamicVariable({
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
<Select
|
||||
<SelectSimple
|
||||
placeholder="Source"
|
||||
defaultValue={AttributeSource.ALL_TELEMETRY}
|
||||
options={sources.map((source) => ({ label: source, value: source }))}
|
||||
items={sources.map((source) => ({ label: source, value: source }))}
|
||||
onChange={(value): void => setAttributeSource(value as AttributeSource)}
|
||||
value={attributeSource || dynamicVariablesSelectedValue?.value}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,9 @@ import { useQuery } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { orange } from '@ant-design/colors';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Collapse, Input, Select, Switch, Tag } from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Button, Collapse, Input, Tag } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import dashboardVariablesQuery from 'api/dashboard/variables/dashboardVariablesQuery';
|
||||
import cx from 'classnames';
|
||||
@@ -55,7 +57,11 @@ import { WidgetSelector } from './WidgetSelector';
|
||||
|
||||
import './VariableItem.styles.scss';
|
||||
|
||||
const { Option } = Select;
|
||||
const SORT_ITEMS = [
|
||||
{ value: VariableSortTypeArr[0], label: 'Disabled' },
|
||||
{ value: VariableSortTypeArr[1], label: 'Ascending' },
|
||||
{ value: VariableSortTypeArr[2], label: 'Descending' },
|
||||
];
|
||||
|
||||
interface VariableItemProps {
|
||||
variableData: IDashboardVariable;
|
||||
@@ -742,19 +748,14 @@ function VariableItem({
|
||||
<Typography className="typography-variables">Sort Values</Typography>
|
||||
</LabelContainer>
|
||||
|
||||
<Select
|
||||
defaultActiveFirstOption
|
||||
defaultValue={VariableSortTypeArr[0]}
|
||||
<SelectSimple
|
||||
value={variableSortType}
|
||||
onChange={(value: TSortVariableValuesType): void =>
|
||||
setVariableSortType(value)
|
||||
onChange={(value): void =>
|
||||
setVariableSortType(value as TSortVariableValuesType)
|
||||
}
|
||||
className="sort-input"
|
||||
>
|
||||
<Option value={VariableSortTypeArr[0]}>Disabled</Option>
|
||||
<Option value={VariableSortTypeArr[1]}>Ascending</Option>
|
||||
<Option value={VariableSortTypeArr[2]}>Descending</Option>
|
||||
</Select>
|
||||
items={SORT_ITEMS}
|
||||
/>
|
||||
</VariableItemRow>
|
||||
<VariableItemRow className="multiple-values-section">
|
||||
<LabelContainer>
|
||||
@@ -763,7 +764,7 @@ function VariableItem({
|
||||
</Typography>
|
||||
</LabelContainer>
|
||||
<Switch
|
||||
checked={variableMultiSelect}
|
||||
value={variableMultiSelect}
|
||||
onChange={(e): void => {
|
||||
setVariableMultiSelect(e);
|
||||
if (!e) {
|
||||
@@ -780,7 +781,7 @@ function VariableItem({
|
||||
</Typography>
|
||||
</LabelContainer>
|
||||
<Switch
|
||||
checked={variableShowALLOption}
|
||||
value={variableShowALLOption}
|
||||
onChange={(e): void => setVariableShowALLOption(e)}
|
||||
/>
|
||||
</VariableItemRow>
|
||||
@@ -797,10 +798,10 @@ function VariableItem({
|
||||
<CustomSelect
|
||||
placeholder="Select a default value"
|
||||
value={variableDefaultValue}
|
||||
onChange={(value): void => setVariableDefaultValue(value)}
|
||||
options={previewValues.map((value) => ({
|
||||
label: value,
|
||||
value,
|
||||
onChange={(value): void => setVariableDefaultValue(value ?? '')}
|
||||
options={previewValues.map((val) => ({
|
||||
label: val,
|
||||
value: val,
|
||||
}))}
|
||||
/>
|
||||
</VariableItemRow>
|
||||
|
||||
@@ -98,6 +98,14 @@
|
||||
|
||||
.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 {
|
||||
@@ -108,7 +116,7 @@
|
||||
padding: 6px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
border-radius: 2var (--l3-border) px 0px 0px 2px;
|
||||
border: 1px solid var(--l1-border) !important;
|
||||
background: var(--l3-background) !important;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Col, Input, Radio, Select, Space, Tooltip } from 'antd';
|
||||
import { Col, Input, Radio, Space, Tooltip } from 'antd';
|
||||
import { SelectSimple } from '@signozhq/ui/select';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import AddTags from 'container/DashboardContainer/DashboardSettings/General/AddTags';
|
||||
import { useDashboardCursorSyncMode } from 'hooks/dashboard/useDashboardCursorSyncMode';
|
||||
@@ -21,8 +22,6 @@ 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();
|
||||
|
||||
@@ -130,24 +129,22 @@ function GeneralDashboardSettings(): JSX.Element {
|
||||
<div>
|
||||
<Typography className={styles.dashboardName}>Dashboard Name</Typography>
|
||||
<section className={styles.nameIconInput}>
|
||||
<Select
|
||||
defaultActiveFirstOption
|
||||
<SelectSimple
|
||||
data-testid="dashboard-image"
|
||||
suffixIcon={null}
|
||||
rootClassName={styles.dashboardImageInput}
|
||||
className={styles.dashboardImageInput}
|
||||
value={updatedImage}
|
||||
onChange={(value: string): void => setUpdatedImage(value)}
|
||||
>
|
||||
{Base64Icons.map((icon) => (
|
||||
<Option value={icon} key={icon}>
|
||||
onChange={(value): void => setUpdatedImage(value as string)}
|
||||
items={Base64Icons.map((icon) => ({
|
||||
value: icon,
|
||||
label: (
|
||||
<img
|
||||
src={icon}
|
||||
alt="dashboard-icon"
|
||||
className={styles.listItemImage}
|
||||
/>
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
<Input
|
||||
data-testid="dashboard-name"
|
||||
className={styles.dashboardNameInput}
|
||||
|
||||