Compare commits
21 Commits
feat/issue
...
tfbtest
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99cbd023b5 | ||
|
|
dfca5b13c0 | ||
|
|
ad392e81ff | ||
|
|
92ceefccee | ||
|
|
9cc4e1b56f | ||
|
|
3758ee7451 | ||
|
|
02b605d109 | ||
|
|
eb86aabf3e | ||
|
|
8810693bda | ||
|
|
6334e09a60 | ||
|
|
1d379931b2 | ||
|
|
815a6d13c5 | ||
|
|
59af9d1c2f | ||
|
|
19d24da147 | ||
|
|
cd1c9ddf11 | ||
|
|
7ff3286c9c | ||
|
|
27830742f9 | ||
|
|
39f07e7477 | ||
|
|
0ab50da7b0 | ||
|
|
c03541cd6c | ||
|
|
727a039eb9 |
75
.github/pull_request_template.md
vendored
75
.github/pull_request_template.md
vendored
@@ -1,17 +1,74 @@
|
||||
### Summary
|
||||
## 📄 Summary
|
||||
|
||||
<!-- ✍️ A clear and concise description...-->
|
||||
<!-- Describe the purpose of the PR in a few sentences. What does it fix/add/update? -->
|
||||
|
||||
#### Related Issues / PR's
|
||||
---
|
||||
|
||||
<!-- ✍️ Add the issues being resolved here and related PR's where applicable -->
|
||||
## ✅ Changes
|
||||
|
||||
#### Screenshots
|
||||
- [ ] Feature: Brief description
|
||||
- [ ] Bug fix: Brief description
|
||||
|
||||
NA
|
||||
---
|
||||
|
||||
<!-- ✍️ Add screenshots of before and after changes where applicable-->
|
||||
## 🏷️ Required: Add Relevant Labels
|
||||
|
||||
#### Affected Areas and Manually Tested Areas
|
||||
> ⚠️ **Manually add appropriate labels in the PR sidebar**
|
||||
Please select one or more labels (as applicable):
|
||||
|
||||
<!-- ✍️ Add details of blast radius and dev testing areas where applicable-->
|
||||
ex:
|
||||
|
||||
- `frontend`
|
||||
- `backend`
|
||||
- `devops`
|
||||
- `bug`
|
||||
- `enhancement`
|
||||
- `ui`
|
||||
- `test`
|
||||
|
||||
---
|
||||
|
||||
## 👥 Reviewers
|
||||
|
||||
> Tag the relevant teams for review:
|
||||
|
||||
- [ ] @SigNoz/frontend
|
||||
- [ ] @SigNoz/backend
|
||||
- [ ] @SigNoz/devops
|
||||
|
||||
---
|
||||
|
||||
## 🧪 How to Test
|
||||
|
||||
<!-- Describe how reviewers can test this PR -->
|
||||
1. ...
|
||||
2. ...
|
||||
3. ...
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Related Issues
|
||||
|
||||
<!-- Reference any related issues (e.g. Fixes #123, Closes #456) -->
|
||||
Closes #
|
||||
|
||||
---
|
||||
|
||||
## 📸 Screenshots / Screen Recording (if applicable / mandatory for UI related changes)
|
||||
|
||||
<!-- Add screenshots or GIFs to help visualize changes -->
|
||||
|
||||
---
|
||||
|
||||
## 📋 Checklist
|
||||
|
||||
- [ ] Dev Review
|
||||
- [ ] Test cases added (Unit/ Integration / E2E)
|
||||
- [ ] Manually tested the changes
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 👀 Notes for Reviewers
|
||||
|
||||
<!-- Anything reviewers should keep in mind while reviewing -->
|
||||
|
||||
1
.github/workflows/build-community.yaml
vendored
1
.github/workflows/build-community.yaml
vendored
@@ -62,6 +62,7 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
GO_VERSION: 1.23
|
||||
GO_NAME: signoz-community
|
||||
GO_INPUT_ARTIFACT_CACHE_KEY: community-jsbuild-${{ github.sha }}
|
||||
GO_INPUT_ARTIFACT_PATH: frontend/build
|
||||
|
||||
1
.github/workflows/build-enterprise.yaml
vendored
1
.github/workflows/build-enterprise.yaml
vendored
@@ -94,6 +94,7 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
GO_VERSION: 1.23
|
||||
GO_INPUT_ARTIFACT_CACHE_KEY: enterprise-jsbuild-${{ github.sha }}
|
||||
GO_INPUT_ARTIFACT_PATH: frontend/build
|
||||
GO_BUILD_CONTEXT: ./ee/query-service
|
||||
|
||||
1
.github/workflows/build-staging.yaml
vendored
1
.github/workflows/build-staging.yaml
vendored
@@ -91,6 +91,7 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
GO_VERSION: 1.23
|
||||
GO_INPUT_ARTIFACT_CACHE_KEY: staging-jsbuild-${{ github.sha }}
|
||||
GO_INPUT_ARTIFACT_PATH: frontend/build
|
||||
GO_BUILD_CONTEXT: ./ee/query-service
|
||||
|
||||
5
.github/workflows/goci.yaml
vendored
5
.github/workflows/goci.yaml
vendored
@@ -18,6 +18,7 @@ jobs:
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
GO_TEST_CONTEXT: ./...
|
||||
GO_VERSION: 1.23
|
||||
fmt:
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
|
||||
@@ -26,6 +27,7 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
GO_VERSION: 1.23
|
||||
lint:
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
|
||||
@@ -34,6 +36,7 @@ jobs:
|
||||
secrets: inherit
|
||||
with:
|
||||
PRIMUS_REF: main
|
||||
GO_VERSION: 1.23
|
||||
build:
|
||||
if: |
|
||||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
|
||||
@@ -45,7 +48,7 @@ jobs:
|
||||
- name: go-install
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
go-version: "1.23"
|
||||
- name: qemu-install
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: aarch64-install
|
||||
|
||||
4
.github/workflows/gor-signoz-community.yaml
vendored
4
.github/workflows/gor-signoz-community.yaml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
- name: setup-go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
go-version: "1.23"
|
||||
- name: cross-compilation-tools
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
- name: setup-go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
go-version: "1.23"
|
||||
|
||||
# copy the caches from build
|
||||
- name: get-sha
|
||||
|
||||
4
.github/workflows/gor-signoz.yaml
vendored
4
.github/workflows/gor-signoz.yaml
vendored
@@ -73,7 +73,7 @@ jobs:
|
||||
- name: setup-go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
go-version: "1.23"
|
||||
- name: cross-compilation-tools
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
- name: setup-go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.22"
|
||||
go-version: "1.23"
|
||||
|
||||
# copy the caches from build
|
||||
- name: get-sha
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -60,9 +60,7 @@ ee/query-service/db
|
||||
|
||||
e2e/node_modules/
|
||||
e2e/test-results/
|
||||
e2e/playwright-report/
|
||||
e2e/blob-report/
|
||||
e2e/playwright/.cache/
|
||||
e2e/.auth
|
||||
|
||||
# go
|
||||
|
||||
@@ -164,3 +164,9 @@ alertmanager:
|
||||
maintenance_interval: 15m
|
||||
# Retention of the notification logs.
|
||||
retention: 120h
|
||||
|
||||
|
||||
##################### Analytics #####################
|
||||
analytics:
|
||||
# Whether to enable analytics.
|
||||
enabled: false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.22-bullseye
|
||||
FROM golang:1.23-bullseye
|
||||
|
||||
ARG OS="linux"
|
||||
ARG TARGETARCH
|
||||
|
||||
@@ -41,8 +41,8 @@ func (ah *APIHandler) lockUnlockDashboard(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
dashboard, err := dashboards.GetDashboard(r.Context(), claims.OrgID, uuid)
|
||||
if err != nil {
|
||||
dashboard, apiErr := dashboards.GetDashboard(r.Context(), claims.OrgID, uuid)
|
||||
if apiErr != nil {
|
||||
render.Error(w, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to get dashboard"))
|
||||
return
|
||||
}
|
||||
@@ -53,8 +53,8 @@ func (ah *APIHandler) lockUnlockDashboard(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
// Lock/Unlock the dashboard
|
||||
err = dashboards.LockUnlockDashboard(r.Context(), claims.OrgID, uuid, lock)
|
||||
if err != nil {
|
||||
apiErr = dashboards.LockUnlockDashboard(r.Context(), claims.OrgID, uuid, lock)
|
||||
if apiErr != nil {
|
||||
render.Error(w, errors.Wrapf(err, errors.TypeInternal, errors.CodeInternal, "failed to lock/unlock dashboard"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -322,6 +322,7 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler, web web.Web) (*h
|
||||
apiHandler.RegisterMessagingQueuesRoutes(r, am)
|
||||
apiHandler.RegisterThirdPartyApiRoutes(r, am)
|
||||
apiHandler.MetricExplorerRoutes(r, am)
|
||||
apiHandler.RegisterTraceFunnelsRoutes(r, am)
|
||||
|
||||
c := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
|
||||
@@ -62,6 +62,13 @@ var BasicPlan = basemodel.FeatureSet{
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.TraceFunnels,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
}
|
||||
|
||||
var EnterprisePlan = basemodel.FeatureSet{
|
||||
@@ -114,4 +121,11 @@ var EnterprisePlan = basemodel.FeatureSet{
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
basemodel.Feature{
|
||||
Name: basemodel.TraceFunnels,
|
||||
Active: false,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Ignore artifacts:
|
||||
build
|
||||
coverage
|
||||
public/
|
||||
|
||||
# Ignore all MD files:
|
||||
**/*.md
|
||||
**/*.md
|
||||
|
||||
# Ignore all JSON files:
|
||||
**/*.json
|
||||
|
||||
@@ -3,5 +3,4 @@ BUNDLE_ANALYSER="true"
|
||||
FRONTEND_API_ENDPOINT="http://localhost:8080/"
|
||||
INTERCOM_APP_ID="intercom-app-id"
|
||||
|
||||
PLAYWRIGHT_TEST_BASE_URL="http://localhost:8080"
|
||||
CI="1"
|
||||
@@ -30,11 +30,6 @@ const config: Config.InitialOptions = {
|
||||
testPathIgnorePatterns: ['/node_modules/', '/public/'],
|
||||
moduleDirectories: ['node_modules', 'src'],
|
||||
testEnvironment: 'jest-environment-jsdom',
|
||||
testEnvironmentOptions: {
|
||||
'jest-playwright': {
|
||||
browsers: ['chromium', 'firefox', 'webkit'],
|
||||
},
|
||||
},
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
statements: 80,
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
"jest:coverage": "jest --coverage",
|
||||
"jest:watch": "jest --watch",
|
||||
"postinstall": "yarn i18n:generate-hash && (is-ci || yarn husky:configure)",
|
||||
"playwright": "NODE_ENV=testing playwright test --config=./playwright.config.ts",
|
||||
"playwright:local:debug": "PWDEBUG=console yarn playwright --headed --browser=chromium",
|
||||
"playwright:codegen:local": "playwright codegen http://localhost:3301",
|
||||
"playwright:codegen:local:auth": "yarn playwright:codegen:local --load-storage=tests/auth.json",
|
||||
"husky:configure": "cd .. && husky install frontend/.husky && cd frontend && chmod ug+x .husky/*",
|
||||
"commitlint": "commitlint --edit $1",
|
||||
"test": "jest",
|
||||
@@ -164,7 +160,6 @@
|
||||
"@commitlint/config-conventional": "^16.2.4",
|
||||
"@faker-js/faker": "9.3.0",
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@playwright/test": "^1.22.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/user-event": "14.4.3",
|
||||
@@ -258,6 +253,7 @@
|
||||
"http-proxy-middleware": "3.0.3",
|
||||
"cross-spawn": "7.0.5",
|
||||
"cookie": "^0.7.1",
|
||||
"serialize-javascript": "6.0.2"
|
||||
"serialize-javascript": "6.0.2",
|
||||
"prismjs": "1.30.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { PlaywrightTestConfig } from '@playwright/test';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
preserveOutput: 'always',
|
||||
name: 'Signoz',
|
||||
testDir: './tests',
|
||||
use: {
|
||||
trace: 'retain-on-failure',
|
||||
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:3301',
|
||||
},
|
||||
updateSnapshots: 'all',
|
||||
fullyParallel: !!process.env.CI,
|
||||
quiet: false,
|
||||
testMatch: ['**/*.spec.ts'],
|
||||
reporter: process.env.CI ? 'github' : 'list',
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -9,7 +9,7 @@ done
|
||||
# create temporary tsconfig which includes only passed files
|
||||
str="{
|
||||
\"extends\": \"./tsconfig.json\",
|
||||
\"include\": [ \"src/typings/**/*.ts\",\"src/**/*.d.ts\", \"./babel.config.js\", \"./jest.config.ts\", \"./.eslintrc.js\",\"./__mocks__\",\"./conf/default.conf\",\"./public\",\"./tests\",\"./playwright.config.ts\",\"./commitlint.config.ts\",\"./webpack.config.js\",\"./webpack.config.prod.js\",\"./jest.setup.ts\",\"./**/*.d.ts\",$files]
|
||||
\"include\": [ \"src/typings/**/*.ts\",\"src/**/*.d.ts\", \"./babel.config.js\", \"./jest.config.ts\", \"./.eslintrc.js\",\"./__mocks__\",\"./public\",\"./tests\",\"./commitlint.config.ts\",\"./webpack.config.js\",\"./webpack.config.prod.js\",\"./jest.setup.ts\",\"./**/*.d.ts\",$files]
|
||||
}"
|
||||
echo $str > tsconfig.tmp
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import getLocalStorageApi from 'api/browser/localstorage/get';
|
||||
import setLocalStorageApi from 'api/browser/localstorage/set';
|
||||
import getOrgUser from 'api/user/getOrgUser';
|
||||
import getOrgUser from 'api/v1/user/getOrgUser';
|
||||
import { FeatureKeys } from 'constants/features';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorV2 } from 'types/api';
|
||||
import { ErrorV2Resp } from 'types/api';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
// reference - https://axios-http.com/docs/handling_errors
|
||||
export function ErrorResponseHandlerV2(error: AxiosError<ErrorV2>): never {
|
||||
export function ErrorResponseHandlerV2(error: AxiosError<ErrorV2Resp>): never {
|
||||
const { response, request } = error;
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
@@ -11,10 +11,10 @@ export function ErrorResponseHandlerV2(error: AxiosError<ErrorV2>): never {
|
||||
throw new APIError({
|
||||
httpStatusCode: response.status || 500,
|
||||
error: {
|
||||
code: response.data.code,
|
||||
message: response.data.message,
|
||||
url: response.data.url,
|
||||
errors: response.data.errors,
|
||||
code: response.data.error.code,
|
||||
message: response.data.error.message,
|
||||
url: response.data.error.url,
|
||||
errors: response.data.error.errors,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createEmail';
|
||||
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/channels', {
|
||||
const response = await axios.post<PayloadProps>('/channels', {
|
||||
name: props.name,
|
||||
email_configs: [
|
||||
{
|
||||
@@ -21,13 +21,12 @@ const create = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createMsTeams';
|
||||
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/channels', {
|
||||
const response = await axios.post<PayloadProps>('/channels', {
|
||||
name: props.name,
|
||||
msteamsv2_configs: [
|
||||
{
|
||||
@@ -21,13 +21,12 @@ const create = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createOpsgenie';
|
||||
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/channels', {
|
||||
const response = await axios.post<PayloadProps>('/channels', {
|
||||
name: props.name,
|
||||
opsgenie_configs: [
|
||||
{
|
||||
@@ -24,13 +24,12 @@ const create = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createPager';
|
||||
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/channels', {
|
||||
const response = await axios.post<PayloadProps>('/channels', {
|
||||
name: props.name,
|
||||
pagerduty_configs: [
|
||||
{
|
||||
@@ -29,13 +29,12 @@ const create = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createSlack';
|
||||
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/channels', {
|
||||
const response = await axios.post<PayloadProps>('/channels', {
|
||||
name: props.name,
|
||||
slack_configs: [
|
||||
{
|
||||
@@ -22,13 +22,12 @@ const create = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createWebhook';
|
||||
|
||||
const create = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
let httpConfig = {};
|
||||
const username = props.username ? props.username.trim() : '';
|
||||
@@ -28,7 +28,7 @@ const create = async (
|
||||
};
|
||||
}
|
||||
|
||||
const response = await axios.post('/channels', {
|
||||
const response = await axios.post<PayloadProps>('/channels', {
|
||||
name: props.name,
|
||||
webhook_configs: [
|
||||
{
|
||||
@@ -40,13 +40,12 @@ const create = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/delete';
|
||||
|
||||
const deleteChannel = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.delete(`/channels/${props.id}`);
|
||||
const response = await axios.delete<PayloadProps>(`/channels/${props.id}`);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editEmail';
|
||||
|
||||
const editEmail = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.put(`/channels/${props.id}`, {
|
||||
const response = await axios.put<PayloadProps>(`/channels/${props.id}`, {
|
||||
name: props.name,
|
||||
email_configs: [
|
||||
{
|
||||
@@ -21,13 +21,12 @@ const editEmail = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editMsTeams';
|
||||
|
||||
const editMsTeams = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.put(`/channels/${props.id}`, {
|
||||
const response = await axios.put<PayloadProps>(`/channels/${props.id}`, {
|
||||
name: props.name,
|
||||
msteamsv2_configs: [
|
||||
{
|
||||
@@ -21,13 +21,12 @@ const editMsTeams = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorResponse, ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editOpsgenie';
|
||||
|
||||
const editOpsgenie = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps> | ErrorResponse> => {
|
||||
try {
|
||||
const response = await axios.put(`/channels/${props.id}`, {
|
||||
const response = await axios.put<PayloadProps>(`/channels/${props.id}`, {
|
||||
name: props.name,
|
||||
opsgenie_configs: [
|
||||
{
|
||||
@@ -25,13 +25,12 @@ const editOpsgenie = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
return ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editPager';
|
||||
|
||||
const editPager = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.put(`/channels/${props.id}`, {
|
||||
const response = await axios.put<PayloadProps>(`/channels/${props.id}`, {
|
||||
name: props.name,
|
||||
pagerduty_configs: [
|
||||
{
|
||||
@@ -29,13 +29,12 @@ const editPager = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editSlack';
|
||||
|
||||
const editSlack = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.put(`/channels/${props.id}`, {
|
||||
const response = await axios.put<PayloadProps>(`/channels/${props.id}`, {
|
||||
name: props.name,
|
||||
slack_configs: [
|
||||
{
|
||||
@@ -22,13 +22,12 @@ const editSlack = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/editWebhook';
|
||||
|
||||
const editWebhook = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
let httpConfig = {};
|
||||
const username = props.username ? props.username.trim() : '';
|
||||
@@ -28,7 +28,7 @@ const editWebhook = async (
|
||||
};
|
||||
}
|
||||
|
||||
const response = await axios.put(`/channels/${props.id}`, {
|
||||
const response = await axios.put<PayloadProps>(`/channels/${props.id}`, {
|
||||
name: props.name,
|
||||
webhook_configs: [
|
||||
{
|
||||
@@ -40,13 +40,12 @@ const editWebhook = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/get';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
|
||||
const get = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
const get = async (props: Props): Promise<SuccessResponseV2<Channels>> => {
|
||||
try {
|
||||
const response = await axios.get(`/channels/${props.id}`);
|
||||
const response = await axios.get<PayloadProps>(`/channels/${props.id}`);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { PayloadProps } from 'types/api/channels/getAll';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { Channels, PayloadProps } from 'types/api/channels/getAll';
|
||||
|
||||
const getAll = async (): Promise<
|
||||
SuccessResponse<PayloadProps> | ErrorResponse
|
||||
> => {
|
||||
const getAll = async (): Promise<SuccessResponseV2<Channels[]>> => {
|
||||
try {
|
||||
const response = await axios.get('/channels');
|
||||
const response = await axios.get<PayloadProps>('/channels');
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createEmail';
|
||||
|
||||
const testEmail = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/testChannel', {
|
||||
const response = await axios.post<PayloadProps>('/testChannel', {
|
||||
name: props.name,
|
||||
email_configs: [
|
||||
{
|
||||
@@ -21,13 +21,12 @@ const testEmail = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createMsTeams';
|
||||
|
||||
const testMsTeams = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/testChannel', {
|
||||
const response = await axios.post<PayloadProps>('/testChannel', {
|
||||
name: props.name,
|
||||
msteamsv2_configs: [
|
||||
{
|
||||
@@ -21,13 +21,12 @@ const testMsTeams = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createOpsgenie';
|
||||
|
||||
const testOpsgenie = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/testChannel', {
|
||||
const response = await axios.post<PayloadProps>('/testChannel', {
|
||||
name: props.name,
|
||||
opsgenie_configs: [
|
||||
{
|
||||
@@ -24,13 +24,12 @@ const testOpsgenie = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createPager';
|
||||
|
||||
const testPager = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/testChannel', {
|
||||
const response = await axios.post<PayloadProps>('/testChannel', {
|
||||
name: props.name,
|
||||
pagerduty_configs: [
|
||||
{
|
||||
@@ -29,13 +29,12 @@ const testPager = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createSlack';
|
||||
|
||||
const testSlack = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
const response = await axios.post('/testChannel', {
|
||||
const response = await axios.post<PayloadProps>('/testChannel', {
|
||||
name: props.name,
|
||||
slack_configs: [
|
||||
{
|
||||
@@ -22,13 +22,12 @@ const testSlack = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/channels/createWebhook';
|
||||
|
||||
const testWebhook = async (
|
||||
props: Props,
|
||||
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
|
||||
): Promise<SuccessResponseV2<PayloadProps>> => {
|
||||
try {
|
||||
let httpConfig = {};
|
||||
const username = props.username ? props.username.trim() : '';
|
||||
@@ -28,7 +28,7 @@ const testWebhook = async (
|
||||
};
|
||||
}
|
||||
|
||||
const response = await axios.post('/testChannel', {
|
||||
const response = await axios.post<PayloadProps>('/testChannel', {
|
||||
name: props.name,
|
||||
webhook_configs: [
|
||||
{
|
||||
@@ -40,13 +40,12 @@ const testWebhook = async (
|
||||
});
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: response.data.data,
|
||||
httpStatusCode: response.status,
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorResponseHandler(error as AxiosError);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import getLocalStorageApi from 'api/browser/localstorage/get';
|
||||
import loginApi from 'api/user/login';
|
||||
import loginApi from 'api/v1/user/login';
|
||||
import afterLogin from 'AppRoutes/utils';
|
||||
import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||
import { ENVIRONMENT } from 'constants/env';
|
||||
|
||||
@@ -222,6 +222,13 @@ export const getFunnelOverview = async (
|
||||
};
|
||||
};
|
||||
|
||||
export interface SlowTracesPayload {
|
||||
start_time: number;
|
||||
end_time: number;
|
||||
step_a_order: number;
|
||||
step_b_order: number;
|
||||
}
|
||||
|
||||
export interface SlowTraceData {
|
||||
status: string;
|
||||
data: Array<{
|
||||
@@ -236,7 +243,7 @@ export interface SlowTraceData {
|
||||
|
||||
export const getFunnelSlowTraces = async (
|
||||
funnelId: string,
|
||||
payload: FunnelOverviewPayload,
|
||||
payload: SlowTracesPayload,
|
||||
signal?: AbortSignal,
|
||||
): Promise<SuccessResponse<SlowTraceData> | ErrorResponse> => {
|
||||
const response = await axios.post(
|
||||
@@ -254,6 +261,12 @@ export const getFunnelSlowTraces = async (
|
||||
payload: response.data,
|
||||
};
|
||||
};
|
||||
export interface ErrorTracesPayload {
|
||||
start_time: number;
|
||||
end_time: number;
|
||||
step_a_order: number;
|
||||
step_b_order: number;
|
||||
}
|
||||
|
||||
export interface ErrorTraceData {
|
||||
status: string;
|
||||
@@ -269,10 +282,10 @@ export interface ErrorTraceData {
|
||||
|
||||
export const getFunnelErrorTraces = async (
|
||||
funnelId: string,
|
||||
payload: FunnelOverviewPayload,
|
||||
payload: ErrorTracesPayload,
|
||||
signal?: AbortSignal,
|
||||
): Promise<SuccessResponse<ErrorTraceData> | ErrorResponse> => {
|
||||
const response = await axios.post(
|
||||
const response: AxiosResponse = await axios.post(
|
||||
`${FUNNELS_BASE_PATH}/${funnelId}/analytics/error-traces`,
|
||||
payload,
|
||||
{
|
||||
@@ -324,37 +337,3 @@ export const getFunnelSteps = async (
|
||||
payload: response.data,
|
||||
};
|
||||
};
|
||||
|
||||
export interface FunnelStepsOverviewPayload {
|
||||
start_time: number;
|
||||
end_time: number;
|
||||
step_start?: number;
|
||||
step_end?: number;
|
||||
}
|
||||
|
||||
export interface FunnelStepsOverviewResponse {
|
||||
status: string;
|
||||
data: Array<{
|
||||
timestamp: string;
|
||||
data: Record<string, unknown>;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const getFunnelStepsOverview = async (
|
||||
funnelId: string,
|
||||
payload: FunnelStepsOverviewPayload,
|
||||
signal?: AbortSignal,
|
||||
): Promise<SuccessResponse<FunnelStepsOverviewResponse> | ErrorResponse> => {
|
||||
const response = await axios.post(
|
||||
`${FUNNELS_BASE_PATH}/${funnelId}/analytics/steps/overview`,
|
||||
payload,
|
||||
{ signal },
|
||||
);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: '',
|
||||
payload: response.data,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import axios from 'api';
|
||||
import { ErrorResponseHandlerV2 } from 'api/ErrorResponseHandlerV2';
|
||||
import { AxiosError } from 'axios';
|
||||
import { ErrorV2, SuccessResponseV2 } from 'types/api';
|
||||
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
|
||||
import { PayloadProps, Props } from 'types/api/user/login';
|
||||
|
||||
const login = async (
|
||||
@@ -17,7 +17,7 @@ const login = async (
|
||||
data: response.data,
|
||||
};
|
||||
} catch (error) {
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2>);
|
||||
ErrorResponseHandlerV2(error as AxiosError<ErrorV2Resp>);
|
||||
// this line is never reached but ts isn't detecting the never type properly for the ErrorResponseHandlerV2
|
||||
throw error;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ const getPreference = async (): Promise<
|
||||
SuccessResponse<PayloadProps> | ErrorResponse
|
||||
> => {
|
||||
try {
|
||||
const response = await axios.get(`/userPreferences`);
|
||||
const response = await axios.get(`/user/preferences`);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
@@ -1,11 +1,11 @@
|
||||
.dropdown-button {
|
||||
color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dropdown-button--dark {
|
||||
color: #000;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.dropdown-icon {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
@@ -4,19 +4,14 @@ export const getYAxisFormattedValue = (
|
||||
value: string,
|
||||
format: string,
|
||||
): string => {
|
||||
let decimalPrecision: number | undefined;
|
||||
const parsedValue = getValueFormat(format)(
|
||||
parseFloat(value),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
try {
|
||||
const parsedValue = getValueFormat(format)(
|
||||
parseFloat(value),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
||||
if (!parsedValue?.text) {
|
||||
return `${parseFloat(value)}`;
|
||||
}
|
||||
|
||||
let decimalPrecision: number | undefined;
|
||||
const decimalSplitted = parsedValue.text.split('.');
|
||||
if (decimalSplitted.length === 1) {
|
||||
decimalPrecision = 0;
|
||||
@@ -46,9 +41,9 @@ export const getYAxisFormattedValue = (
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error in getYAxisFormattedValue:', error);
|
||||
return `${parseFloat(value)}`;
|
||||
console.error(error);
|
||||
}
|
||||
return `${parseFloat(value)}`;
|
||||
};
|
||||
|
||||
export const getToolTipValue = (value: string, format?: string): string => {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
.learn-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
&,&:hover {
|
||||
color: var(--bg-robin-400) !important;
|
||||
}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 18px; /* 128.571% */
|
||||
letter-spacing: -0.07px;
|
||||
&,
|
||||
&:hover {
|
||||
color: var(--bg-robin-400) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ exports[`Quick Filters renders correctly with default props 1`] = `
|
||||
class="left-action"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-chevron-down"
|
||||
cursor="pointer"
|
||||
fill="none"
|
||||
@@ -347,6 +348,7 @@ exports[`Quick Filters renders correctly with default props 1`] = `
|
||||
class="left-action"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide lucide-chevron-right"
|
||||
cursor="pointer"
|
||||
fill="none"
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
.label-column {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.label-column--tag {
|
||||
white-space: normal;
|
||||
margin: 0.2rem 0.2rem;
|
||||
}
|
||||
.label-column--tag {
|
||||
white-space: normal;
|
||||
margin: 0.2rem 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
.overlay--text-wrap {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
@@ -8,4 +8,6 @@ export enum FeatureKeys {
|
||||
PREMIUM_SUPPORT = 'PREMIUM_SUPPORT',
|
||||
ANOMALY_DETECTION = 'ANOMALY_DETECTION',
|
||||
ONBOARDING_V3 = 'ONBOARDING_V3',
|
||||
THIRD_PARTY_API = 'THIRD_PARTY_API',
|
||||
TRACE_FUNNELS = 'TRACE_FUNNELS',
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ export const REACT_QUERY_KEY = {
|
||||
VALIDATE_FUNNEL_STEPS: 'VALIDATE_FUNNEL_STEPS',
|
||||
UPDATE_FUNNEL_STEP_DETAILS: 'UPDATE_FUNNEL_STEP_DETAILS',
|
||||
GET_FUNNEL_OVERVIEW: 'GET_FUNNEL_OVERVIEW',
|
||||
GET_FUNNEL_STEPS_OVERVIEW: 'GET_FUNNEL_STEPS_OVERVIEW',
|
||||
GET_FUNNEL_SLOW_TRACES: 'GET_FUNNEL_SLOW_TRACES',
|
||||
GET_FUNNEL_ERROR_TRACES: 'GET_FUNNEL_ERROR_TRACES',
|
||||
GET_FUNNEL_STEPS_GRAPH_DATA: 'GET_FUNNEL_STEPS_GRAPH_DATA',
|
||||
|
||||
@@ -10,7 +10,7 @@ import { useAppContext } from 'providers/App/App';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { Channels, PayloadProps } from 'types/api/channels/getAll';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
|
||||
import Delete from './Delete';
|
||||
|
||||
@@ -68,7 +68,7 @@ function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element {
|
||||
}
|
||||
|
||||
interface AlertChannelsProps {
|
||||
allChannels: PayloadProps;
|
||||
allChannels: Channels[];
|
||||
}
|
||||
|
||||
export default AlertChannels;
|
||||
|
||||
@@ -4,6 +4,7 @@ import deleteChannel from 'api/channels/delete';
|
||||
import { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
function Delete({ notifications, setChannels, id }: DeleteProps): JSX.Element {
|
||||
const { t } = useTranslation(['channels']);
|
||||
@@ -12,30 +13,20 @@ function Delete({ notifications, setChannels, id }: DeleteProps): JSX.Element {
|
||||
const onClickHandler = async (): Promise<void> => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await deleteChannel({
|
||||
await deleteChannel({
|
||||
id,
|
||||
});
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_delete_success'),
|
||||
});
|
||||
setChannels((preChannels) => preChannels.filter((e) => e.id !== id));
|
||||
} else {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_delete_unexp_error'),
|
||||
});
|
||||
}
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_delete_success'),
|
||||
});
|
||||
setChannels((preChannels) => preChannels.filter((e) => e.id !== id));
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description:
|
||||
error instanceof Error
|
||||
? error.toString()
|
||||
: t('channel_delete_unexp_error'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import ROUTES from 'constants/routes';
|
||||
import AlertChannels from 'container/AllAlertChannels';
|
||||
import { allAlertChannels } from 'mocks-server/__mockdata__/alerts';
|
||||
import { act, fireEvent, render, screen, waitFor } from 'tests/test-utils';
|
||||
|
||||
jest.mock('hooks/useFetch', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn().mockImplementation(() => ({
|
||||
payload: allAlertChannels,
|
||||
})),
|
||||
}));
|
||||
|
||||
const successNotification = jest.fn();
|
||||
jest.mock('hooks/useNotifications', () => ({
|
||||
__esModule: true,
|
||||
@@ -29,8 +21,11 @@ jest.mock('react-router-dom', () => ({
|
||||
}));
|
||||
|
||||
describe('Alert Channels Settings List page', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
render(<AlertChannels />);
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('sending_channels_note')).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import ROUTES from 'constants/routes';
|
||||
import AlertChannels from 'container/AllAlertChannels';
|
||||
import { allAlertChannels } from 'mocks-server/__mockdata__/alerts';
|
||||
import { fireEvent, render, screen, waitFor } from 'tests/test-utils';
|
||||
|
||||
jest.mock('hooks/useFetch', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn().mockImplementation(() => ({
|
||||
payload: allAlertChannels,
|
||||
})),
|
||||
}));
|
||||
|
||||
const successNotification = jest.fn();
|
||||
jest.mock('hooks/useNotifications', () => ({
|
||||
__esModule: true,
|
||||
@@ -34,27 +27,31 @@ jest.mock('react-router-dom', () => ({
|
||||
}));
|
||||
|
||||
describe('Alert Channels Settings List page (Normal User)', () => {
|
||||
beforeEach(() => {
|
||||
beforeEach(async () => {
|
||||
render(<AlertChannels />);
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('sending_channels_note')).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
describe('Should display the Alert Channels page properly', () => {
|
||||
it('Should check if "The alerts will be sent to all the configured channels." is visible ', () => {
|
||||
expect(screen.getByText('sending_channels_note')).toBeInTheDocument();
|
||||
it('Should check if "The alerts will be sent to all the configured channels." is visible ', async () => {
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('sending_channels_note')).toBeInTheDocument(),
|
||||
);
|
||||
});
|
||||
|
||||
it('Should check if "New Alert Channel" Button is visble and disabled', () => {
|
||||
it('Should check if "New Alert Channel" Button is visble and disabled', async () => {
|
||||
const newAlertButton = screen.getByRole('button', {
|
||||
name: 'plus button_new_channel',
|
||||
});
|
||||
expect(newAlertButton).toBeInTheDocument();
|
||||
await waitFor(() => expect(newAlertButton).toBeInTheDocument());
|
||||
expect(newAlertButton).toBeDisabled();
|
||||
});
|
||||
it('Should check if the help icon is visible and displays "tooltip_notification_channels ', async () => {
|
||||
const helpIcon = screen.getByLabelText('question-circle');
|
||||
|
||||
fireEvent.mouseOver(helpIcon);
|
||||
|
||||
await waitFor(() => {
|
||||
@@ -64,13 +61,13 @@ describe('Alert Channels Settings List page (Normal User)', () => {
|
||||
});
|
||||
});
|
||||
describe('Should check if the channels table is properly displayed', () => {
|
||||
it('Should check if the table columns are properly displayed', () => {
|
||||
it('Should check if the table columns are properly displayed', async () => {
|
||||
expect(screen.getByText('column_channel_name')).toBeInTheDocument();
|
||||
expect(screen.getByText('column_channel_type')).toBeInTheDocument();
|
||||
expect(screen.queryByText('column_channel_action')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should check if the data in the table is displayed properly', () => {
|
||||
it('Should check if the data in the table is displayed properly', async () => {
|
||||
expect(screen.getByText('Dummy-Channel')).toBeInTheDocument();
|
||||
expect(screen.getAllByText('slack')[0]).toBeInTheDocument();
|
||||
expect(screen.queryByText('column_channel_edit')).not.toBeInTheDocument();
|
||||
|
||||
@@ -119,12 +119,7 @@ describe('Create Alert Channel', () => {
|
||||
|
||||
fireEvent.click(saveButton);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(errorNotification).toHaveBeenCalledWith({
|
||||
description: 'Something went wrong',
|
||||
message: 'Error',
|
||||
}),
|
||||
);
|
||||
await waitFor(() => expect(errorNotification).toHaveBeenCalled());
|
||||
});
|
||||
it('Should check if clicking on Test button shows "An alert has been sent to this channel" success message if testing passes', async () => {
|
||||
server.use(
|
||||
@@ -158,12 +153,7 @@ describe('Create Alert Channel', () => {
|
||||
|
||||
fireEvent.click(testButton);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(errorNotification).toHaveBeenCalledWith({
|
||||
message: 'Error',
|
||||
description: 'channel_test_failed',
|
||||
}),
|
||||
);
|
||||
await waitFor(() => expect(errorNotification).toHaveBeenCalled());
|
||||
});
|
||||
});
|
||||
describe('New Alert Channel Cascading Fields Based on Channel Type', () => {
|
||||
|
||||
@@ -6,12 +6,15 @@ import Spinner from 'components/Spinner';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
import ROUTES from 'constants/routes';
|
||||
import useComponentPermission from 'hooks/useComponentPermission';
|
||||
import useFetch from 'hooks/useFetch';
|
||||
import history from 'lib/history';
|
||||
import { isUndefined } from 'lodash-es';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useQuery } from 'react-query';
|
||||
import { SuccessResponseV2 } from 'types/api';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
import AlertChannelsComponent from './AlertChannels';
|
||||
import { Button, ButtonContainer, RightActionContainer } from './styles';
|
||||
@@ -29,21 +32,26 @@ function AlertChannels(): JSX.Element {
|
||||
history.push(ROUTES.CHANNELS_NEW);
|
||||
}, []);
|
||||
|
||||
const { loading, payload, error, errorMessage } = useFetch(getAll);
|
||||
const { isLoading, data, error } = useQuery<
|
||||
SuccessResponseV2<Channels[]>,
|
||||
APIError
|
||||
>(['getChannels'], {
|
||||
queryFn: () => getAll(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!isUndefined(payload)) {
|
||||
if (!isUndefined(data?.data)) {
|
||||
logEvent('Alert Channel: Channel list page visited', {
|
||||
number: payload?.length,
|
||||
number: data?.data?.length,
|
||||
});
|
||||
}
|
||||
}, [payload]);
|
||||
}, [data?.data]);
|
||||
|
||||
if (error) {
|
||||
return <Typography>{errorMessage}</Typography>;
|
||||
return <Typography>{error.getErrorMessage()}</Typography>;
|
||||
}
|
||||
|
||||
if (loading || payload === undefined) {
|
||||
if (isLoading || isUndefined(data?.data)) {
|
||||
return <Spinner tip={t('loading_channels_message')} height="90vh" />;
|
||||
}
|
||||
|
||||
@@ -78,7 +86,7 @@ function AlertChannels(): JSX.Element {
|
||||
</RightActionContainer>
|
||||
</ButtonContainer>
|
||||
|
||||
<AlertChannelsComponent allChannels={payload} />
|
||||
<AlertChannelsComponent allChannels={data?.data || []} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import manageCreditCardApi from 'api/billing/manage';
|
||||
import getLocalStorageApi from 'api/browser/localstorage/get';
|
||||
import setLocalStorageApi from 'api/browser/localstorage/set';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import getUserLatestVersion from 'api/user/getLatestVersion';
|
||||
import getUserVersion from 'api/user/getVersion';
|
||||
import getUserLatestVersion from 'api/v1/version/getLatestVersion';
|
||||
import getUserVersion from 'api/v1/version/getVersion';
|
||||
import cx from 'classnames';
|
||||
import ChatSupportGateway from 'components/ChatSupportGateway/ChatSupportGateway';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
|
||||
@@ -35,13 +35,13 @@
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
padding: 8px 17px;
|
||||
|
||||
|
||||
&.primary {
|
||||
background: var(--bg-robin-500);
|
||||
border: none;
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
|
||||
|
||||
&.secondary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -45,4 +45,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { useNotifications } from 'hooks/useNotifications';
|
||||
import history from 'lib/history';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
import {
|
||||
ChannelType,
|
||||
@@ -136,28 +137,17 @@ function CreateAlertChannels({
|
||||
setSavingState(true);
|
||||
|
||||
try {
|
||||
const response = await createSlackApi(prepareSlackRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_creation_failed'),
|
||||
await createSlackApi(prepareSlackRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_creation_failed'),
|
||||
};
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
message: (error as APIError).error.error.code,
|
||||
description: (error as APIError).error.error.message,
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} finally {
|
||||
@@ -204,27 +194,17 @@ function CreateAlertChannels({
|
||||
setSavingState(true);
|
||||
try {
|
||||
const request = prepareWebhookRequest();
|
||||
const response = await createWebhookApi(request);
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_creation_failed'),
|
||||
await createWebhookApi(request);
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_creation_failed'),
|
||||
};
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} finally {
|
||||
@@ -264,34 +244,19 @@ function CreateAlertChannels({
|
||||
|
||||
try {
|
||||
if (request) {
|
||||
const response = await createPagerApi(request);
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_creation_failed'),
|
||||
await createPagerApi(request);
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_creation_failed'),
|
||||
};
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} finally {
|
||||
@@ -313,30 +278,18 @@ function CreateAlertChannels({
|
||||
|
||||
const onOpsgenieHandler = useCallback(async () => {
|
||||
setSavingState(true);
|
||||
|
||||
try {
|
||||
const response = await createOpsgenie(prepareOpsgenieRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_creation_failed'),
|
||||
await createOpsgenie(prepareOpsgenieRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_creation_failed'),
|
||||
};
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} finally {
|
||||
@@ -359,27 +312,17 @@ function CreateAlertChannels({
|
||||
setSavingState(true);
|
||||
try {
|
||||
const request = prepareEmailRequest();
|
||||
const response = await createEmail(request);
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_creation_failed'),
|
||||
await createEmail(request);
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_creation_failed'),
|
||||
};
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} finally {
|
||||
@@ -402,28 +345,17 @@ function CreateAlertChannels({
|
||||
setSavingState(true);
|
||||
|
||||
try {
|
||||
const response = await createMsTeamsApi(prepareMsTeamsRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_creation_failed'),
|
||||
await createMsTeamsApi(prepareMsTeamsRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_creation_done'),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_creation_failed'),
|
||||
};
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_creation_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_creation_failed'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return { status: 'failed', statusMessage: t('channel_creation_failed') };
|
||||
} finally {
|
||||
@@ -481,31 +413,30 @@ function CreateAlertChannels({
|
||||
setTestingState(true);
|
||||
try {
|
||||
let request;
|
||||
let response;
|
||||
switch (channelType) {
|
||||
case ChannelType.Webhook:
|
||||
request = prepareWebhookRequest();
|
||||
response = await testWebhookApi(request);
|
||||
await testWebhookApi(request);
|
||||
break;
|
||||
case ChannelType.Slack:
|
||||
request = prepareSlackRequest();
|
||||
response = await testSlackApi(request);
|
||||
await testSlackApi(request);
|
||||
break;
|
||||
case ChannelType.Pagerduty:
|
||||
request = preparePagerRequest();
|
||||
if (request) response = await testPagerApi(request);
|
||||
if (request) await testPagerApi(request);
|
||||
break;
|
||||
case ChannelType.MsTeams:
|
||||
request = prepareMsTeamsRequest();
|
||||
response = await testMsTeamsApi(request);
|
||||
await testMsTeamsApi(request);
|
||||
break;
|
||||
case ChannelType.Opsgenie:
|
||||
request = prepareOpsgenieRequest();
|
||||
response = await testOpsGenie(request);
|
||||
await testOpsGenie(request);
|
||||
break;
|
||||
case ChannelType.Email:
|
||||
request = prepareEmailRequest();
|
||||
response = await testEmail(request);
|
||||
await testEmail(request);
|
||||
break;
|
||||
default:
|
||||
notifications.error({
|
||||
@@ -516,30 +447,28 @@ function CreateAlertChannels({
|
||||
return;
|
||||
}
|
||||
|
||||
if (response && response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_test_done'),
|
||||
});
|
||||
} else {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_test_failed'),
|
||||
});
|
||||
}
|
||||
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_test_done'),
|
||||
});
|
||||
logEvent('Alert Channel: Test notification', {
|
||||
type: channelType,
|
||||
sendResolvedAlert: selectedConfig?.send_resolved,
|
||||
name: selectedConfig?.name,
|
||||
new: 'true',
|
||||
status:
|
||||
response && response.statusCode === 200 ? 'Test success' : 'Test failed',
|
||||
status: 'Test success',
|
||||
});
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_test_unexpected'),
|
||||
message: (error as APIError).error.error.code,
|
||||
description: (error as APIError).error.error.message,
|
||||
});
|
||||
logEvent('Alert Channel: Test notification', {
|
||||
type: channelType,
|
||||
sendResolvedAlert: selectedConfig?.send_resolved,
|
||||
name: selectedConfig?.name,
|
||||
new: 'true',
|
||||
status: 'Test failed',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.download-button {
|
||||
display: flex;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import history from 'lib/history';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
function EditAlertChannels({
|
||||
initialValue,
|
||||
@@ -93,9 +94,8 @@ function EditAlertChannels({
|
||||
return { status: 'failed', statusMessage: t('webhook_url_required') };
|
||||
}
|
||||
|
||||
const response = await editSlackApi(prepareSlackRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
try {
|
||||
await editSlackApi(prepareSlackRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_edit_done'),
|
||||
@@ -103,16 +103,19 @@ function EditAlertChannels({
|
||||
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_edit_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage:
|
||||
(error as APIError).getErrorMessage() || t('channel_edit_failed'),
|
||||
};
|
||||
} finally {
|
||||
setSavingState(false);
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_edit_failed'),
|
||||
});
|
||||
setSavingState(false);
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_edit_failed'),
|
||||
};
|
||||
}, [prepareSlackRequest, t, notifications, selectedConfig]);
|
||||
|
||||
const prepareWebhookRequest = useCallback(() => {
|
||||
@@ -150,9 +153,8 @@ function EditAlertChannels({
|
||||
return { status: 'failed', statusMessage: t('username_no_password') };
|
||||
}
|
||||
|
||||
const response = await editWebhookApi(prepareWebhookRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
try {
|
||||
await editWebhookApi(prepareWebhookRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_edit_done'),
|
||||
@@ -160,14 +162,19 @@ function EditAlertChannels({
|
||||
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_edit_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage:
|
||||
(error as APIError).getErrorMessage() || t('channel_edit_failed'),
|
||||
};
|
||||
} finally {
|
||||
setSavingState(false);
|
||||
}
|
||||
showError(response.error || t('channel_edit_failed'));
|
||||
|
||||
setSavingState(false);
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_edit_failed'),
|
||||
};
|
||||
}, [prepareWebhookRequest, t, notifications, selectedConfig]);
|
||||
|
||||
const prepareEmailRequest = useCallback(
|
||||
@@ -185,25 +192,28 @@ function EditAlertChannels({
|
||||
const onEmailEditHandler = useCallback(async () => {
|
||||
setSavingState(true);
|
||||
const request = prepareEmailRequest();
|
||||
const response = await editEmail(request);
|
||||
if (response.statusCode === 200) {
|
||||
|
||||
try {
|
||||
await editEmail(request);
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_edit_done'),
|
||||
});
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_edit_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage:
|
||||
(error as APIError).getErrorMessage() || t('channel_edit_failed'),
|
||||
};
|
||||
} finally {
|
||||
setSavingState(false);
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_edit_failed'),
|
||||
});
|
||||
|
||||
setSavingState(false);
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_edit_failed'),
|
||||
};
|
||||
}, [prepareEmailRequest, t, notifications]);
|
||||
|
||||
const preparePagerRequest = useCallback(
|
||||
@@ -237,27 +247,28 @@ function EditAlertChannels({
|
||||
setSavingState(false);
|
||||
return { status: 'failed', statusMessage: validationError };
|
||||
}
|
||||
const response = await editPagerApi(preparePagerRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
try {
|
||||
await editPagerApi(preparePagerRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_edit_done'),
|
||||
});
|
||||
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_edit_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage:
|
||||
(error as APIError).getErrorMessage() || t('channel_edit_failed'),
|
||||
};
|
||||
} finally {
|
||||
setSavingState(false);
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_edit_failed'),
|
||||
});
|
||||
|
||||
setSavingState(false);
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_edit_failed'),
|
||||
};
|
||||
}, [preparePagerRequest, notifications, selectedConfig, t]);
|
||||
|
||||
const prepareOpsgenieRequest = useCallback(
|
||||
@@ -284,28 +295,27 @@ function EditAlertChannels({
|
||||
setSavingState(false);
|
||||
return { status: 'failed', statusMessage: t('api_key_required') };
|
||||
}
|
||||
|
||||
const response = await editOpsgenie(prepareOpsgenieRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
try {
|
||||
await editOpsgenie(prepareOpsgenieRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_edit_done'),
|
||||
});
|
||||
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_edit_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage:
|
||||
(error as APIError).getErrorMessage() || t('channel_edit_failed'),
|
||||
};
|
||||
} finally {
|
||||
setSavingState(false);
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_edit_failed'),
|
||||
});
|
||||
|
||||
setSavingState(false);
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_edit_failed'),
|
||||
};
|
||||
}, [prepareOpsgenieRequest, t, notifications, selectedConfig]);
|
||||
|
||||
const prepareMsTeamsRequest = useCallback(
|
||||
@@ -332,27 +342,27 @@ function EditAlertChannels({
|
||||
return { status: 'failed', statusMessage: t('webhook_url_required') };
|
||||
}
|
||||
|
||||
const response = await editMsTeamsApi(prepareMsTeamsRequest());
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
try {
|
||||
await editMsTeamsApi(prepareMsTeamsRequest());
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_edit_done'),
|
||||
});
|
||||
|
||||
history.replace(ROUTES.ALL_CHANNELS);
|
||||
return { status: 'success', statusMessage: t('channel_edit_done') };
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage:
|
||||
(error as APIError).getErrorMessage() || t('channel_edit_failed'),
|
||||
};
|
||||
} finally {
|
||||
setSavingState(false);
|
||||
}
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: response.error || t('channel_edit_failed'),
|
||||
});
|
||||
|
||||
setSavingState(false);
|
||||
return {
|
||||
status: 'failed',
|
||||
statusMessage: response.error || t('channel_edit_failed'),
|
||||
};
|
||||
}, [prepareMsTeamsRequest, t, notifications, selectedConfig]);
|
||||
|
||||
const onSaveHandler = useCallback(
|
||||
@@ -396,31 +406,30 @@ function EditAlertChannels({
|
||||
setTestingState(true);
|
||||
try {
|
||||
let request;
|
||||
let response;
|
||||
switch (channelType) {
|
||||
case ChannelType.Webhook:
|
||||
request = prepareWebhookRequest();
|
||||
response = await testWebhookApi(request);
|
||||
await testWebhookApi(request);
|
||||
break;
|
||||
case ChannelType.Slack:
|
||||
request = prepareSlackRequest();
|
||||
response = await testSlackApi(request);
|
||||
await testSlackApi(request);
|
||||
break;
|
||||
case ChannelType.Pagerduty:
|
||||
request = preparePagerRequest();
|
||||
if (request) response = await testPagerApi(request);
|
||||
if (request) await testPagerApi(request);
|
||||
break;
|
||||
case ChannelType.MsTeams:
|
||||
request = prepareMsTeamsRequest();
|
||||
if (request) response = await testMsTeamsApi(request);
|
||||
if (request) await testMsTeamsApi(request);
|
||||
break;
|
||||
case ChannelType.Opsgenie:
|
||||
request = prepareOpsgenieRequest();
|
||||
if (request) response = await testOpsgenie(request);
|
||||
if (request) await testOpsgenie(request);
|
||||
break;
|
||||
case ChannelType.Email:
|
||||
request = prepareEmailRequest();
|
||||
if (request) response = await testEmail(request);
|
||||
if (request) await testEmail(request);
|
||||
break;
|
||||
default:
|
||||
notifications.error({
|
||||
@@ -431,29 +440,28 @@ function EditAlertChannels({
|
||||
return;
|
||||
}
|
||||
|
||||
if (response && response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_test_done'),
|
||||
});
|
||||
} else {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_test_failed'),
|
||||
});
|
||||
}
|
||||
notifications.success({
|
||||
message: 'Success',
|
||||
description: t('channel_test_done'),
|
||||
});
|
||||
logEvent('Alert Channel: Test notification', {
|
||||
type: channelType,
|
||||
sendResolvedAlert: selectedConfig?.send_resolved,
|
||||
name: selectedConfig?.name,
|
||||
new: 'false',
|
||||
status:
|
||||
response && response.statusCode === 200 ? 'Test success' : 'Test failed',
|
||||
status: 'Test success',
|
||||
});
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: t('channel_test_failed'),
|
||||
message: (error as APIError).getErrorCode(),
|
||||
description: (error as APIError).getErrorMessage(),
|
||||
});
|
||||
logEvent('Alert Channel: Test notification', {
|
||||
type: channelType,
|
||||
sendResolvedAlert: selectedConfig?.send_resolved,
|
||||
name: selectedConfig?.name,
|
||||
new: 'false',
|
||||
status: 'Test failed',
|
||||
});
|
||||
}
|
||||
setTestingState(false);
|
||||
|
||||
@@ -1,55 +1,54 @@
|
||||
.explorer-option-droppable-container {
|
||||
position: fixed;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: -webkit-fill-available;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
// box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25);
|
||||
// backdrop-filter: blur(20px);
|
||||
width: -webkit-fill-available;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
// box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25);
|
||||
// backdrop-filter: blur(20px);
|
||||
|
||||
.explorer-actions-btn {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-right: 8px;
|
||||
.explorer-actions-btn {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-right: 8px;
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25);
|
||||
backdrop-filter: blur(20px);
|
||||
height: 24px !important;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.action-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25);
|
||||
backdrop-filter: blur(20px);
|
||||
height: 24px !important;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.explorer-show-btn {
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: rgba(22, 24, 29, 0.40);
|
||||
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25);
|
||||
backdrop-filter: blur(20px);
|
||||
align-self: center;
|
||||
padding: 8px 12px;
|
||||
height: 24px !important;
|
||||
.explorer-show-btn {
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
background: rgba(22, 24, 29, 0.4);
|
||||
box-shadow: 0px 4px 16px 0px rgba(0, 0, 0, 0.25);
|
||||
backdrop-filter: blur(20px);
|
||||
align-self: center;
|
||||
padding: 8px 12px;
|
||||
height: 24px !important;
|
||||
|
||||
.menu-bar {
|
||||
border-radius: 50px;
|
||||
background: var(--bg-slate-200);
|
||||
height: 4px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
.menu-bar {
|
||||
border-radius: 50px;
|
||||
background: var(--bg-slate-200);
|
||||
height: 4px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lightMode {
|
||||
.explorer-option-droppable-container {
|
||||
|
||||
.explorer-show-btn {
|
||||
background: var(--bg-vanilla-200);
|
||||
}
|
||||
}
|
||||
}
|
||||
.explorer-option-droppable-container {
|
||||
.explorer-show-btn {
|
||||
background: var(--bg-vanilla-200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,20 @@ import './FormAlertRules.styles.scss';
|
||||
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Form, Select, Switch, Tooltip } from 'antd';
|
||||
import getChannels from 'api/channels/getAll';
|
||||
import getAll from 'api/channels/getAll';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
|
||||
import ROUTES from 'constants/routes';
|
||||
import useComponentPermission from 'hooks/useComponentPermission';
|
||||
import useFetch from 'hooks/useFetch';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useQuery } from 'react-query';
|
||||
import { SuccessResponseV2 } from 'types/api';
|
||||
import { AlertTypes } from 'types/api/alerts/alertTypes';
|
||||
import { AlertDef, Labels } from 'types/api/alerts/def';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
import APIError from 'types/api/error';
|
||||
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
@@ -42,7 +45,13 @@ function BasicInfo({
|
||||
}: BasicInfoProps): JSX.Element {
|
||||
const { t } = useTranslation('alerts');
|
||||
|
||||
const channels = useFetch(getChannels);
|
||||
const { isLoading, data, error, isError, refetch } = useQuery<
|
||||
SuccessResponseV2<Channels[]>,
|
||||
APIError
|
||||
>(['getChannels'], {
|
||||
queryFn: () => getAll(),
|
||||
});
|
||||
|
||||
const { user } = useAppContext();
|
||||
const [addNewChannelPermission] = useComponentPermission(
|
||||
['add_new_channel'],
|
||||
@@ -72,7 +81,7 @@ function BasicInfo({
|
||||
});
|
||||
};
|
||||
|
||||
const noChannels = channels.payload?.length === 0;
|
||||
const noChannels = data?.data?.length === 0;
|
||||
const handleCreateNewChannels = useCallback(() => {
|
||||
logEvent('Alert: Create notification channel button clicked', {
|
||||
dataSource: ALERTS_DATA_SOURCE_MAP[alertDef?.alertType as AlertTypes],
|
||||
@@ -84,18 +93,18 @@ function BasicInfo({
|
||||
const hasLoggedEvent = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!channels.loading && isNewRule && !hasLoggedEvent.current) {
|
||||
if (!isLoading && isNewRule && !hasLoggedEvent.current) {
|
||||
logEvent('Alert: New alert creation page visited', {
|
||||
dataSource: ALERTS_DATA_SOURCE_MAP[alertDef?.alertType as AlertTypes],
|
||||
numberOfChannels: channels?.payload?.length,
|
||||
numberOfChannels: data?.data?.length,
|
||||
});
|
||||
hasLoggedEvent.current = true;
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [channels.loading]);
|
||||
}, [isLoading]);
|
||||
|
||||
const refetchChannels = async (): Promise<void> => {
|
||||
await channels.refetch();
|
||||
await refetch();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -192,7 +201,7 @@ function BasicInfo({
|
||||
<Switch
|
||||
checked={shouldBroadCastToAllChannels}
|
||||
onChange={handleBroadcastToAllChannels}
|
||||
disabled={noChannels || !!channels.loading}
|
||||
disabled={noChannels || !!isLoading}
|
||||
data-testid="alert-broadcast-to-all-channels"
|
||||
/>
|
||||
</Tooltip>
|
||||
@@ -220,7 +229,10 @@ function BasicInfo({
|
||||
disabled={shouldBroadCastToAllChannels}
|
||||
currentValue={alertDef.preferredChannels}
|
||||
handleCreateNewChannels={handleCreateNewChannels}
|
||||
channels={channels}
|
||||
channels={data?.data || []}
|
||||
isLoading={isLoading}
|
||||
hasError={isError}
|
||||
error={error as APIError}
|
||||
onSelectChannels={(preferredChannels): void => {
|
||||
setAlertDef({
|
||||
...alertDef,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Select, Spin } from 'antd';
|
||||
import useComponentPermission from 'hooks/useComponentPermission';
|
||||
import { State } from 'hooks/useFetch';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { ReactNode } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PayloadProps } from 'types/api/channels/getAll';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
import { StyledCreateChannelOption, StyledSelect } from './styles';
|
||||
|
||||
@@ -15,7 +15,10 @@ export interface ChannelSelectProps {
|
||||
currentValue?: string[];
|
||||
onSelectChannels: (s: string[]) => void;
|
||||
onDropdownOpen: () => void;
|
||||
channels: State<PayloadProps | undefined>;
|
||||
isLoading: boolean;
|
||||
channels: Channels[];
|
||||
hasError: boolean;
|
||||
error: APIError;
|
||||
handleCreateNewChannels: () => void;
|
||||
}
|
||||
|
||||
@@ -25,6 +28,9 @@ function ChannelSelect({
|
||||
onSelectChannels,
|
||||
onDropdownOpen,
|
||||
channels,
|
||||
isLoading,
|
||||
hasError,
|
||||
error,
|
||||
handleCreateNewChannels,
|
||||
}: ChannelSelectProps): JSX.Element | null {
|
||||
// init namespace for translations
|
||||
@@ -40,10 +46,10 @@ function ChannelSelect({
|
||||
onSelectChannels(value);
|
||||
};
|
||||
|
||||
if (channels.error && channels.errorMessage !== '') {
|
||||
if (hasError) {
|
||||
notifications.error({
|
||||
message: 'Error',
|
||||
description: channels.errorMessage,
|
||||
message: error.getErrorCode(),
|
||||
description: error.getErrorMessage(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,7 +62,7 @@ function ChannelSelect({
|
||||
const renderOptions = (): ReactNode[] => {
|
||||
const children: ReactNode[] = [];
|
||||
|
||||
if (!channels.loading && addNewChannelPermission) {
|
||||
if (!isLoading && addNewChannelPermission) {
|
||||
children.push(
|
||||
<Select.Option key="add-new-channel" value="add-new-channel">
|
||||
<StyledCreateChannelOption>
|
||||
@@ -67,15 +73,11 @@ function ChannelSelect({
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
channels.loading ||
|
||||
channels.payload === undefined ||
|
||||
channels.payload.length === 0
|
||||
) {
|
||||
if (isLoading || channels.length === 0) {
|
||||
return children;
|
||||
}
|
||||
|
||||
channels.payload.forEach((o) => {
|
||||
channels.forEach((o) => {
|
||||
children.push(
|
||||
<Select.Option key={o.id} value={o.name}>
|
||||
{o.name}
|
||||
@@ -89,13 +91,13 @@ function ChannelSelect({
|
||||
return (
|
||||
<StyledSelect
|
||||
disabled={disabled}
|
||||
status={channels.error ? 'error' : ''}
|
||||
status={hasError ? 'error' : ''}
|
||||
mode="multiple"
|
||||
style={{ width: '100%' }}
|
||||
placeholder={t('placeholder_channel_select')}
|
||||
data-testid="alert-channel-select"
|
||||
value={currentValue}
|
||||
notFoundContent={channels.loading && <Spin size="small" />}
|
||||
notFoundContent={isLoading && <Spin size="small" />}
|
||||
onDropdownVisibleChange={(open): void => {
|
||||
if (open) {
|
||||
onDropdownOpen();
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
.context-log-renderer {
|
||||
.virtuoso-list {
|
||||
overflow-y: hidden !important;
|
||||
.virtuoso-list {
|
||||
overflow-y: hidden !important;
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.3rem;
|
||||
height: 0.3rem;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--bg-slate-300);
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--bg-slate-300);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--bg-slate-200);
|
||||
}
|
||||
|
||||
.ant-row {
|
||||
width: fit-content;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--bg-slate-200);
|
||||
}
|
||||
|
||||
.ant-row {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
&__item {
|
||||
width: 100%;
|
||||
.raw-log-content {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&__item {
|
||||
width: 100%;
|
||||
.raw-log-content {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
.log-context-container {
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: scroll;
|
||||
overflow-x: hidden;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.3rem;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.3rem;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--bg-slate-300);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--bg-slate-200);
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--bg-slate-300);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--bg-slate-200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
.empty-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.infra-metrics-container {
|
||||
.views-tabs {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.views-tabs {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.infra-metrics-card {
|
||||
margin: 1rem 0;
|
||||
height: 300px;
|
||||
padding: 10px;
|
||||
margin: 1rem 0;
|
||||
height: 300px;
|
||||
padding: 10px;
|
||||
|
||||
.ant-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
.ant-card-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.no-data-container {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.no-data-container {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
.log-context-container {
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
}
|
||||
border: 1px solid var(--bg-slate-400);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Button, Form, Input, Space, Tooltip, Typography } from 'antd';
|
||||
import getLocalStorageApi from 'api/browser/localstorage/get';
|
||||
import setLocalStorageApi from 'api/browser/localstorage/set';
|
||||
import getUserVersion from 'api/user/getVersion';
|
||||
import loginApi from 'api/user/login';
|
||||
import loginPrecheckApi from 'api/user/loginPrecheck';
|
||||
import loginPrecheckApi from 'api/v1/login/loginPrecheck';
|
||||
import loginApi from 'api/v1/user/login';
|
||||
import getUserVersion from 'api/v1/version/getVersion';
|
||||
import afterLogin from 'AppRoutes/utils';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { getQueryStats, WsDataEvent } from 'api/common/getQueryStats';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
|
||||
import LogsFormatOptionsMenu from 'components/LogsFormatOptionsMenu/LogsFormatOptionsMenu';
|
||||
import { DEFAULT_ENTITY_VERSION } from 'constants/app';
|
||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { AVAILABLE_EXPORT_PANEL_TYPES } from 'constants/panelTypes';
|
||||
@@ -247,7 +247,7 @@ function LogsExplorerViews({
|
||||
} = useGetExplorerQueryRange(
|
||||
listChartQuery,
|
||||
PANEL_TYPES.TIME_SERIES,
|
||||
DEFAULT_ENTITY_VERSION,
|
||||
ENTITY_VERSION_V4,
|
||||
{
|
||||
enabled: !!listChartQuery && panelType === PANEL_TYPES.LIST,
|
||||
},
|
||||
@@ -265,7 +265,7 @@ function LogsExplorerViews({
|
||||
} = useGetExplorerQueryRange(
|
||||
requestData,
|
||||
panelType,
|
||||
DEFAULT_ENTITY_VERSION,
|
||||
ENTITY_VERSION_V4,
|
||||
{
|
||||
keepPreviousData: true,
|
||||
enabled: !isLimit && !!requestData,
|
||||
|
||||
@@ -2,30 +2,33 @@
|
||||
// @ts-ignore
|
||||
// @ts-nocheck
|
||||
|
||||
import { QueryTypes, ConditionalOperators, ValidTypeSequence, ValidTypeValue } from 'lib/logql/tokens';
|
||||
import {
|
||||
QueryTypes,
|
||||
ConditionalOperators,
|
||||
ValidTypeSequence,
|
||||
ValidTypeValue,
|
||||
} from 'lib/logql/tokens';
|
||||
|
||||
export interface QueryFields {
|
||||
type: keyof typeof QueryTypes;
|
||||
value: string | string[];
|
||||
}
|
||||
|
||||
|
||||
export function fieldsQueryIsvalid(queryFields: QueryFields[]): boolean {
|
||||
let lastOp: string;
|
||||
let result = true;
|
||||
queryFields.forEach((q, idx)=> {
|
||||
|
||||
queryFields.forEach((q, idx) => {
|
||||
if (!q.value || q.value === null || q.value === '') result = false;
|
||||
|
||||
if (Array.isArray(q.value) && q.value.length === 0 ) result = false;
|
||||
|
||||
const nextOp = idx < queryFields.length ? queryFields[idx+1]: undefined;
|
||||
if (!ValidTypeSequence(lastOp?.type, q?.type, nextOp?.type)) result = false
|
||||
if (Array.isArray(q.value) && q.value.length === 0) result = false;
|
||||
|
||||
const nextOp = idx < queryFields.length ? queryFields[idx + 1] : undefined;
|
||||
if (!ValidTypeSequence(lastOp?.type, q?.type, nextOp?.type)) result = false;
|
||||
|
||||
if (!ValidTypeValue(lastOp?.value, q.value)) result = false;
|
||||
lastOp = q;
|
||||
});
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
|
||||
export const queryKOVPair = (): QueryFields[] => [
|
||||
@@ -43,7 +46,11 @@ export const queryKOVPair = (): QueryFields[] => [
|
||||
},
|
||||
];
|
||||
|
||||
export const initQueryKOVPair = (name?: string = null, op?: string = null , value?: string | string[] = null ): QueryFields[] => [
|
||||
export const initQueryKOVPair = (
|
||||
name?: string = null,
|
||||
op?: string = null,
|
||||
value?: string | string[] = null,
|
||||
): QueryFields[] => [
|
||||
{
|
||||
type: QueryTypes.QUERY_KEY,
|
||||
value: name,
|
||||
@@ -58,12 +65,14 @@ export const initQueryKOVPair = (name?: string = null, op?: string = null , val
|
||||
},
|
||||
];
|
||||
|
||||
export const prepareConditionOperator = (op?: string = ConditionalOperators.AND): QueryFields => {
|
||||
export const prepareConditionOperator = (
|
||||
op?: string = ConditionalOperators.AND,
|
||||
): QueryFields => {
|
||||
return {
|
||||
type: QueryTypes.CONDITIONAL_OPERATOR,
|
||||
value: op,
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const createParsedQueryStructure = (parsedQuery = []) => {
|
||||
if (!parsedQuery.length) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.graph-controls-panel {
|
||||
position: absolute;
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
display: none;
|
||||
width: 110px;
|
||||
@@ -22,4 +22,4 @@
|
||||
.ant-btn-link:hover {
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
.top-operation {
|
||||
position: relative;
|
||||
.top-operation--download {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
position: relative;
|
||||
.top-operation--download {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
}
|
||||
|
||||
.explore-content {
|
||||
margin-top: 10px;
|
||||
|
||||
.ant-space {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
@@ -75,16 +77,14 @@
|
||||
}
|
||||
|
||||
.time-series-container {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(
|
||||
auto-fit,
|
||||
minmax(min(100%, calc(50% - 8px)), 1fr)
|
||||
);
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
height: fit-content;
|
||||
overflow-y: scroll;
|
||||
|
||||
.time-series-view {
|
||||
min-width: 80%;
|
||||
width: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.related-metrics-container {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user