Compare commits

..

41 Commits

Author SHA1 Message Date
Yunus M
f13b083277 feat: api / ingestion keys - initial commit 2024-02-03 02:44:29 +05:30
Vikrant Gupta
efc7aff7a2 fix: loading states for list log view (#4486) 2024-02-02 17:25:07 +05:30
Vikrant Gupta
f04937bbd1 feat: support custom times unique to pages new design changes (#4485) 2024-02-02 17:05:46 +05:30
Vikrant Gupta
fce66a2c5c fix: logs explorer issues (#4483)
* fix: logs explorer issues

* fix: jest test cases
2024-02-02 16:58:58 +05:30
Yunus M
3b4fb3eb80 UI feedback updates (#4482)
* feat: handle loading and fix ui issues

* feat: ui updates
2024-02-02 14:52:28 +05:30
Yunus M
e3ddd0470e feat: handle loading states and incorporate ui feedback (#4479) 2024-02-02 11:14:55 +05:30
Vikrant Gupta
e88b6e400d fix: update TODO and remove extra braces 2024-01-31 22:35:12 +05:30
Vikrant Gupta
857a1e9356 fix: jest config issues 2024-01-31 19:32:30 +05:30
Yunus M
5c0096623c chore: fix tsc issues 2024-01-31 16:34:14 +05:30
Rajat Dabade
32380d5688 [Feat]: View in Traces (#4450)
* refactor: datetime selector beside run query removed add to dashboard

* refactor: added tab for traces view details page

* refactor: done with the save view in traces

* fix: the gittery effect when navigatigating from views

* refactor: view tab view title light mode support

* refactor: removed console

* fix: gittery effect when switch view from views tabs

* refactor: separate traces routes

* refactor: remove query params
2024-01-31 16:16:53 +05:30
Vikrant Gupta
55a0cbc3f1 fix: switching between logs display tabs (#4457) 2024-01-31 16:16:53 +05:30
Rajat Dabade
d319ce99d6 [Refactor]: Tab Switch deplay issue and UI improvement for Clickhouse (#4409) 2024-01-31 16:16:49 +05:30
Vikrant Gupta
dc74592347 feat: added loading and error states for logs design (#4452)
* feat: added loading and error states for logs design

* feat: added error states for table view and time series view

* feat: handle error and loading states

* feat: loading states
2024-01-31 16:16:13 +05:30
Yunus M
5ef07a229d feat: update ui (#4449) 2024-01-31 16:16:13 +05:30
Vikrant Gupta
17b4e69f8b feat: [GH-4436]: date range enhancements (#4448)
* feat: [GH-4436]: when selecting custom time range it should be from start of day to end of date

* fix: custom time width and refresh text visibility issues (#4428)

---------

Co-authored-by: Yunus M <myounis.ar@live.com>
2024-01-31 16:16:12 +05:30
Rajat Dabade
aecd10ef24 refactor: New design for Save views. (#4435) 2024-01-31 16:16:12 +05:30
Vikrant Gupta
7f0574061f fix: logs UI improvements (#4426)
* fix: remove fixed times from the date time picker v2

* fix: added old logs explorer CTA in new designs

* feat: handle active logs indicator update

* fix: address review comments

* fix: old logs explorer page

* fix: remove info text and add relative time buttons

* fix: update logs explorer tab designs

* fix: update logs explorer tab designs

* fix: update logs explorer tab designs
2024-01-31 16:16:12 +05:30
Vikrant Gupta
71266836f8 feat: add raw view attributes in the logs list view (#4422)
* feat: add raw view attributes in the logs list view

* feat: add raw view attributes in the logs list view

* fix: raw attributes
2024-01-31 16:16:12 +05:30
Yunus M
4d4cd72ab2 feat: update styles for logs detail view (#4407)
* feat: update styles for logs detail view

* feat: update styles for logs detail view
2024-01-31 16:16:12 +05:30
Rajat Dabade
b3f1fdefe6 feat: save view for new design (#4392)
* feat: save view for new design

* refactor: done with save view
2024-01-31 16:16:12 +05:30
Rajat Dabade
5fea20f4e7 [Refactor]: New design for Log details page (#4362)
New design for Log details page 

Co-authored-by: Vikrant Gupta <vikrant.thomso@gmail.com>
Co-authored-by: Yunus M <myounis.ar@live.com>
2024-01-31 16:16:12 +05:30
Yunus M
195035f035 Settings theme change (#4368)
* feat: settings theme change
2024-01-31 16:16:08 +05:30
Vikrant Gupta
5c283a3013 chore: styles improvement across new design (#4389)
* fix: improve date time styles

* feat: table view changes according to new design

* fix: button visibility in clickhouse and promQL headers (#4390)

* feat: change the tabs to new design buttons for query builder
2024-01-31 16:15:24 +05:30
Vikrant Gupta
b81d3598bc feat: handle new typing changes for date time picker v2 (#4386)
Co-authored-by: Yunus M <myounis.ar@live.com>
2024-01-31 16:15:20 +05:30
Vikrant Gupta
01f1bee3cd fix: virtuoso scroll refresh issue 2024-01-31 16:12:17 +05:30
Vikrant Gupta
077d23e7b4 feat: handle light theme 2024-01-31 16:12:17 +05:30
Vikrant Gupta
212a36a233 feat: handle light theme 2024-01-31 16:12:17 +05:30
Vikrant Gupta
d296ea9574 feat: handle qb design changes across the application 2024-01-31 16:12:17 +05:30
Vikrant Gupta
065bc3d55d fix: remove dangling border after element removal 2024-01-31 16:12:17 +05:30
Vikrant Gupta
e60f430d66 feat: integrate date time selector across app 2024-01-31 16:12:17 +05:30
Vikrant Gupta
fca51d3d06 feat: date time custom time modal to render inside the new popover (#4366)
* feat: single calender for range picker

* fix: edgecases
2024-01-31 16:12:12 +05:30
Vikrant Gupta
630bf74e4f feat: handle light theme for logs explorer design changes (#4363)
* feat: handle light theme for list tables and dateTime selection

* feat: handle light theme for popover

* fix: address review comments
2024-01-31 16:11:50 +05:30
Vikrant Gupta
109e4e0bed fix: type errors (#4360) 2024-01-31 16:11:50 +05:30
Vikrant Gupta
7b5bb46b84 fix: eslint error 2024-01-31 16:11:50 +05:30
Vikrant Gupta
bc5e409c73 feat: new table view for logs explorer list section (#4353)
* feat: table view changes for logs list

* feat: code refactor to support log line actions

* feat: code refactor to support log line actions

* fix: the positioning of the btns

* feat: fix the table onclick

* fix: header issue

* fix: on hover

* fix: type issue
2024-01-31 16:11:50 +05:30
Yunus M
ccc7cb5b42 fix: lint errors 2024-01-31 16:11:50 +05:30
Yunus M
9423531db1 Query builder design update (#4359)
* feat: QB design update

* fix: add functionality and light mode styles

* fix: ts issues

* fix: update all css color variables to correct names
2024-01-31 16:11:50 +05:30
Vikrant Gupta
3ec56c12dd feat: logs list view changes (#4348)
* feat: logs list view changes

* fix: list view and toolbar styles

* feat: side btns

* feat: added auto refresh handler

* feat: handle popover close for btn click date time

* feat: extract the common log actions btn component

* feat: update the button for log line actions

* fix: event propagation from context button

* feat: use styles from ui-library
2024-01-31 16:11:47 +05:30
Vikrant Gupta
27b4b98ed0 feat: added new toolbar for logs explorer (#4336) 2024-01-31 16:11:15 +05:30
Yunus M
4eb3a4c570 feat: update styles 2024-01-31 16:11:11 +05:30
Yunus M
cb2aec9139 feat: logs explorer - new design 2024-01-31 16:10:44 +05:30
421 changed files with 1554 additions and 20916 deletions

View File

@@ -19,4 +19,4 @@ jobs:
- name: 'Dependency Review'
with:
fail-on-severity: high
uses: actions/dependency-review-action@v3
uses: actions/dependency-review-action@v2

View File

@@ -15,11 +15,6 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup golang
uses: actions/setup-go@v4
with:
go-version: "1.21"
- name: Build query-service image
env:
DEV_BUILD: 1
@@ -70,9 +65,9 @@ jobs:
- name: Kick off a sample-app workload
run: |
# start the locust swarm
kubectl --namespace sample-application run strzal --image=djbingham/curl \
--restart='OnFailure' -i --tty --rm --command -- curl -X POST -F \
'user_count=6' -F 'spawn_rate=2' http://locust-master:8089/swarm
kubectl -n sample-application run strzal --image=djbingham/curl \
--restart='OnFailure' -i --rm --command -- curl -X POST -F \
'locust_count=6' -F 'hatch_rate=2' http://locust-master:8089/swarm
- name: Get short commit SHA, display tunnel URL and IP Address of the worker node
id: get-subdomain

View File

@@ -20,13 +20,13 @@ jobs:
with:
go-version: "1.21"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -64,13 +64,13 @@ jobs:
with:
go-version: "1.21"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -115,11 +115,11 @@ jobs:
run: npm run lint
continue-on-error: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -152,12 +152,6 @@ jobs:
echo 'INTERCOM_APP_ID="${{ secrets.INTERCOM_APP_ID }}"' > frontend/.env
echo 'SEGMENT_ID="${{ secrets.SEGMENT_ID }}"' >> frontend/.env
echo 'CLARITY_PROJECT_ID="${{ secrets.CLARITY_PROJECT_ID }}"' >> frontend/.env
echo 'SENTRY_AUTH_TOKEN="${{ secrets.SENTRY_AUTH_TOKEN }}"' >> frontend/.env
echo 'SENTRY_ORG="${{ secrets.SENTRY_ORG }}"' >> frontend/.env
echo 'SENTRY_PROJECT_ID="${{ secrets.SENTRY_PROJECT_ID }}"' >> frontend/.env
echo 'SENTRY_DSN="${{ secrets.SENTRY_DSN }}"' >> frontend/.env
echo 'TUNNEL_URL="${{ secrets.TUNNEL_URL }}"' >> frontend/.env
echo 'TUNNEL_DOMAIN="${{ secrets.TUNNEL_DOMAIN }}"' >> frontend/.env
- name: Install dependencies
working-directory: frontend
run: yarn install
@@ -170,11 +164,11 @@ jobs:
run: npm run lint
continue-on-error: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

View File

@@ -11,7 +11,7 @@ jobs:
environment: staging
steps:
- name: Executing remote ssh commands using ssh key
uses: appleboy/ssh-action@v1.0.3
uses: appleboy/ssh-action@v0.1.8
env:
GITHUB_BRANCH: develop
GITHUB_SHA: ${{ github.sha }}

View File

@@ -11,7 +11,7 @@ jobs:
if: ${{ github.event.label.name == 'testing-deploy' }}
steps:
- name: Executing remote ssh commands using ssh key
uses: appleboy/ssh-action@v1.0.3
uses: appleboy/ssh-action@v0.1.8
env:
GITHUB_BRANCH: ${{ github.head_ref || github.ref_name }}
GITHUB_SHA: ${{ github.sha }}
@@ -33,11 +33,8 @@ jobs:
git add .
git stash push -m "stashed on $(date --iso-8601=seconds)"
git fetch origin
git checkout develop
git checkout ${GITHUB_BRANCH}
git pull
# This is added to include the scenerio when new commit in PR is force-pushed
git branch -D ${GITHUB_BRANCH}
git checkout --track origin/${GITHUB_BRANCH}
make build-ee-query-service-amd64
make build-frontend-amd64
make run-signoz

View File

@@ -108,7 +108,7 @@ We support [OpenTelemetry](https://opentelemetry.io) as the library which you ca
- Java
- Python
- Node.js
- NodeJS
- Go
- PHP
- .NET

View File

@@ -1,7 +1,7 @@
version: "3.9"
x-clickhouse-defaults: &clickhouse-defaults
image: clickhouse/clickhouse-server:24.1.2-alpine
image: clickhouse/clickhouse-server:23.11.1-alpine
tty: true
deploy:
restart_policy:
@@ -146,7 +146,7 @@ services:
condition: on-failure
query-service:
image: signoz/query-service:0.40.0
image: signoz/query-service:0.37.1
command:
[
"-config=/root/config/prometheus.yml",
@@ -160,7 +160,7 @@ services:
- ../dashboards:/root/config/dashboards
- ./data/signoz/:/var/lib/signoz/
environment:
- ClickHouseUrl=tcp://clickhouse:9000
- ClickHouseUrl=tcp://clickhouse:9000/?database=signoz_traces
- ALERTMANAGER_API_PREFIX=http://alertmanager:9093/api/
- SIGNOZ_LOCAL_DB_PATH=/var/lib/signoz/signoz.db
- DASHBOARDS_PATH=/root/config/dashboards
@@ -186,7 +186,7 @@ services:
<<: *db-depend
frontend:
image: signoz/frontend:0.40.0
image: signoz/frontend:0.37.1
deploy:
restart_policy:
condition: on-failure
@@ -199,7 +199,7 @@ services:
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
otel-collector:
image: signoz/signoz-otel-collector:0.88.14
image: signoz/signoz-otel-collector:0.88.8
command:
[
"--config=/etc/otel-collector-config.yaml",
@@ -237,7 +237,7 @@ services:
- query-service
otel-collector-migrator:
image: signoz/signoz-schema-migrator:0.88.14
image: signoz/signoz-schema-migrator:0.88.8
deploy:
restart_policy:
condition: on-failure

View File

@@ -98,7 +98,6 @@ processors:
latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s ]
dimensions_cache_size: 100000
aggregation_temporality: AGGREGATION_TEMPORALITY_DELTA
enable_exp_histogram: true
dimensions:
- name: service.namespace
default: default
@@ -124,7 +123,15 @@ exporters:
clickhouselogsexporter:
dsn: tcp://clickhouse:9000/
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
timeout: 10s
timeout: 5s
sending_queue:
queue_size: 100
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
extensions:
health_check:
endpoint: 0.0.0.0:13133

View File

@@ -19,7 +19,7 @@ services:
- ZOO_AUTOPURGE_INTERVAL=1
clickhouse:
image: clickhouse/clickhouse-server:24.1.2-alpine
image: clickhouse/clickhouse-server:23.7.3-alpine
container_name: signoz-clickhouse
# ports:
# - "9000:9000"
@@ -66,7 +66,7 @@ services:
- --storage.path=/data
otel-collector-migrator:
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.14}
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.8}
container_name: otel-migrator
command:
- "--dsn=tcp://clickhouse:9000"
@@ -81,7 +81,7 @@ services:
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
otel-collector:
container_name: signoz-otel-collector
image: signoz/signoz-otel-collector:0.88.14
image: signoz/signoz-otel-collector:0.88.8
command:
[
"--config=/etc/otel-collector-config.yaml",

View File

@@ -3,7 +3,7 @@ version: "2.4"
x-clickhouse-defaults: &clickhouse-defaults
restart: on-failure
# addding non LTS version due to this fix https://github.com/ClickHouse/ClickHouse/commit/32caf8716352f45c1b617274c7508c86b7d1afab
image: clickhouse/clickhouse-server:24.1.2-alpine
image: clickhouse/clickhouse-server:23.11.1-alpine
tty: true
depends_on:
- zookeeper-1
@@ -164,7 +164,7 @@ services:
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
query-service:
image: signoz/query-service:${DOCKER_TAG:-0.40.0}
image: signoz/query-service:${DOCKER_TAG:-0.37.1}
container_name: signoz-query-service
command:
[
@@ -179,7 +179,7 @@ services:
- ../dashboards:/root/config/dashboards
- ./data/signoz/:/var/lib/signoz/
environment:
- ClickHouseUrl=tcp://clickhouse:9000
- ClickHouseUrl=tcp://clickhouse:9000/?database=signoz_traces
- ALERTMANAGER_API_PREFIX=http://alertmanager:9093/api/
- SIGNOZ_LOCAL_DB_PATH=/var/lib/signoz/signoz.db
- DASHBOARDS_PATH=/root/config/dashboards
@@ -203,7 +203,7 @@ services:
<<: *db-depend
frontend:
image: signoz/frontend:${DOCKER_TAG:-0.40.0}
image: signoz/frontend:${DOCKER_TAG:-0.37.1}
container_name: signoz-frontend
restart: on-failure
depends_on:
@@ -215,7 +215,7 @@ services:
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
otel-collector-migrator:
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.14}
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.8}
container_name: otel-migrator
command:
- "--dsn=tcp://clickhouse:9000"
@@ -229,7 +229,7 @@ services:
otel-collector:
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.14}
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.8}
container_name: signoz-otel-collector
command:
[

View File

@@ -101,7 +101,6 @@ processors:
latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s ]
dimensions_cache_size: 100000
aggregation_temporality: AGGREGATION_TEMPORALITY_DELTA
enable_exp_histogram: true
dimensions:
- name: service.namespace
default: default
@@ -136,7 +135,14 @@ exporters:
clickhouselogsexporter:
dsn: tcp://clickhouse:9000/
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
timeout: 10s
timeout: 5s
sending_queue:
queue_size: 100
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
service:
telemetry:

View File

@@ -1,5 +1,5 @@
# use a minimal alpine image
FROM alpine:3.18.6
FROM alpine:3.18.5
# Add Maintainer Info
LABEL maintainer="signoz"

View File

@@ -152,10 +152,9 @@ func (ah *APIHandler) RegisterRoutes(router *mux.Router, am *baseapp.AuthMiddlew
router.HandleFunc("/api/v2/metrics/query_range", am.ViewAccess(ah.queryRangeMetricsV2)).Methods(http.MethodPost)
// PAT APIs
router.HandleFunc("/api/v1/pats", am.AdminAccess(ah.createPAT)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/pats", am.AdminAccess(ah.getPATs)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/pats/{id}", am.AdminAccess(ah.updatePAT)).Methods(http.MethodPut)
router.HandleFunc("/api/v1/pats/{id}", am.AdminAccess(ah.revokePAT)).Methods(http.MethodDelete)
router.HandleFunc("/api/v1/pat", am.AdminAccess(ah.createPAT)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/pat", am.AdminAccess(ah.getPATs)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/pat/{id}", am.AdminAccess(ah.deletePAT)).Methods(http.MethodDelete)
router.HandleFunc("/api/v1/checkout", am.AdminAccess(ah.checkout)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/billing", am.AdminAccess(ah.getBilling)).Methods(http.MethodGet)

View File

@@ -12,7 +12,6 @@ import (
"github.com/gorilla/mux"
"go.signoz.io/signoz/ee/query-service/model"
"go.signoz.io/signoz/pkg/query-service/auth"
baseconstants "go.signoz.io/signoz/pkg/query-service/constants"
basemodel "go.signoz.io/signoz/pkg/query-service/model"
"go.uber.org/zap"
)
@@ -29,74 +28,11 @@ func generatePATToken() string {
func (ah *APIHandler) createPAT(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
req := model.CreatePATRequestBody{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
RespondError(w, model.BadRequest(err), nil)
return
}
user, err := auth.GetUserFromRequest(r)
if err != nil {
RespondError(w, &model.ApiError{
Typ: model.ErrorUnauthorized,
Err: err,
}, nil)
return
}
pat := model.PAT{
Name: req.Name,
Role: req.Role,
ExpiresAt: req.ExpiresInDays,
}
err = validatePATRequest(pat)
if err != nil {
RespondError(w, model.BadRequest(err), nil)
return
}
// All the PATs are associated with the user creating the PAT.
pat.UserID = user.Id
pat.CreatedAt = time.Now().Unix()
pat.UpdatedAt = time.Now().Unix()
pat.LastUsed = 0
pat.Token = generatePATToken()
if pat.ExpiresAt != 0 {
// convert expiresAt to unix timestamp from days
pat.ExpiresAt = time.Now().Unix() + (pat.ExpiresAt * 24 * 60 * 60)
}
zap.S().Debugf("Got Create PAT request: %+v", pat)
var apierr basemodel.BaseApiError
if pat, apierr = ah.AppDao().CreatePAT(ctx, pat); apierr != nil {
RespondError(w, apierr, nil)
return
}
ah.Respond(w, &pat)
}
func validatePATRequest(req model.PAT) error {
if req.Role == "" || (req.Role != baseconstants.ViewerGroup && req.Role != baseconstants.EditorGroup && req.Role != baseconstants.AdminGroup) {
return fmt.Errorf("valid role is required")
}
if req.ExpiresAt < 0 {
return fmt.Errorf("valid expiresAt is required")
}
if req.Name == "" {
return fmt.Errorf("valid name is required")
}
return nil
}
func (ah *APIHandler) updatePAT(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
req := model.PAT{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
RespondError(w, model.BadRequest(err), nil)
return
}
user, err := auth.GetUserFromRequest(r)
if err != nil {
RespondError(w, &model.ApiError{
@@ -106,23 +42,29 @@ func (ah *APIHandler) updatePAT(w http.ResponseWriter, r *http.Request) {
return
}
err = validatePATRequest(req)
if err != nil {
RespondError(w, model.BadRequest(err), nil)
return
// All the PATs are associated with the user creating the PAT. Hence, the permissions
// associated with the PAT is also equivalent to that of the user.
req.UserID = user.Id
req.CreatedAt = time.Now().Unix()
req.Token = generatePATToken()
// default expiry is 30 days
if req.ExpiresAt == 0 {
req.ExpiresAt = time.Now().AddDate(0, 0, 30).Unix()
}
// max expiry is 1 year
if req.ExpiresAt > time.Now().AddDate(1, 0, 0).Unix() {
req.ExpiresAt = time.Now().AddDate(1, 0, 0).Unix()
}
req.UpdatedByUserID = user.Id
id := mux.Vars(r)["id"]
req.UpdatedAt = time.Now().Unix()
zap.S().Debugf("Got Update PAT request: %+v", req)
zap.S().Debugf("Got PAT request: %+v", req)
var apierr basemodel.BaseApiError
if apierr = ah.AppDao().UpdatePAT(ctx, req, id); apierr != nil {
if req, apierr = ah.AppDao().CreatePAT(ctx, req); apierr != nil {
RespondError(w, apierr, nil)
return
}
ah.Respond(w, map[string]string{"data": "pat updated successfully"})
ah.Respond(w, &req)
}
func (ah *APIHandler) getPATs(w http.ResponseWriter, r *http.Request) {
@@ -136,7 +78,7 @@ func (ah *APIHandler) getPATs(w http.ResponseWriter, r *http.Request) {
return
}
zap.S().Infof("Get PATs for user: %+v", user.Id)
pats, apierr := ah.AppDao().ListPATs(ctx)
pats, apierr := ah.AppDao().ListPATs(ctx, user.Id)
if apierr != nil {
RespondError(w, apierr, nil)
return
@@ -144,7 +86,7 @@ func (ah *APIHandler) getPATs(w http.ResponseWriter, r *http.Request) {
ah.Respond(w, pats)
}
func (ah *APIHandler) revokePAT(w http.ResponseWriter, r *http.Request) {
func (ah *APIHandler) deletePAT(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
id := mux.Vars(r)["id"]
user, err := auth.GetUserFromRequest(r)
@@ -155,11 +97,22 @@ func (ah *APIHandler) revokePAT(w http.ResponseWriter, r *http.Request) {
}, nil)
return
}
zap.S().Debugf("Revoke PAT with id: %+v", id)
if apierr := ah.AppDao().RevokePAT(ctx, id, user.Id); apierr != nil {
pat, apierr := ah.AppDao().GetPATByID(ctx, id)
if apierr != nil {
RespondError(w, apierr, nil)
return
}
ah.Respond(w, map[string]string{"data": "pat revoked successfully"})
if pat.UserID != user.Id {
RespondError(w, &model.ApiError{
Typ: model.ErrorUnauthorized,
Err: fmt.Errorf("unauthorized PAT delete request"),
}, nil)
return
}
zap.S().Debugf("Delete PAT with id: %+v", id)
if apierr := ah.AppDao().DeletePAT(ctx, id); apierr != nil {
RespondError(w, apierr, nil)
return
}
ah.Respond(w, map[string]string{"data": "pat deleted successfully"})
}

View File

@@ -20,11 +20,10 @@ import (
"github.com/soheilhy/cmux"
"go.signoz.io/signoz/ee/query-service/app/api"
"go.signoz.io/signoz/ee/query-service/app/db"
"go.signoz.io/signoz/ee/query-service/auth"
"go.signoz.io/signoz/ee/query-service/constants"
"go.signoz.io/signoz/ee/query-service/dao"
"go.signoz.io/signoz/ee/query-service/interfaces"
baseauth "go.signoz.io/signoz/pkg/query-service/auth"
"go.signoz.io/signoz/pkg/query-service/auth"
baseInterface "go.signoz.io/signoz/pkg/query-service/interfaces"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
@@ -38,6 +37,7 @@ import (
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
"go.signoz.io/signoz/pkg/query-service/app/opamp"
opAmpModel "go.signoz.io/signoz/pkg/query-service/app/opamp/model"
baseauth "go.signoz.io/signoz/pkg/query-service/auth"
"go.signoz.io/signoz/pkg/query-service/cache"
baseconst "go.signoz.io/signoz/pkg/query-service/constants"
"go.signoz.io/signoz/pkg/query-service/healthcheck"
@@ -304,12 +304,25 @@ func (s *Server) createPublicServer(apiHandler *api.APIHandler) (*http.Server, e
r := mux.NewRouter()
// add auth middleware
getUserFromRequest := func(r *http.Request) (*basemodel.UserPayload, error) {
return auth.GetUserFromRequest(r, apiHandler)
patToken := r.Header.Get("SIGNOZ-API-KEY")
if len(patToken) > 0 {
zap.S().Debugf("Received a non-zero length PAT token")
ctx := context.Background()
dao := apiHandler.AppDao()
user, err := dao.GetUserByPAT(ctx, patToken)
if err == nil && user != nil {
zap.S().Debugf("Found valid PAT user: %+v", user)
return user, nil
}
if err != nil {
zap.S().Debugf("Error while getting user for PAT: %+v", err)
}
}
return baseauth.GetUserFromRequest(r)
}
am := baseapp.NewAuthMiddleware(getUserFromRequest)
r.Use(setTimeoutMiddleware)
r.Use(s.analyticsMiddleware)
r.Use(loggingMiddleware)
@@ -426,7 +439,7 @@ func extractQueryRangeV3Data(path string, r *http.Request) (map[string]interface
telemetry.GetInstance().AddActiveLogsUser()
}
data["dataSources"] = dataSources
userEmail, err := baseauth.GetEmailFromJwt(r.Context())
userEmail, err := auth.GetEmailFromJwt(r.Context())
if err == nil {
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_QUERY_RANGE_V3, data, userEmail, true)
}
@@ -450,7 +463,7 @@ func getActiveLogs(path string, r *http.Request) {
func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := baseauth.AttachJwtToContext(r.Context(), r)
ctx := auth.AttachJwtToContext(r.Context(), r)
r = r.WithContext(ctx)
route := mux.CurrentRoute(r)
path, _ := route.GetPathTemplate()
@@ -469,7 +482,7 @@ func (s *Server) analyticsMiddleware(next http.Handler) http.Handler {
}
if _, ok := telemetry.EnabledPaths()[path]; ok {
userEmail, err := baseauth.GetEmailFromJwt(r.Context())
userEmail, err := auth.GetEmailFromJwt(r.Context())
if err == nil {
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_PATH, data, userEmail)
}

View File

@@ -1,56 +0,0 @@
package auth
import (
"context"
"fmt"
"net/http"
"time"
"go.signoz.io/signoz/ee/query-service/app/api"
baseauth "go.signoz.io/signoz/pkg/query-service/auth"
basemodel "go.signoz.io/signoz/pkg/query-service/model"
"go.signoz.io/signoz/pkg/query-service/telemetry"
"go.uber.org/zap"
)
func GetUserFromRequest(r *http.Request, apiHandler *api.APIHandler) (*basemodel.UserPayload, error) {
patToken := r.Header.Get("SIGNOZ-API-KEY")
if len(patToken) > 0 {
zap.S().Debugf("Received a non-zero length PAT token")
ctx := context.Background()
dao := apiHandler.AppDao()
pat, err := dao.GetPAT(ctx, patToken)
if err == nil && pat != nil {
zap.S().Debugf("Found valid PAT: %+v", pat)
if pat.ExpiresAt < time.Now().Unix() && pat.ExpiresAt != 0 {
zap.S().Debugf("PAT has expired: %+v", pat)
return nil, fmt.Errorf("PAT has expired")
}
group, apiErr := dao.GetGroupByName(ctx, pat.Role)
if apiErr != nil {
zap.S().Debugf("Error while getting group for PAT: %+v", apiErr)
return nil, apiErr
}
user, err := dao.GetUser(ctx, pat.UserID)
if err != nil {
zap.S().Debugf("Error while getting user for PAT: %+v", err)
return nil, err
}
telemetry.GetInstance().SetPatTokenUser()
dao.UpdatePATLastUsed(ctx, patToken, time.Now().Unix())
user.User.GroupId = group.Id
user.User.Id = pat.Id
return &basemodel.UserPayload{
User: user.User,
Role: pat.Role,
}, nil
}
if err != nil {
zap.S().Debugf("Error while getting user for PAT: %+v", err)
return nil, err
}
}
return baseauth.GetUserFromRequest(r)
}

View File

@@ -34,11 +34,9 @@ type ModelDao interface {
GetDomainByEmail(ctx context.Context, email string) (*model.OrgDomain, basemodel.BaseApiError)
CreatePAT(ctx context.Context, p model.PAT) (model.PAT, basemodel.BaseApiError)
UpdatePAT(ctx context.Context, p model.PAT, id string) (basemodel.BaseApiError)
GetPAT(ctx context.Context, pat string) (*model.PAT, basemodel.BaseApiError)
UpdatePATLastUsed(ctx context.Context, pat string, lastUsed int64) basemodel.BaseApiError
GetPATByID(ctx context.Context, id string) (*model.PAT, basemodel.BaseApiError)
GetUserByPAT(ctx context.Context, token string) (*basemodel.UserPayload, basemodel.BaseApiError)
ListPATs(ctx context.Context) ([]model.PAT, basemodel.BaseApiError)
RevokePAT(ctx context.Context, id string, userID string) basemodel.BaseApiError
ListPATs(ctx context.Context, userID string) ([]model.PAT, basemodel.BaseApiError)
DeletePAT(ctx context.Context, id string) basemodel.BaseApiError
}

View File

@@ -7,7 +7,6 @@ import (
basedao "go.signoz.io/signoz/pkg/query-service/dao"
basedsql "go.signoz.io/signoz/pkg/query-service/dao/sqlite"
baseint "go.signoz.io/signoz/pkg/query-service/interfaces"
"go.uber.org/zap"
)
type modelDao struct {
@@ -29,41 +28,6 @@ func (m *modelDao) checkFeature(key string) error {
return m.flags.CheckFeature(key)
}
func columnExists(db *sqlx.DB, tableName, columnName string) bool {
query := fmt.Sprintf("PRAGMA table_info(%s);", tableName)
rows, err := db.Query(query)
if err != nil {
zap.L().Error("Failed to query table info", zap.Error(err))
return false
}
defer rows.Close()
var (
cid int
name string
ctype string
notnull int
dflt_value *string
pk int
)
for rows.Next() {
err := rows.Scan(&cid, &name, &ctype, &notnull, &dflt_value, &pk)
if err != nil {
zap.L().Error("Failed to scan table info", zap.Error(err))
return false
}
if name == columnName {
return true
}
}
err = rows.Err()
if err != nil {
zap.L().Error("Failed to scan table info", zap.Error(err))
return false
}
return false
}
// InitDB creates and extends base model DB repository
func InitDB(dataSourceName string) (*modelDao, error) {
dao, err := basedsql.InitDB(dataSourceName)
@@ -87,16 +51,11 @@ func InitDB(dataSourceName string) (*modelDao, error) {
);
CREATE TABLE IF NOT EXISTS personal_access_tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
role TEXT NOT NULL,
user_id TEXT NOT NULL,
token TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
created_at INTEGER NOT NULL,
expires_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL,
last_used INTEGER NOT NULL,
revoked BOOLEAN NOT NULL,
updated_by_user_id TEXT NOT NULL,
FOREIGN KEY(user_id) REFERENCES users(id)
);
`
@@ -106,36 +65,6 @@ func InitDB(dataSourceName string) (*modelDao, error) {
return nil, fmt.Errorf("error in creating tables: %v", err.Error())
}
if !columnExists(m.DB(), "personal_access_tokens", "role") {
_, err = m.DB().Exec("ALTER TABLE personal_access_tokens ADD COLUMN role TEXT NOT NULL DEFAULT 'ADMIN';")
if err != nil {
return nil, fmt.Errorf("error in adding column: %v", err.Error())
}
}
if !columnExists(m.DB(), "personal_access_tokens", "updated_at") {
_, err = m.DB().Exec("ALTER TABLE personal_access_tokens ADD COLUMN updated_at INTEGER NOT NULL DEFAULT 0;")
if err != nil {
return nil, fmt.Errorf("error in adding column: %v", err.Error())
}
}
if !columnExists(m.DB(), "personal_access_tokens", "last_used") {
_, err = m.DB().Exec("ALTER TABLE personal_access_tokens ADD COLUMN last_used INTEGER NOT NULL DEFAULT 0;")
if err != nil {
return nil, fmt.Errorf("error in adding column: %v", err.Error())
}
}
if !columnExists(m.DB(), "personal_access_tokens", "revoked") {
_, err = m.DB().Exec("ALTER TABLE personal_access_tokens ADD COLUMN revoked BOOLEAN NOT NULL DEFAULT FALSE;")
if err != nil {
return nil, fmt.Errorf("error in adding column: %v", err.Error())
}
}
if !columnExists(m.DB(), "personal_access_tokens", "updated_by_user_id") {
_, err = m.DB().Exec("ALTER TABLE personal_access_tokens ADD COLUMN updated_by_user_id TEXT NOT NULL DEFAULT '';")
if err != nil {
return nil, fmt.Errorf("error in adding column: %v", err.Error())
}
}
return m, nil
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"strconv"
"time"
"go.signoz.io/signoz/ee/query-service/model"
basemodel "go.signoz.io/signoz/pkg/query-service/model"
@@ -13,18 +12,12 @@ import (
func (m *modelDao) CreatePAT(ctx context.Context, p model.PAT) (model.PAT, basemodel.BaseApiError) {
result, err := m.DB().ExecContext(ctx,
"INSERT INTO personal_access_tokens (user_id, token, role, name, created_at, expires_at, updated_at, updated_by_user_id, last_used, revoked) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
"INSERT INTO personal_access_tokens (user_id, token, name, created_at, expires_at) VALUES ($1, $2, $3, $4, $5)",
p.UserID,
p.Token,
p.Role,
p.Name,
p.CreatedAt,
p.ExpiresAt,
p.UpdatedAt,
p.UpdatedByUserID,
p.LastUsed,
p.Revoked,
)
p.ExpiresAt)
if err != nil {
zap.S().Errorf("Failed to insert PAT in db, err: %v", zap.Error(err))
return model.PAT{}, model.InternalError(fmt.Errorf("PAT insertion failed"))
@@ -35,102 +28,24 @@ func (m *modelDao) CreatePAT(ctx context.Context, p model.PAT) (model.PAT, basem
return model.PAT{}, model.InternalError(fmt.Errorf("PAT insertion failed"))
}
p.Id = strconv.Itoa(int(id))
createdByUser, _ := m.GetUser(ctx, p.UserID)
if createdByUser == nil {
p.CreatedByUser = model.User{
NotFound: true,
}
} else {
p.CreatedByUser = model.User{
Id: createdByUser.Id,
Name: createdByUser.Name,
Email: createdByUser.Email,
CreatedAt: createdByUser.CreatedAt,
ProfilePictureURL: createdByUser.ProfilePictureURL,
NotFound: false,
}
}
return p, nil
}
func (m *modelDao) UpdatePAT(ctx context.Context, p model.PAT, id string) basemodel.BaseApiError {
_, err := m.DB().ExecContext(ctx,
"UPDATE personal_access_tokens SET role=$1, name=$2, updated_at=$3, updated_by_user_id=$4 WHERE id=$5 and revoked=false;",
p.Role,
p.Name,
p.UpdatedAt,
p.UpdatedByUserID,
id)
if err != nil {
zap.S().Errorf("Failed to update PAT in db, err: %v", zap.Error(err))
return model.InternalError(fmt.Errorf("PAT update failed"))
}
return nil
}
func (m *modelDao) UpdatePATLastUsed(ctx context.Context, token string, lastUsed int64) basemodel.BaseApiError {
_, err := m.DB().ExecContext(ctx,
"UPDATE personal_access_tokens SET last_used=$1 WHERE token=$2 and revoked=false;",
lastUsed,
token)
if err != nil {
zap.S().Errorf("Failed to update PAT last used in db, err: %v", zap.Error(err))
return model.InternalError(fmt.Errorf("PAT last used update failed"))
}
return nil
}
func (m *modelDao) ListPATs(ctx context.Context) ([]model.PAT, basemodel.BaseApiError) {
func (m *modelDao) ListPATs(ctx context.Context, userID string) ([]model.PAT, basemodel.BaseApiError) {
pats := []model.PAT{}
if err := m.DB().Select(&pats, "SELECT * FROM personal_access_tokens WHERE revoked=false ORDER by updated_at DESC;"); err != nil {
zap.S().Errorf("Failed to fetch PATs err: %v", zap.Error(err))
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE user_id=?;`, userID); err != nil {
zap.S().Errorf("Failed to fetch PATs for user: %s, err: %v", userID, zap.Error(err))
return nil, model.InternalError(fmt.Errorf("failed to fetch PATs"))
}
for i := range pats {
createdByUser, _ := m.GetUser(ctx, pats[i].UserID)
if createdByUser == nil {
pats[i].CreatedByUser = model.User{
NotFound: true,
}
} else {
pats[i].CreatedByUser = model.User{
Id: createdByUser.Id,
Name: createdByUser.Name,
Email: createdByUser.Email,
CreatedAt: createdByUser.CreatedAt,
ProfilePictureURL: createdByUser.ProfilePictureURL,
NotFound: false,
}
}
updatedByUser, _ := m.GetUser(ctx, pats[i].UpdatedByUserID)
if updatedByUser == nil {
pats[i].UpdatedByUser = model.User{
NotFound: true,
}
} else {
pats[i].UpdatedByUser = model.User{
Id: updatedByUser.Id,
Name: updatedByUser.Name,
Email: updatedByUser.Email,
CreatedAt: updatedByUser.CreatedAt,
ProfilePictureURL: updatedByUser.ProfilePictureURL,
NotFound: false,
}
}
}
return pats, nil
}
func (m *modelDao) RevokePAT(ctx context.Context, id string, userID string) basemodel.BaseApiError {
updatedAt := time.Now().Unix()
_, err := m.DB().ExecContext(ctx,
"UPDATE personal_access_tokens SET revoked=true, updated_by_user_id = $1, updated_at=$2 WHERE id=$3",
userID, updatedAt, id)
func (m *modelDao) DeletePAT(ctx context.Context, id string) basemodel.BaseApiError {
_, err := m.DB().ExecContext(ctx, `DELETE from personal_access_tokens where id=?;`, id)
if err != nil {
zap.S().Errorf("Failed to revoke PAT in db, err: %v", zap.Error(err))
return model.InternalError(fmt.Errorf("PAT revoke failed"))
zap.S().Errorf("Failed to delete PAT, err: %v", zap.Error(err))
return model.InternalError(fmt.Errorf("failed to delete PAT"))
}
return nil
}
@@ -138,7 +53,7 @@ func (m *modelDao) RevokePAT(ctx context.Context, id string, userID string) base
func (m *modelDao) GetPAT(ctx context.Context, token string) (*model.PAT, basemodel.BaseApiError) {
pats := []model.PAT{}
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE token=? and revoked=false;`, token); err != nil {
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE token=?;`, token); err != nil {
return nil, model.InternalError(fmt.Errorf("failed to fetch PAT"))
}
@@ -155,7 +70,7 @@ func (m *modelDao) GetPAT(ctx context.Context, token string) (*model.PAT, basemo
func (m *modelDao) GetPATByID(ctx context.Context, id string) (*model.PAT, basemodel.BaseApiError) {
pats := []model.PAT{}
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE id=? and revoked=false;`, id); err != nil {
if err := m.DB().Select(&pats, `SELECT * FROM personal_access_tokens WHERE id=?;`, id); err != nil {
return nil, model.InternalError(fmt.Errorf("failed to fetch PAT"))
}
@@ -169,7 +84,6 @@ func (m *modelDao) GetPATByID(ctx context.Context, id string) (*model.PAT, basem
return &pats[0], nil
}
// deprecated
func (m *modelDao) GetUserByPAT(ctx context.Context, token string) (*basemodel.UserPayload, basemodel.BaseApiError) {
users := []basemodel.UserPayload{}

View File

@@ -1,32 +1,10 @@
package model
type User struct {
Id string `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
CreatedAt int64 `json:"createdAt" db:"created_at"`
ProfilePictureURL string `json:"profilePictureURL" db:"profile_picture_url"`
NotFound bool `json:"notFound"`
}
type CreatePATRequestBody struct {
Name string `json:"name"`
Role string `json:"role"`
ExpiresInDays int64 `json:"expiresInDays"`
}
type PAT struct {
Id string `json:"id" db:"id"`
UserID string `json:"userId" db:"user_id"`
CreatedByUser User `json:"createdByUser"`
UpdatedByUser User `json:"updatedByUser"`
Token string `json:"token" db:"token"`
Role string `json:"role" db:"role"`
Name string `json:"name" db:"name"`
CreatedAt int64 `json:"createdAt" db:"created_at"`
ExpiresAt int64 `json:"expiresAt" db:"expires_at"`
UpdatedAt int64 `json:"updatedAt" db:"updated_at"`
LastUsed int64 `json:"lastUsed" db:"last_used"`
Revoked bool `json:"revoked" db:"revoked"`
UpdatedByUserID string `json:"updatedByUserId" db:"updated_by_user_id"`
Id string `json:"id" db:"id"`
UserID string `json:"userId" db:"user_id"`
Token string `json:"token" db:"token"`
Name string `json:"name" db:"name"`
CreatedAt int64 `json:"createdAt" db:"created_at"`
ExpiresAt int64 `json:"expiresAt" db:"expires_at"`
}

View File

@@ -139,13 +139,17 @@ func (lm *Manager) UploadUsage() {
zap.S().Info("uploading usage data")
// Try to get the org name
orgName := ""
orgNames, orgError := lm.modelDao.GetOrgs(ctx)
if orgError != nil {
zap.S().Errorf("failed to get org data: %v", zap.Error(orgError))
}
if len(orgNames) == 1 {
orgName = orgNames[0].Name
orgNames, err := lm.modelDao.GetOrgs(ctx)
if err != nil {
zap.S().Errorf("failed to get org data: %v", zap.Error(err))
} else {
if len(orgNames) != 1 {
zap.S().Errorf("expected one org but got %d orgs", len(orgNames))
} else {
orgName = orgNames[0].Name
}
}
usagesPayload := []model.Usage{}

View File

@@ -20,11 +20,9 @@ const config: Config.InitialOptions = {
transform: {
'^.+\\.(ts|tsx)?$': 'ts-jest',
'^.+\\.(js|jsx)$': 'babel-jest',
'^.+\\.(css|scss|sass|less)$': 'jest-preview/transforms/css',
'^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': 'jest-preview/transforms/file',
},
transformIgnorePatterns: [
'node_modules/(?!(lodash-es|react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend|axios|@signozhq/design-tokens|d3-interpolate|d3-color)/)',
'node_modules/(?!(lodash-es|react-dnd|core-dnd|@react-dnd|dnd-core|react-dnd-html5-backend|axios|@signozhq/design-tokens)/)',
],
setupFilesAfterEnv: ['<rootDir>jest.setup.ts'],
testPathIgnorePatterns: ['/node_modules/', '/public/'],

View File

@@ -7,7 +7,6 @@
*/
import '@testing-library/jest-dom';
import 'jest-styled-components';
import './src/styles.scss';
import { server } from './src/mocks-server/server';
// Establish API mocking before all tests.

View File

@@ -13,8 +13,6 @@
"jest": "jest",
"jest:coverage": "jest --coverage",
"jest:watch": "jest --watch",
"jest-preview": "jest-preview",
"test:debug": "npm-run-all -p test jest-preview",
"postinstall": "is-ci || yarn husky:configure",
"playwright": "npm run i18n:generate-hash && NODE_ENV=testing playwright test --config=./playwright.config.ts",
"playwright:local:debug": "PWDEBUG=console yarn playwright --headed --browser=chromium",
@@ -40,8 +38,6 @@
"@monaco-editor/react": "^4.3.1",
"@radix-ui/react-tabs": "1.0.4",
"@radix-ui/react-tooltip": "1.0.7",
"@sentry/react": "7.102.1",
"@sentry/webpack-plugin": "2.14.2",
"@signozhq/design-tokens": "0.0.8",
"@uiw/react-md-editor": "3.23.5",
"@xstate/react": "^3.0.0",
@@ -73,7 +69,6 @@
"fontfaceobserver": "2.3.0",
"history": "4.10.1",
"html-webpack-plugin": "5.5.0",
"http-proxy-middleware": "2.0.6",
"i18next": "^21.6.12",
"i18next-browser-languagedetector": "^6.1.3",
"i18next-http-backend": "^1.3.2",
@@ -87,7 +82,6 @@
"papaparse": "5.4.1",
"react": "18.2.0",
"react-addons-update": "15.6.3",
"react-beautiful-dnd": "13.1.1",
"react-dnd": "16.0.1",
"react-dnd-html5-backend": "16.0.1",
"react-dom": "18.2.0",
@@ -161,7 +155,6 @@
"@types/papaparse": "5.3.7",
"@types/react": "18.0.26",
"@types/react-addons-update": "0.14.21",
"@types/react-beautiful-dnd": "13.1.8",
"@types/react-dom": "18.0.10",
"@types/react-grid-layout": "^1.1.2",
"@types/react-helmet-async": "1.0.3",
@@ -199,7 +192,6 @@
"husky": "^7.0.4",
"is-ci": "^3.0.1",
"jest-playwright-preset": "^1.7.2",
"jest-preview": "0.3.1",
"jest-styled-components": "^7.0.8",
"lint-staged": "^12.5.0",
"msw": "1.3.2",
@@ -216,13 +208,11 @@
"ts-node": "^10.2.1",
"typescript-plugin-css-modules": "5.0.1",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cli": "^4.9.2",
"npm-run-all": "latest"
"webpack-cli": "^4.9.2"
},
"lint-staged": {
"*.(js|jsx|ts|tsx)": [
"eslint --fix",
"sh scripts/typecheck-staged.sh"
"eslint --fix"
]
},
"resolutions": {

View File

@@ -1 +0,0 @@
<svg width="24" height="24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c1 2.538 2.5 2.962 3.5 3.808.942.78 1.481 1.845 1.5 2.961 0 1.122-.527 2.198-1.464 2.992C14.598 12.554 13.326 13 12 13s-2.598-.446-3.536-1.24C7.527 10.968 7 9.892 7 8.77c0-.255 0-.508.1-.762.085.25.236.48.443.673.207.193.463.342.75.437a2.334 2.334 0 001.767-.128c.263-.135.485-.32.65-.539.166-.22.269-.468.301-.727a1.452 1.452 0 00-.11-.765 1.699 1.699 0 00-.501-.644C8 4.115 11 2 12 2zM17 16l-5 6-5-6h10z" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>

Before

Width:  |  Height:  |  Size: 581 B

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 64 (93537) - https://sketch.com -->
<title>Icon-Architecture/64/Arch_Amazon-EC2_64</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="0%" y1="100%" x2="100%" y2="0%" id="linearGradient-1">
<stop stop-color="#C8511B" offset="0%"></stop>
<stop stop-color="#FF9900" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Icon-Architecture/64/Arch_Amazon-EC2_64" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icon-Architecture-BG/64/Compute" fill="url(#linearGradient-1)">
<rect id="Rectangle" x="0" y="0" width="80" height="80"></rect>
</g>
<path d="M27,53 L52,53 L52,28 L27,28 L27,53 Z M54,28 L58,28 L58,30 L54,30 L54,34 L58,34 L58,36 L54,36 L54,39 L58,39 L58,41 L54,41 L54,45 L58,45 L58,47 L54,47 L54,51 L58,51 L58,53 L54,53 L54,53.136 C54,54.164 53.164,55 52.136,55 L52,55 L52,59 L50,59 L50,55 L46,55 L46,59 L44,59 L44,55 L41,55 L41,59 L39,59 L39,55 L35,55 L35,59 L33,59 L33,55 L29,55 L29,59 L27,59 L27,55 L26.864,55 C25.836,55 25,54.164 25,53.136 L25,53 L22,53 L22,51 L25,51 L25,47 L22,47 L22,45 L25,45 L25,41 L22,41 L22,39 L25,39 L25,36 L22,36 L22,34 L25,34 L25,30 L22,30 L22,28 L25,28 L25,27.864 C25,26.836 25.836,26 26.864,26 L27,26 L27,22 L29,22 L29,26 L33,26 L33,22 L35,22 L35,26 L39,26 L39,22 L41,22 L41,26 L44,26 L44,22 L46,22 L46,26 L50,26 L50,22 L52,22 L52,26 L52.136,26 C53.164,26 54,26.836 54,27.864 L54,28 Z M41,65.876 C41,65.944 40.944,66 40.876,66 L14.124,66 C14.056,66 14,65.944 14,65.876 L14,39.124 C14,39.056 14.056,39 14.124,39 L20,39 L20,37 L14.124,37 C12.953,37 12,37.953 12,39.124 L12,65.876 C12,67.047 12.953,68 14.124,68 L40.876,68 C42.047,68 43,67.047 43,65.876 L43,61 L41,61 L41,65.876 Z M68,14.124 L68,40.876 C68,42.047 67.047,43 65.876,43 L60,43 L60,41 L65.876,41 C65.944,41 66,40.944 66,40.876 L66,14.124 C66,14.056 65.944,14 65.876,14 L39.124,14 C39.056,14 39,14.056 39,14.124 L39,20 L37,20 L37,14.124 C37,12.953 37.953,12 39.124,12 L65.876,12 C67.047,12 68,12.953 68,14.124 L68,14.124 Z" id="Amazon-EC2_Icon_64_Squid" fill="#FFFFFF"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="80px" height="80px" viewBox="0 0 80 80" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 64 (93537) - https://sketch.com -->
<title>Icon-Architecture/64/Arch_Amazon-Elastic-Container-Service_64</title>
<desc>Created with Sketch.</desc>
<defs>
<linearGradient x1="0%" y1="100%" x2="100%" y2="0%" id="linearGradient-1">
<stop stop-color="#C8511B" offset="0%"></stop>
<stop stop-color="#FF9900" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Icon-Architecture/64/Arch_Amazon-Elastic-Container-Service_64" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icon-Architecture-BG/64/Containers" fill="url(#linearGradient-1)">
<rect id="Rectangle" x="0" y="0" width="80" height="80"></rect>
</g>
<path d="M64,48.2340095 L56,43.4330117 L56,32.0000169 C56,31.6440171 55.812,31.3150172 55.504,31.1360173 L44,24.4260204 L44,14.7520248 L64,26.5710194 L64,48.2340095 Z M65.509,25.13902 L43.509,12.139026 C43.199,11.9560261 42.818,11.9540261 42.504,12.131026 C42.193,12.3090259 42,12.6410257 42,13.0000256 L42,25.0000201 C42,25.3550199 42.189,25.6840198 42.496,25.8640197 L54,32.5740166 L54,44.0000114 C54,44.3510113 54.185,44.6770111 54.486,44.857011 L64.486,50.8570083 C64.644,50.9520082 64.822,51 65,51 C65.17,51 65.34,50.9570082 65.493,50.8700083 C65.807,50.6930084 66,50.3600085 66,50 L66,26.0000196 C66,25.6460198 65.814,25.31902 65.509,25.13902 L65.509,25.13902 Z M40.445,66.863001 L17,54.3990067 L17,26.5710194 L37,14.7520248 L37,24.4510204 L26.463,31.1560173 C26.175,31.3400172 26,31.6580171 26,32.0000169 L26,49.0000091 C26,49.373009 26.208,49.7150088 26.538,49.8870087 L39.991,56.8870055 C40.28,57.0370055 40.624,57.0380055 40.912,56.8880055 L53.964,50.1440086 L61.996,54.9640064 L40.445,66.863001 Z M64.515,54.1420068 L54.515,48.1420095 C54.217,47.9640096 53.849,47.9520096 53.541,48.1120095 L40.455,54.8730065 L28,48.3930094 L28,32.5490167 L38.537,25.8440197 C38.825,25.6600198 39,25.3420199 39,25.0000201 L39,13.0000256 C39,12.6410257 38.808,12.3090259 38.496,12.131026 C38.184,11.9540261 37.802,11.9560261 37.491,12.139026 L15.491,25.13902 C15.187,25.31902 15,25.6460198 15,26.0000196 L15,55 C15,55.3690062 15.204,55.7090061 15.53,55.883006 L39.984,68.8830001 C40.131,68.961 40.292,69 40.453,69 C40.62,69 40.786,68.958 40.937,68.8750001 L64.484,55.875006 C64.797,55.7020061 64.993,55.3750062 65.0001416,55.0180064 C65.006,54.6600066 64.821,54.3260067 64.515,54.1420068 L64.515,54.1420068 Z" id="Amazon-Elastic-Container-Service_Icon_64_Squid" fill="#FFFFFF"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="none"><path fill="url(#amazon-eks-color-16__paint0_linear_879_141)" fill-rule="evenodd" d="M6.381 10.148h.897V8.121l1.837 2.027h1.164L7.997 7.642l2.169-2.195H8.963L7.278 7.146V5.447h-.897v4.701z" clip-rule="evenodd"/><path fill="url(#amazon-eks-color-16__paint1_linear_879_141)" d="M8.532 3.803l3.186 1.81a.173.173 0 01.088.149v3.62c0 .06.033.118.088.149l2.842 1.615a.176.176 0 00.264-.15V3.947a.173.173 0 00-.088-.15L8.708.274a.176.176 0 00-.264.15v3.23c0 .062.034.119.088.15z"/><path fill="url(#amazon-eks-color-16__paint2_linear_879_141)" d="M11.273 10.288l-3.185 1.81a.178.178 0 01-.176 0l-3.63-2.062a.173.173 0 01-.088-.15V5.762c0-.062.034-.119.088-.15l3.186-1.81a.172.172 0 00.088-.15V.424a.176.176 0 00-.264-.15L1.088 3.798a.173.173 0 00-.088.15V11.7c0 .061.033.118.088.15l6.824 3.876c.054.03.122.03.176 0l6.204-3.524a.172.172 0 000-.3l-2.843-1.615a.178.178 0 00-.176 0z"/><defs><linearGradient id="amazon-eks-color-16__paint0_linear_879_141" x1="10.691" x2="8.521" y1="9.879" y2="4.634" gradientUnits="userSpaceOnUse"><stop stop-color="#426DDB"/><stop offset="1" stop-color="#3B4BDB"/></linearGradient><linearGradient id="amazon-eks-color-16__paint1_linear_879_141" x1="15.693" x2="9.546" y1="10.544" y2="-.213" gradientUnits="userSpaceOnUse"><stop stop-color="#426DDB"/><stop offset="1" stop-color="#3B4BDB"/></linearGradient><linearGradient id="amazon-eks-color-16__paint2_linear_879_141" x1="9.433" x2="2.732" y1="14.904" y2="2.88" gradientUnits="userSpaceOnUse"><stop stop-color="#2775FF"/><stop offset="1" stop-color="#188DFF"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -3,7 +3,7 @@
"alert_channels": "Alert Channels",
"organization_settings": "Organization Settings",
"ingestion_settings": "Ingestion Settings",
"api_keys": "Access Tokens",
"api_keys": "API Keys",
"my_settings": "My Settings",
"overview_metrics": "Overview Metrics",
"dbcall_metrics": "Database Calls",

View File

@@ -26,7 +26,7 @@
"MY_SETTINGS": "SigNoz | My Settings",
"ORG_SETTINGS": "SigNoz | Organization Settings",
"INGESTION_SETTINGS": "SigNoz | Ingestion Settings",
"API_KEYS": "SigNoz | Access Tokens",
"API_KEYS": "SigNoz | API Keys",
"SOMETHING_WENT_WRONG": "SigNoz | Something Went Wrong",
"UN_AUTHORIZED": "SigNoz | Unauthorized",
"NOT_FOUND": "SigNoz | Page Not Found",

View File

@@ -1,3 +1,3 @@
{
"delete_confirm_message": "Are you sure you want to delete {{keyName}} token? Deleting a token is irreversible and cannot be undone."
"delete_confirm_message": "Are you sure you want to delete {{keyName}} key? Deleting a key is irreversible and cannot be undone."
}

View File

@@ -3,7 +3,7 @@
"alert_channels": "Alert Channels",
"organization_settings": "Organization Settings",
"ingestion_settings": "Ingestion Settings",
"api_keys": "Access Tokens",
"api_keys": "API Keys",
"my_settings": "My Settings",
"overview_metrics": "Overview Metrics",
"dbcall_metrics": "Database Calls",

View File

@@ -26,7 +26,7 @@
"MY_SETTINGS": "SigNoz | My Settings",
"ORG_SETTINGS": "SigNoz | Organization Settings",
"INGESTION_SETTINGS": "SigNoz | Ingestion Settings",
"API_KEYS": "SigNoz | Access Tokens",
"API_KEYS": "SigNoz | API Keys",
"SOMETHING_WENT_WRONG": "SigNoz | Something Went Wrong",
"UN_AUTHORIZED": "SigNoz | Unauthorized",
"NOT_FOUND": "SigNoz | Page Not Found",
@@ -42,6 +42,5 @@
"SUPPORT": "SigNoz | Support",
"LOGS_SAVE_VIEWS": "SigNoz | Logs Save Views",
"TRACES_SAVE_VIEWS": "SigNoz | Traces Save Views",
"DEFAULT": "Open source Observability Platform | SigNoz",
"SHORTCUTS": "SigNoz | Shortcuts"
"DEFAULT": "Open source Observability Platform | SigNoz"
}

View File

@@ -1,25 +0,0 @@
files="";
# lint-staged will pass all files in $1 $2 $3 etc. iterate and concat.
for var in "$@"
do
files="$files \"$var\","
done
# create temporary tsconfig which includes only passed files
str="{
\"extends\": \"./tsconfig.json\",
\"include\": [\"src/types/global.d.ts\",\"src/typings/window.ts\", \"src/typings/chartjs-adapter-date-fns.d.ts\", \"src/typings/environment.ts\" ,\"src/container/OnboardingContainer/typings.d.ts\",$files]
}"
echo $str > tsconfig.tmp
# run typecheck using temp config
tsc -p ./tsconfig.tmp
# capture exit code of tsc
code=$?
# delete temp config
rm ./tsconfig.tmp
exit $code

View File

@@ -20,21 +20,16 @@ import { UPDATE_USER_IS_FETCH } from 'types/actions/app';
import AppReducer from 'types/reducer/app';
import { routePermission } from 'utils/permission';
import routes, {
LIST_LICENSES,
oldNewRoutesMapping,
oldRoutes,
} from './routes';
import routes from './routes';
import afterLogin from './utils';
function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
const location = useLocation();
const { pathname } = location;
const { pathname } = useLocation();
const mapRoutes = useMemo(
() =>
new Map(
[...routes, LIST_LICENSES].map((e) => {
routes.map((e) => {
const currentPath = matchPath(pathname, {
path: e.path,
});
@@ -64,8 +59,6 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
const currentRoute = mapRoutes.get('current');
const isOldRoute = oldRoutes.indexOf(pathname) > -1;
const isLocalStorageLoggedIn =
getLocalStorageApi(LOCALSTORAGE.IS_LOGGED_IN) === 'true';
@@ -165,16 +158,6 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
useEffect(() => {
(async (): Promise<void> => {
try {
if (isOldRoute) {
const redirectUrl = oldNewRoutesMapping[pathname];
const newLocation = {
...location,
pathname: redirectUrl,
};
history.replace(newLocation);
}
if (currentRoute) {
const { isPrivate, key } = currentRoute;

View File

@@ -8,7 +8,6 @@ import { LOCALSTORAGE } from 'constants/localStorage';
import ROUTES from 'constants/routes';
import AppLayout from 'container/AppLayout';
import useAnalytics from 'hooks/analytics/useAnalytics';
import { KeyboardHotkeysProvider } from 'hooks/hotkeys/useKeyboardHotkeys';
import { useThemeConfig } from 'hooks/useDarkMode';
import useGetFeatureFlag from 'hooks/useGetFeatureFlag';
import useLicense, { LICENSE_PLAN_KEY } from 'hooks/useLicense';
@@ -178,24 +177,22 @@ function App(): JSX.Element {
<ResourceProvider>
<QueryBuilderProvider>
<DashboardProvider>
<KeyboardHotkeysProvider>
<AppLayout>
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
<Switch>
{routes.map(({ path, component, exact }) => (
<Route
key={`${path}`}
exact={exact}
path={path}
component={component}
/>
))}
<AppLayout>
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
<Switch>
{routes.map(({ path, component, exact }) => (
<Route
key={`${path}`}
exact={exact}
path={path}
component={component}
/>
))}
<Route path="*" component={NotFound} />
</Switch>
</Suspense>
</AppLayout>
</KeyboardHotkeysProvider>
<Route path="*" component={NotFound} />
</Switch>
</Suspense>
</AppLayout>
</DashboardProvider>
</QueryBuilderProvider>
</ResourceProvider>

View File

@@ -186,7 +186,3 @@ export const WorkspaceBlocked = Loadable(
() =>
import(/* webpackChunkName: "WorkspaceLocked" */ 'pages/WorkspaceLocked'),
);
export const ShortcutsPage = Loadable(
() => import(/* webpackChunkName: "ShortcutsPage" */ 'pages/Shortcuts'),
);

View File

@@ -1,5 +1,4 @@
import ROUTES from 'constants/routes';
import Shortcuts from 'pages/Shortcuts/Shortcuts';
import WorkspaceBlocked from 'pages/WorkspaceLocked';
import { RouteProps } from 'react-router-dom';
@@ -279,13 +278,6 @@ const routes: AppRoutes[] = [
key: 'LIVE_LOGS',
isPrivate: true,
},
{
path: ROUTES.LOGS_PIPELINES,
exact: true,
component: PipelinePage,
key: 'LOGS_PIPELINES',
isPrivate: true,
},
{
path: ROUTES.LOGIN,
exact: true,
@@ -314,6 +306,13 @@ const routes: AppRoutes[] = [
key: 'SOMETHING_WENT_WRONG',
isPrivate: false,
},
{
path: ROUTES.LOGS_PIPELINES,
exact: true,
component: PipelinePage,
key: 'LOGS_PIPELINES',
isPrivate: true,
},
{
path: ROUTES.BILLING,
exact: true,
@@ -328,13 +327,6 @@ const routes: AppRoutes[] = [
isPrivate: true,
key: 'WORKSPACE_LOCKED',
},
{
path: ROUTES.SHORTCUTS,
exact: true,
component: Shortcuts,
isPrivate: true,
key: 'SHORTCUTS',
},
];
export const SUPPORT_ROUTE: AppRoutes = {
@@ -353,22 +345,6 @@ export const LIST_LICENSES: AppRoutes = {
key: 'LIST_LICENSES',
};
export const oldRoutes = [
'/pipelines',
'/logs/old-logs-explorer',
'/logs-explorer',
'/logs-explorer/live',
'/settings/api-keys',
];
export const oldNewRoutesMapping: Record<string, string> = {
'/pipelines': '/logs/pipelines',
'/logs/old-logs-explorer': '/logs/old-logs-explorer',
'/logs-explorer': '/logs/logs-explorer',
'/logs-explorer/live': '/logs/logs-explorer/live',
'/settings/api-keys': '/settings/access-tokens',
};
export interface AppRoutes {
component: RouteProps['component'];
path: RouteProps['path'];

View File

@@ -1,26 +0,0 @@
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { APIKeyProps, CreateAPIKeyProps } from 'types/api/pat/types';
const createAPIKey = async (
props: CreateAPIKeyProps,
): Promise<SuccessResponse<APIKeyProps> | ErrorResponse> => {
try {
const response = await axios.post('/pats', {
...props,
});
return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
export default createAPIKey;

View File

@@ -1,24 +0,0 @@
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { AllAPIKeyProps } from 'types/api/pat/types';
const deleteAPIKey = async (
id: string,
): Promise<SuccessResponse<AllAPIKeyProps> | ErrorResponse> => {
try {
const response = await axios.delete(`/pats/${id}`);
return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
export default deleteAPIKey;

View File

@@ -1,24 +0,0 @@
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps, Props } from 'types/api/alerts/get';
const get = async (
props: Props,
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
try {
const response = await axios.get(`/pats/${props.id}`);
return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
export default get;

View File

@@ -1,6 +0,0 @@
import axios from 'api';
import { AxiosResponse } from 'axios';
import { AllAPIKeyProps } from 'types/api/pat/types';
export const getAllAPIKeys = (): Promise<AxiosResponse<AllAPIKeyProps>> =>
axios.get(`/pats`);

View File

@@ -1,26 +0,0 @@
import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps, UpdateAPIKeyProps } from 'types/api/pat/types';
const updateAPIKey = async (
props: UpdateAPIKeyProps,
): Promise<SuccessResponse<PayloadProps> | ErrorResponse> => {
try {
const response = await axios.put(`/pats/${props.id}`, {
...props.data,
});
return {
statusCode: 200,
error: null,
message: response.data.status,
payload: response.data.data,
};
} catch (error) {
return ErrorResponseHandler(error as AxiosError);
}
};
export default updateAPIKey;

View File

@@ -1,41 +0,0 @@
import { CSSProperties } from 'react';
function BarIcon({
fillColor,
}: {
fillColor: CSSProperties['color'];
}): JSX.Element {
return (
<svg
width="30"
height="30"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8 2H6C4.89543 2 4 2.89543 4 4V16C4 17.1046 4.89543 18 6 18H8C9.10457 18 10 17.1046 10 16V4C10 2.89543 9.10457 2 8 2Z"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M18 9H16C14.8954 9 14 9.89543 14 11V16C14 17.1046 14.8954 18 16 18H18C19.1046 18 20 17.1046 20 16V11C20 9.89543 19.1046 9 18 9Z"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M22 22H2"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
export default BarIcon;

View File

@@ -1,30 +0,0 @@
import { CSSProperties } from 'react';
function ListIcon({
fillColor,
}: {
fillColor: CSSProperties['color'];
}): JSX.Element {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="30"
height="30"
viewBox="0 0 24 24"
fill="none"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<line x1="8" x2="21" y1="6" y2="6" />
<line x1="8" x2="21" y1="12" y2="12" />
<line x1="8" x2="21" y1="18" y2="18" />
<line x1="3" x2="3.01" y1="6" y2="6" />
<line x1="3" x2="3.01" y1="12" y2="12" />
<line x1="3" x2="3.01" y1="18" y2="18" />
</svg>
);
}
export default ListIcon;

View File

@@ -1,48 +1,18 @@
import { CSSProperties } from 'react';
function TableIcon({
fillColor,
}: {
fillColor: CSSProperties['color'];
}): JSX.Element {
function Table(): JSX.Element {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
width="48"
height="48"
viewBox="0 0 48 48"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 3V21"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M19 3H5C3.89543 3 3 3.89543 3 5V19C3 20.1046 3.89543 21 5 21H19C20.1046 21 21 20.1046 21 19V5C21 3.89543 20.1046 3 19 3Z"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M3 9H21"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M3 15H21"
stroke={fillColor}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
d="M41.0667 0H6.39993C2.87982 0 0 2.87982 0 6.39993V41.6001C0 45.1202 2.87982 48 6.39993 48H41.0667C44.5868 48 47.4667 45.1202 47.4667 41.6001V6.39993C47.4667 2.87982 44.5868 0 41.0667 0ZM44.2669 6.39993V9.60013H32.0002V3.2002H41.0668C42.8268 3.2002 44.267 4.63992 44.267 6.40003L44.2669 6.39993ZM17.6002 9.60013V3.2002H29.8669V9.60013H17.6002ZM29.8669 11.7333V44.8001H17.6002L17.6005 11.7333H29.8669ZM6.40012 3.20011H15.4667V9.60004H3.20001V6.39984C3.20001 4.63983 4.64011 3.20001 6.40022 3.20001L6.40012 3.20011ZM3.19992 41.6003V11.7335H15.4666V44.8003H6.40003C4.64002 44.8003 3.19982 43.3606 3.19982 41.6005L3.19992 41.6003ZM41.0667 44.8001H32.0001V11.7333H44.2668V41.6001C44.2668 43.3601 42.8267 44.7999 41.0666 44.7999L41.0667 44.8001ZM5.33326 18.6666C5.33326 18.08 5.81317 17.6001 6.39983 17.6001H12.2667C12.8534 17.6001 13.3333 18.08 13.3333 18.6666C13.3333 19.2533 12.8534 19.7332 12.2667 19.7332H6.39983C5.81315 19.7332 5.33326 19.2533 5.33326 18.6666ZM13.3333 25.0666C13.3333 25.6533 12.8534 26.1332 12.2667 26.1332H6.39983C5.81315 26.1332 5.33326 25.6532 5.33326 25.0666C5.33326 24.4799 5.81317 24 6.39983 24H12.2667C12.8534 24 13.3333 24.4799 13.3333 25.0666ZM13.3333 31.4665C13.3333 32.0532 12.8534 32.5331 12.2667 32.5331H6.39983C5.81315 32.5331 5.33326 32.0532 5.33326 31.4665C5.33326 30.8798 5.81317 30.3999 6.39983 30.3999H12.2667C12.8534 30.3999 13.3333 30.8798 13.3333 31.4665ZM13.3333 37.8668C13.3333 38.4535 12.8534 38.9334 12.2667 38.9334H6.39983C5.81315 38.9334 5.33326 38.4535 5.33326 37.8668C5.33326 37.2801 5.81317 36.8002 6.39983 36.8002H12.2667C12.8534 36.7999 13.3333 37.2802 13.3333 37.8668ZM19.7332 18.6667C19.7332 18.0801 20.2131 17.6002 20.7998 17.6002H26.6667C27.2534 17.6002 27.7333 18.0801 27.7333 18.6667C27.7333 19.2534 27.2533 19.7333 26.6667 19.7333H20.7998C20.2131 19.7333 19.7332 19.2534 19.7332 18.6667ZM19.7332 25.0667C19.7332 24.48 20.2131 24.0001 20.7998 24.0001H26.6667C27.2534 24.0001 27.7333 24.48 27.7333 25.0667C27.7333 25.6534 27.2533 26.1332 26.6667 26.1332H20.7998C20.2131 26.1332 19.7332 25.6533 19.7332 25.0667ZM19.7332 31.4666C19.7332 30.8799 20.2131 30.4 20.7998 30.4H26.6667C27.2534 30.4 27.7333 30.8799 27.7333 31.4666C27.7333 32.0533 27.2533 32.5332 26.6667 32.5332H20.7998C20.2131 32.5336 19.7332 32.0533 19.7332 31.4666ZM27.7333 37.8669C27.7333 38.4536 27.2533 38.9335 26.6667 38.9335H20.7998C20.2131 38.9335 19.7332 38.4536 19.7332 37.8669C19.7332 37.2802 20.2131 36.8003 20.7998 36.8003H26.6667C27.2534 36.8 27.7333 37.2803 27.7333 37.8669ZM42.1333 18.6668C42.1333 19.2535 41.6534 19.7334 41.0667 19.7334H35.1999C34.6132 19.7334 34.1333 19.2535 34.1333 18.6668C34.1333 18.0802 34.6132 17.6003 35.1999 17.6003H41.0667C41.6534 17.6003 42.1333 18.0802 42.1333 18.6668ZM42.1333 25.0668C42.1333 25.6535 41.6534 26.1333 41.0667 26.1333H35.1999C34.6132 26.1333 34.1333 25.6534 34.1333 25.0668C34.1333 24.4801 34.6132 24.0002 35.1999 24.0002H41.0667C41.6534 24.0002 42.1333 24.4801 42.1333 25.0668ZM42.1333 31.4667C42.1333 32.0534 41.6534 32.5333 41.0667 32.5333H35.1999C34.6132 32.5333 34.1333 32.0534 34.1333 31.4667C34.1333 30.88 34.6132 30.4001 35.1999 30.4001H41.0667C41.6534 30.4001 42.1333 30.88 42.1333 31.4667ZM42.1333 37.867C42.1333 38.4537 41.6534 38.9336 41.0667 38.9336H35.1999C34.6132 38.9336 34.1333 38.4537 34.1333 37.867C34.1333 37.2803 34.6132 36.8004 35.1999 36.8004H41.0667C41.6534 36.8001 42.1333 37.2803 42.1333 37.867Z"
fill="#1668DC"
/>
</svg>
);
}
export default TableIcon;
export default Table;

File diff suppressed because one or more lines are too long

View File

@@ -1,29 +1,19 @@
import { CSSProperties } from 'react';
function Value({
fillColor,
}: {
fillColor: CSSProperties['color'];
}): JSX.Element {
function Value(): JSX.Element {
return (
<svg
width="30"
height="30"
viewBox="0 0 24 24"
width="68"
height="48"
viewBox="0 0 68 48"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 3H5C4.46957 3 3.96086 3.21071 3.58579 3.58579C3.21071 3.96086 3 4.46957 3 5V9M9 3H19C19.5304 3 20.0391 3.21071 20.4142 3.58579C20.7893 3.96086 21 4.46957 21 5V9M9 21H19C19.5304 21 20.0391 20.7893 20.4142 20.4142C20.7893 20.0391 21 19.5304 21 19V9M9 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V9"
stroke="white"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
fill={fillColor}
d="M0 5.914V42.086C0 43.6542 0.62289 45.1585 1.73183 46.2675C2.84078 47.3771 4.34511 48 5.91329 48H61.5019C63.0701 48 64.5744 47.3771 65.6834 46.2675C66.7923 45.1585 67.4152 43.6542 67.4152 42.086V5.914C67.4152 4.34578 66.7923 2.84152 65.6834 1.73253C64.5744 0.623576 63.0701 0 61.5019 0H5.91329C4.34508 0 2.84082 0.623576 1.73183 1.73253C0.622872 2.84149 0 4.34581 0 5.914ZM63.4735 5.914V42.086C63.4735 42.6092 63.2659 43.1104 62.896 43.4803C62.5261 43.8495 62.0249 44.0571 61.5024 44.0571H5.91382C4.82549 44.0571 3.94277 43.175 3.94277 42.086V5.91403C3.94277 4.8257 4.82553 3.94298 5.91382 3.94298H61.5024C62.0249 3.94298 62.5261 4.15061 62.896 4.52048C63.2659 4.88968 63.4735 5.39148 63.4735 5.914Z"
fill="#1554AD"
/>
<path
d="M9.76562 15.6221C9.19922 15.6221 8.78906 15.3047 8.78906 14.6406V14.3818H6.58691C5.83984 14.3818 5.32227 13.9082 5.32227 13.2246C5.32227 12.8486 5.44922 12.4531 5.72266 11.9648C6.18164 11.1396 6.61621 10.4219 7.1582 9.57227C7.74414 8.64941 8.22266 8.33203 9.02832 8.33203C10.0586 8.33203 10.7422 8.90332 10.7422 9.76758V12.7949H10.9033C11.4453 12.7949 11.7041 13.1318 11.7041 13.5908C11.7041 14.0498 11.4404 14.3818 10.8984 14.3818H10.7422V14.6406C10.7422 15.3047 10.3271 15.6221 9.76562 15.6221ZM8.84766 12.8779V9.83594H8.80859C8.10059 10.8711 7.58789 11.6914 7.0166 12.8193V12.8779H8.84766ZM13.2959 15.5C12.6221 15.5 12.3291 15.124 12.3291 14.6064C12.3291 14.2256 12.5049 13.9326 12.8955 13.6055L14.834 11.9453C15.625 11.2666 15.8496 10.959 15.8496 10.5391C15.8496 10.0947 15.5078 9.78711 15.0049 9.78711C14.6338 9.78711 14.3799 9.95801 14.1162 10.3389C13.8428 10.7393 13.5938 10.8857 13.1982 10.8857C12.6709 10.8857 12.3486 10.5781 12.3486 10.0801C12.3486 9.91895 12.3779 9.76758 12.4414 9.62109C12.8125 8.78125 13.8037 8.25879 15.0342 8.25879C16.748 8.25879 17.8418 9.12305 17.8418 10.4023C17.8418 11.3496 17.3535 11.8428 16.2598 12.79L14.9756 13.8984V13.9375H17.2119C17.7295 13.9375 18.0225 14.2451 18.0225 14.7188C18.0225 15.1826 17.7295 15.5 17.2119 15.5H13.2959Z"
fill={fillColor}
d="M13.7695 17.668C10.1016 17.668 7.48828 20.1758 7.48828 23.6094V23.6328C7.48828 26.8438 9.76172 29.2109 13.0078 29.2109C15.3281 29.2109 16.8047 28.0273 17.4258 26.6914H17.6602C17.6602 26.8203 17.6484 26.9492 17.6484 27.0781C17.5195 30.3125 16.3828 32.9375 13.6992 32.9375C12.2109 32.9375 11.168 32.1641 10.7227 30.9805L10.6875 30.8633H7.71094L7.73438 30.9922C8.27344 33.582 10.5938 35.4219 13.6992 35.4219C17.9531 35.4219 20.5195 32.0469 20.5195 26.3516V26.3281C20.5195 20.2344 17.3789 17.668 13.7695 17.668ZM13.7578 26.8906C11.8359 26.8906 10.4414 25.4844 10.4414 23.5273V23.5039C10.4414 21.6172 11.9297 20.1289 13.793 20.1289C15.668 20.1289 17.1328 21.6406 17.1328 23.5742V23.5977C17.1328 25.5078 15.668 26.8906 13.7578 26.8906ZM24.832 35.2344C25.9102 35.2344 26.6953 34.4258 26.6953 33.3828C26.6953 32.3398 25.9102 31.5312 24.832 31.5312C23.7656 31.5312 22.9688 32.3398 22.9688 33.3828C22.9688 34.4258 23.7656 35.2344 24.832 35.2344ZM37.8633 35H40.7578V31.7539H43.0312V29.2578H40.7578V18.0898H36.4805C34.1836 21.582 31.7812 25.4727 29.5898 29.2812V31.7539H37.8633V35ZM32.4023 29.3281V29.1523C34.043 26.2812 36 23.1523 37.7344 20.5039H37.9102V29.3281H32.4023ZM52.6406 35.4219C56.3086 35.4219 58.9219 32.9141 58.9219 29.4805V29.457C58.9219 26.2461 56.6484 23.8789 53.4023 23.8789C51.082 23.8789 49.6055 25.0625 48.9844 26.3984H48.75C48.75 26.2695 48.7617 26.1406 48.7617 26.0117C48.8906 22.7773 50.0273 20.1523 52.7109 20.1523C54.1992 20.1523 55.2422 20.9258 55.6875 22.1094L55.7344 22.2266H58.6992L58.6758 22.0977C58.1367 19.5078 55.8164 17.668 52.7109 17.668C48.457 17.668 45.8906 21.043 45.8906 26.7383V26.7617C45.8906 32.8555 49.0312 35.4219 52.6406 35.4219ZM49.2773 29.5156V29.4922C49.2773 27.582 50.7422 26.1992 52.6523 26.1992C54.5742 26.1992 55.9688 27.6055 55.9688 29.5625V29.5859C55.9688 31.4727 54.4922 32.9609 52.6172 32.9609C50.7422 32.9609 49.2773 31.4492 49.2773 29.5156Z"
fill="#1668DC"
/>
</svg>
);

View File

@@ -21,7 +21,6 @@ import {
useEffect,
useState,
} from 'react';
import { useLocation } from 'react-router-dom';
import { popupContainer } from 'utils/selectPopupContainer';
import CustomTimePickerPopoverContent from './CustomTimePickerPopoverContent';
@@ -69,7 +68,6 @@ function CustomTimePicker({
const [inputErrorMessage, setInputErrorMessage] = useState<string | null>(
null,
);
const location = useLocation();
const [isInputFocused, setIsInputFocused] = useState(false);
const getSelectedTimeRangeLabel = (
@@ -154,7 +152,7 @@ function CustomTimePicker({
break;
}
if (minTime && (!minTime.isValid() || minTime < maxAllowedMinTime)) {
if (minTime && minTime < maxAllowedMinTime) {
setInputStatus('error');
onError(true);
setInputErrorMessage('Please enter time less than 6 months');
@@ -224,15 +222,6 @@ function CustomTimePicker({
setIsInputFocused(false);
};
// this is required as TopNav component wraps the components and we need to clear the state on path change
useEffect(() => {
setInputStatus('');
onError(false);
setInputErrorMessage(null);
setInputValue('');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location.pathname]);
return (
<div className="custom-time-picker">
<Popover

View File

@@ -5,7 +5,6 @@ import cx from 'classnames';
import ROUTES from 'constants/routes';
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
import {
LexicalContext,
Option,
RelativeDurationSuggestionOptions,
} from 'container/TopNav/DateTimeSelectionV2/config';
@@ -21,10 +20,7 @@ interface CustomTimePickerPopoverContentProps {
setIsOpen: Dispatch<SetStateAction<boolean>>;
customDateTimeVisible: boolean;
setCustomDTPickerVisible: Dispatch<SetStateAction<boolean>>;
onCustomDateHandler: (
dateTimeRange: DateTimeRangeType,
lexicalContext?: LexicalContext,
) => void;
onCustomDateHandler: (dateTimeRange: DateTimeRangeType) => void;
onSelectHandler: (label: string, value: string) => void;
handleGoLive: () => void;
selectedTime: string;
@@ -67,7 +63,7 @@ function CustomTimePickerPopoverContent({
if (date_time?.[1]) {
onPopoverClose(false);
}
onCustomDateHandler(date_time, LexicalContext.CUSTOM_DATE_PICKER);
onCustomDateHandler(date_time);
};
function getTimeChips(options: Option[]): JSX.Element {
return (

View File

@@ -8,7 +8,6 @@ import { VIEWS } from './constants';
export type LogDetailProps = {
log: ILog | null;
selectedTab: VIEWS;
isListViewPanel?: boolean;
} & Pick<AddToQueryHOCProps, 'onAddToQuery'> &
Partial<Pick<ActionItemProps, 'onClickActionItem'>> &
Pick<DrawerProps, 'onClose'>;

View File

@@ -151,12 +151,6 @@
border: 1px solid var(--bg-slate-400);
height: 46px;
padding: var(--padding-1) var(--padding-2);
box-shadow: none;
border-radius: 0;
}
.ant-drawer-close {
padding: 0px;
}
}

View File

@@ -35,7 +35,6 @@ function LogDetail({
onAddToQuery,
onClickActionItem,
selectedTab,
isListViewPanel = false,
}: LogDetailProps): JSX.Element {
const [, copyToClipboard] = useCopyToClipboard();
const [selectedView, setSelectedView] = useState<VIEWS>(selectedTab);
@@ -191,7 +190,6 @@ function LogDetail({
logData={log}
onAddToQuery={onAddToQuery}
onClickActionItem={onClickActionItem}
isListViewPanel={isListViewPanel}
/>
)}
{selectedView === VIEW_TYPES.JSON && <JSONView logData={log} />}

View File

@@ -1,3 +0,0 @@
.addToQueryContainer {
cursor: pointer;
}

View File

@@ -1,9 +1,9 @@
import './AddToQueryHOC.styles.scss';
import { Popover } from 'antd';
import { OPERATORS } from 'constants/queryBuilder';
import { memo, ReactNode, useCallback, useMemo } from 'react';
import { ButtonContainer } from './styles';
function AddToQueryHOC({
fieldKey,
fieldValue,
@@ -19,12 +19,11 @@ function AddToQueryHOC({
]);
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div className="addToQueryContainer" onClick={handleQueryAdd}>
<ButtonContainer size="small" type="text" onClick={handleQueryAdd}>
<Popover placement="top" content={popOverContent}>
{children}
</Popover>
</div>
</ButtonContainer>
);
}

View File

@@ -17,7 +17,7 @@ export default function LogLinesActionButtons({
}: LogLinesActionButtonsProps): JSX.Element {
return (
<div className={`log-line-action-buttons ${customClassName}`}>
<Tooltip title="Show in Context">
<Tooltip title="Show Context">
<Button
size="small"
icon={<TextSelect size={14} />}

View File

@@ -12,7 +12,7 @@ import { useCopyLogLink } from 'hooks/logs/useCopyLogLink';
// hooks
import { useIsDarkMode } from 'hooks/useDarkMode';
import { FlatLogData } from 'lib/logs/flatLogData';
import { isEmpty, isNumber, isUndefined } from 'lodash-es';
import { isEmpty, isUndefined } from 'lodash-es';
import {
KeyboardEvent,
MouseEvent,
@@ -73,14 +73,7 @@ function RawLogView({
const attributesValues = updatedSelecedFields
.map((field) => flattenLogData[field.name])
.filter((attribute) => {
// loadash isEmpty doesnot work with numbers
if (isNumber(attribute)) {
return true;
}
return !isUndefined(attribute) && !isEmpty(attribute);
});
.filter((attribute) => !isUndefined(attribute) && !isEmpty(attribute));
let attributesText = attributesValues.join(' | ');

View File

@@ -22,10 +22,6 @@ export const defaultTableStyle: CSSProperties = {
maxWidth: '40rem',
};
export const defaultListViewPanelStyle: CSSProperties = {
maxWidth: '40rem',
};
export const tableScroll: TableProps<Record<string, unknown>>['scroll'] = {
x: true,
};

View File

@@ -24,7 +24,6 @@ export type UseTableViewProps = {
onClickExpand?: (log: ILog) => void;
activeLog?: ILog | null;
activeContextLog?: ILog | null;
isListViewPanel?: boolean;
} & LogsTableViewProps;
export type ActionsColumnProps = {

View File

@@ -13,11 +13,7 @@ import { useMemo } from 'react';
import LogStateIndicator, {
LogType,
} from '../LogStateIndicator/LogStateIndicator';
import {
defaultListViewPanelStyle,
defaultTableStyle,
getDefaultCellStyle,
} from './config';
import { defaultTableStyle, getDefaultCellStyle } from './config';
import { TableBodyContent } from './styles';
import {
ColumnTypeRender,
@@ -35,7 +31,6 @@ export const useTableView = (props: UseTableViewProps): UseTableViewResult => {
appendTo = 'center',
activeContextLog,
activeLog,
isListViewPanel,
} = props;
const isDarkMode = useIsDarkMode();
@@ -53,9 +48,7 @@ export const useTableView = (props: UseTableViewProps): UseTableViewResult => {
key: name,
render: (field): ColumnTypeRender<Record<string, unknown>> => ({
props: {
style: isListViewPanel
? defaultListViewPanelStyle
: getDefaultCellStyle(isDarkMode),
style: getDefaultCellStyle(isDarkMode),
},
children: (
<Typography.Paragraph ellipsis={{ rows: linesPerRow }}>
@@ -65,10 +58,6 @@ export const useTableView = (props: UseTableViewProps): UseTableViewResult => {
}),
}));
if (isListViewPanel) {
return [...fieldColumns];
}
return [
{
title: 'timestamp',
@@ -121,7 +110,6 @@ export const useTableView = (props: UseTableViewProps): UseTableViewResult => {
];
}, [
fields,
isListViewPanel,
appendTo,
isDarkMode,
linesPerRow,

View File

@@ -32,7 +32,7 @@
.menu-items {
display: flex;
gap: 8px;
gap: 12px;
flex-direction: column;
margin-top: 12px;
}
@@ -49,7 +49,6 @@
display: flex;
color: var(--bg-vanilla-400, #c0c1c3);
justify-content: space-between;
align-items: center;
}
cursor: pointer;
@@ -89,6 +88,8 @@
.max-lines-per-row-input {
display: flex;
border: 1px solid var(--bg-slate-400, #1d212d);
.ant-input-number-handler-wrap {
display: none;
}
@@ -96,10 +97,7 @@
.ant-input-number {
min-width: 36px;
width: auto;
border-right: none;
border-left: none;
border-top: 1px solid var(--bg-slate-400);
border-bottom: 1px solid var(--bg-slate-400);
border: 0px;
text-align: center;
height: 26px;
border-radius: 0;

View File

@@ -1,31 +1,25 @@
.DynamicColumnTable {
display: flex;
flex-direction: column;
width: 100%;
display: flex;
flex-direction: column;
width: 100%;
.dynamicColumnTable-button {
align-self: flex-end;
margin: 10px 0;
&.filter-btn {
display: flex;
align-items: center;
justify-content: center;
}
}
.dynamicColumnTable-button {
align-self: flex-end;
margin: 10px 0;
}
}
.dynamicColumnsTable-items {
display: flex;
width: 10.625rem;
justify-content: space-between;
align-items: center;
display: flex;
width: 10.625rem;
justify-content: space-between;
align-items: center;
}
@media (max-width: 768px) {
.dynamicColumnsTable-items {
flex-direction: column;
width: auto;
text-align: center;
}
}
.dynamicColumnsTable-items {
flex-direction: column;
width: auto;
text-align: center;
}
}

View File

@@ -1,9 +1,9 @@
/* eslint-disable react/jsx-props-no-spreading */
import './DynamicColumnTable.syles.scss';
import { SettingOutlined } from '@ant-design/icons';
import { Button, Dropdown, MenuProps, Switch } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { SlidersHorizontal } from 'lucide-react';
import { memo, useEffect, useState } from 'react';
import { popupContainer } from 'utils/selectPopupContainer';
@@ -90,9 +90,9 @@ function DynamicColumnTable({
trigger={['click']}
>
<Button
className="dynamicColumnTable-button filter-btn"
className="dynamicColumnTable-button"
size="middle"
icon={<SlidersHorizontal size={14} />}
icon={<SettingOutlined />}
/>
</Dropdown>
)}

View File

@@ -73,12 +73,21 @@ function ResizeTable({
}
}, [columns]);
const paginationConfig = tableParams.pagination
? {
hideOnSinglePage: true,
showTotal: (total: number, range: number[]): string =>
`${range[0]}-${range[1]} of ${total} items`,
...tableParams.pagination,
}
: tableParams.pagination;
return onDragColumn ? (
<ReactDragListView.DragColumn {...dragColumnParams} onDragEnd={onDragColumn}>
<Table {...tableParams} />
<Table {...tableParams} pagination={paginationConfig} />
</ReactDragListView.DragColumn>
) : (
<Table {...tableParams} />
<Table {...tableParams} pagination={paginationConfig} />
);
}

View File

@@ -15,5 +15,4 @@ export enum LOCALSTORAGE {
LOGGED_IN_USER_EMAIL = 'LOGGED_IN_USER_EMAIL',
CHAT_SUPPORT = 'CHAT_SUPPORT',
IS_IDENTIFIED_USER = 'IS_IDENTIFIED_USER',
DASHBOARD_VARIABLES = 'DASHBOARD_VARIABLES',
}

View File

@@ -1,9 +1,6 @@
import Uplot from 'components/Uplot';
import GridTableComponent from 'container/GridTableComponent';
import GridValueComponent from 'container/GridValueComponent';
import LogsPanelComponent from 'container/LogsPanelTable/LogsPanelComponent';
import TracesTableComponent from 'container/TracesTableComponent/TracesTableComponent';
import { DataSource } from 'types/common/queryBuilder';
import { PANEL_TYPES } from './queryBuilder';
@@ -12,29 +9,10 @@ export const PANEL_TYPES_COMPONENT_MAP = {
[PANEL_TYPES.VALUE]: GridValueComponent,
[PANEL_TYPES.TABLE]: GridTableComponent,
[PANEL_TYPES.TRACE]: null,
[PANEL_TYPES.LIST]: LogsPanelComponent,
[PANEL_TYPES.LIST]: null,
[PANEL_TYPES.EMPTY_WIDGET]: null,
[PANEL_TYPES.BAR]: Uplot,
} as const;
export const getComponentForPanelType = (
panelType: PANEL_TYPES,
dataSource?: DataSource,
): React.ComponentType<any> | null => {
const componentsMap = {
[PANEL_TYPES.TIME_SERIES]: Uplot,
[PANEL_TYPES.VALUE]: GridValueComponent,
[PANEL_TYPES.TABLE]: GridTableComponent,
[PANEL_TYPES.TRACE]: null,
[PANEL_TYPES.LIST]:
dataSource === DataSource.LOGS ? LogsPanelComponent : TracesTableComponent,
[PANEL_TYPES.BAR]: Uplot,
[PANEL_TYPES.EMPTY_WIDGET]: null,
};
return componentsMap[panelType];
};
export const AVAILABLE_EXPORT_PANEL_TYPES = [
PANEL_TYPES.TIME_SERIES,
PANEL_TYPES.TABLE,

View File

@@ -264,7 +264,6 @@ export enum PANEL_TYPES {
TABLE = 'table',
LIST = 'list',
TRACE = 'trace',
BAR = 'bar',
EMPTY_WIDGET = 'EMPTY_WIDGET',
}

View File

@@ -24,7 +24,7 @@ const ROUTES = {
MY_SETTINGS: '/my-settings',
SETTINGS: '/settings',
ORG_SETTINGS: '/settings/org-settings',
API_KEYS: '/settings/access-tokens',
API_KEYS: '/settings/api-keys',
INGESTION_SETTINGS: '/settings/ingestion-settings',
SOMETHING_WENT_WRONG: '/something-went-wrong',
UN_AUTHORIZED: '/un-authorized',
@@ -45,7 +45,6 @@ const ROUTES = {
LOGS_SAVE_VIEWS: '/logs-save-views',
TRACES_SAVE_VIEWS: '/traces-save-views',
WORKSPACE_LOCKED: '/workspace-locked',
SHORTCUTS: '/shortcuts',
} as const;
export default ROUTES;

View File

@@ -1,32 +0,0 @@
import { getUserOperatingSystem, UserOperatingSystem } from 'utils/getUserOS';
const userOS = getUserOperatingSystem();
export const GlobalShortcuts = {
SidebarCollapse: '\\+meta',
NavigateToServices: 's+shift',
NavigateToTraces: 't+shift',
NavigateToLogs: 'l+shift',
NavigateToDashboards: 'd+shift',
NavigateToAlerts: 'a+shift',
NavigateToExceptions: 'e+shift',
};
export const GlobalShortcutsName = {
SidebarCollapse: `${userOS === UserOperatingSystem.MACOS ? 'cmd' : 'ctrl'}+\\`,
NavigateToServices: 'shift+s',
NavigateToTraces: 'shift+t',
NavigateToLogs: 'shift+l',
NavigateToDashboards: 'shift+d',
NavigateToAlerts: 'shift+a',
NavigateToExceptions: 'shift+e',
};
export const GlobalShortcutsDescription = {
SidebarCollapse: 'Collpase the sidebar',
NavigateToServices: 'Navigate to Services page',
NavigateToTraces: 'Navigate to Traces page',
NavigateToLogs: 'Navigate to logs page',
NavigateToDashboards: 'Navigate to dashboards page',
NavigateToAlerts: 'Navigate to alerts page',
NavigateToExceptions: 'Navigate to Exceptions page',
};

View File

@@ -1,19 +0,0 @@
import { getUserOperatingSystem, UserOperatingSystem } from 'utils/getUserOS';
const userOS = getUserOperatingSystem();
export const LogsExplorerShortcuts = {
StageAndRunQuery: 'enter+meta',
FocusTheSearchBar: 's',
};
export const LogsExplorerShortcutsName = {
StageAndRunQuery: `${
userOS === UserOperatingSystem.MACOS ? 'cmd' : 'ctrl'
}+enter`,
FocusTheSearchBar: 's',
};
export const LogsExplorerShortcutsDescription = {
StageAndRunQuery: 'Stage and Run the current query',
FocusTheSearchBar: 'Shift the focus to the last query filter bar',
};

View File

@@ -1,5 +1,5 @@
.api-key-container {
margin-top: 24px;
margin-top: 32px;
display: flex;
justify-content: center;
width: 100%;
@@ -18,7 +18,7 @@
}
.subtitle {
color: var(--bg-vanilla-400);
color: var(---bg-vanilla-400);
font-size: var(--font-size-sm);
font-style: normal;
font-weight: var(--font-weight-normal);
@@ -87,7 +87,7 @@
border-radius: 20px;
padding: 0px 12px;
background: var(--bg-ink-200);
background: var(--bg-ink-200, #23262e);
.ant-typography {
color: var(--bg-vanilla-400);
@@ -108,7 +108,7 @@
.action-btn {
display: flex;
align-items: center;
gap: 4px;
gap: 20px;
cursor: pointer;
}
@@ -117,37 +117,10 @@
background: rgba(113, 144, 249, 0.1);
}
}
.ant-collapse {
border: none;
.ant-collapse-header {
padding: 0px 8px;
display: flex;
align-items: center;
background-color: #121317;
}
.ant-collapse-content {
border-top: 1px solid var(--bg-slate-500);
}
.ant-collapse-item {
border-bottom: none;
}
.ant-collapse-expand-icon {
padding-inline-end: 0px;
}
}
.api-key-details {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
border-top: 1px solid var(--bg-slate-500);
border-top: 1px solid var(--bg-slate-500, #161922);
padding: 8px;
.api-key-tag {
@@ -175,12 +148,13 @@
margin-left: 8px;
}
.api-key-last-used-at {
.api-key-created-at {
display: flex;
align-items: center;
gap: 8px;
.ant-typography {
margin-left: 6px;
color: var(--bg-vanilla-400);
font-size: var(--font-size-sm);
font-style: normal;
@@ -192,40 +166,6 @@
font-feature-settings: 'dlig' on, 'salt' on, 'cpsp' on, 'case' on;
}
}
.api-key-expires-in {
font-style: normal;
font-weight: 400;
line-height: 18px;
display: flex;
align-items: center;
gap: 8px;
.dot {
height: 6px;
width: 6px;
border-radius: 50%;
}
&.warning {
color: var(--bg-amber-400);
.dot {
background: var(--bg-amber-400);
box-shadow: 0px 0px 6px 0px var(--bg-amber-400);
}
}
&.danger {
color: var(--bg-cherry-400);
.dot {
background: var(--bg-cherry-400);
box-shadow: 0px 0px 6px 0px var(--bg-cherry-400);
}
}
}
}
}
}
@@ -259,52 +199,17 @@
}
}
.api-key-info-container {
display: flex;
gap: 12px;
flex-direction: column;
.user-info {
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
.user-avatar {
background-color: lightslategray;
vertical-align: middle;
}
}
.user-email {
display: inline-flex;
align-items: center;
gap: 12px;
border-radius: 20px;
padding: 0px 12px;
background: var(--bg-ink-200);
font-family: 'Space Mono', monospace;
}
.role {
display: flex;
align-items: center;
gap: 12px;
}
}
.api-key-modal {
.ant-modal-content {
border-radius: 4px;
border: 1px solid var(--bg-slate-500);
background: var(--bg-ink-400);
border: 1px solid var(--Slate-500, #161922);
background: var(--Ink-400, #121317);
box-shadow: 0px -4px 16px 2px rgba(0, 0, 0, 0.2);
padding: 0;
.ant-modal-header {
background: none;
border-bottom: 1px solid var(--bg-slate-500);
border-bottom: 1px solid var(--Slate-500, #161922);
padding: 16px;
}
@@ -327,49 +232,20 @@
}
.api-key-access-role {
display: flex;
.ant-radio-button-wrapper {
font-size: 12px;
text-transform: capitalize;
&.ant-radio-button-wrapper-checked {
color: #fff;
background: var(--bg-slate-400, #1d212d);
border-color: var(--bg-slate-400, #1d212d);
&:hover {
color: #fff;
background: var(--bg-slate-400, #1d212d);
border-color: var(--bg-slate-400, #1d212d);
&::before {
background-color: var(--bg-slate-400, #1d212d);
}
}
&:focus {
color: #fff;
background: var(--bg-slate-400, #1d212d);
border-color: var(--bg-slate-400, #1d212d);
}
}
}
.tab {
border: 1px solid var(--bg-slate-400);
flex: 1;
display: flex;
justify-content: center;
&::before {
background: var(--bg-slate-400);
}
&.selected {
background: var(--bg-slate-400, #1d212d);
background: var(--Slate-400, #1d212d);
}
}
@@ -475,31 +351,6 @@
}
}
.expiration-selector {
.ant-select-selector {
border: 1px solid var(--bg-slate-400) !important;
}
}
.newAPIKeyDetails {
display: flex;
flex-direction: column;
gap: 8px;
}
.copyable-text {
display: inline-flex;
align-items: center;
gap: 12px;
border-radius: 20px;
padding: 0px 12px;
background: var(--bg-ink-200, #23262e);
.copy-key-btn {
cursor: pointer;
}
}
.lightMode {
.api-key-container {
.api-key-content {
@@ -522,18 +373,6 @@
border: 1px solid var(--bg-vanilla-200);
background: var(--bg-vanilla-100);
.ant-collapse {
border: none;
.ant-collapse-header {
background: var(--bg-vanilla-100);
}
.ant-collapse-content {
border-top: 1px solid var(--bg-vanilla-300);
}
}
.title-with-action {
.api-key-title {
.ant-typography {
@@ -541,18 +380,6 @@
}
}
.api-key-value {
background: var(--bg-vanilla-200);
.ant-typography {
color: var(--bg-slate-400);
}
.copy-key-btn {
cursor: pointer;
}
}
.action-btn {
.ant-typography {
color: var(--bg-ink-500);
@@ -561,7 +388,6 @@
}
.api-key-details {
border-top: 1px solid var(--bg-vanilla-200);
.api-key-tag {
background: var(--bg-vanilla-200);
.tag-text {
@@ -573,7 +399,7 @@
color: var(--bg-ink-500);
}
.api-key-last-used-at {
.api-key-created-at {
.ant-typography {
color: var(--bg-ink-500);
}
@@ -618,68 +444,4 @@
}
}
}
.api-key-info-container {
.user-email {
background: var(--bg-vanilla-200);
}
}
.api-key-modal {
.ant-modal-content {
border-radius: 4px;
border: 1px solid var(--bg-vanilla-200);
background: var(--bg-vanilla-100);
box-shadow: 0px -4px 16px 2px rgba(0, 0, 0, 0.2);
padding: 0;
.ant-modal-header {
background: none;
border-bottom: 1px solid var(--bg-vanilla-200);
padding: 16px;
}
}
}
.api-key-access-role {
.ant-radio-button-wrapper {
&.ant-radio-button-wrapper-checked {
color: var(--bg-ink-400);
background: var(--bg-vanilla-300);
border-color: var(--bg-vanilla-300);
&:hover {
color: var(--bg-ink-400);
background: var(--bg-vanilla-300);
border-color: var(--bg-vanilla-300);
&::before {
background-color: var(--bg-vanilla-300);
}
}
&:focus {
color: var(--bg-ink-400);
background: var(--bg-vanilla-300);
border-color: var(--bg-vanilla-300);
}
}
}
.tab {
border: 1px solid var(--bg-vanilla-300);
&::before {
background: var(--bg-vanilla-300);
}
&.selected {
background: var(--bg-vanilla-300);
}
}
}
.copyable-text {
background: var(--bg-vanilla-200);
}
}

View File

@@ -1,99 +0,0 @@
import {
createAPIKeyResponse,
getAPIKeysResponse,
} from 'mocks-server/__mockdata__/apiKeys';
import { server } from 'mocks-server/server';
import { rest } from 'msw';
import { act, fireEvent, render, screen, waitFor } from 'tests/test-utils';
import APIKeys from './APIKeys';
const apiKeysURL = 'http://localhost/api/v1/pats';
describe('APIKeys component', () => {
beforeEach(() => {
server.use(
rest.get(apiKeysURL, (req, res, ctx) =>
res(ctx.status(200), ctx.json(getAPIKeysResponse)),
),
);
render(<APIKeys />);
});
afterEach(() => {
jest.clearAllMocks();
});
it('renders APIKeys component without crashing', () => {
expect(screen.getByText('Access Tokens')).toBeInTheDocument();
expect(
screen.getByText('Create and manage access tokens for the SigNoz API'),
).toBeInTheDocument();
});
it('render list of Access Tokens', async () => {
server.use(
rest.get(apiKeysURL, (req, res, ctx) =>
res(ctx.status(200), ctx.json(getAPIKeysResponse)),
),
);
await waitFor(() => {
expect(screen.getByText('No Expiry Token')).toBeInTheDocument();
expect(screen.getByText('1-5 of 18 tokens')).toBeInTheDocument();
});
});
it('opens add new key modal on button click', async () => {
fireEvent.click(screen.getByText('New Token'));
await waitFor(() => {
const createNewKeyBtn = screen.getByRole('button', {
name: /Create new token/i,
});
expect(createNewKeyBtn).toBeInTheDocument();
});
});
it('closes add new key modal on cancel button click', async () => {
fireEvent.click(screen.getByText('New Token'));
const createNewKeyBtn = screen.getByRole('button', {
name: /Create new token/i,
});
await waitFor(() => {
expect(createNewKeyBtn).toBeInTheDocument();
});
fireEvent.click(screen.getByText('Cancel'));
await waitFor(() => {
expect(createNewKeyBtn).not.toBeInTheDocument();
});
});
it('creates a new key on form submission', async () => {
server.use(
rest.post(apiKeysURL, (req, res, ctx) =>
res(ctx.status(200), ctx.json(createAPIKeyResponse)),
),
);
fireEvent.click(screen.getByText('New Token'));
const createNewKeyBtn = screen.getByRole('button', {
name: /Create new token/i,
});
await waitFor(() => {
expect(createNewKeyBtn).toBeInTheDocument();
});
act(() => {
const inputElement = screen.getByPlaceholderText('Enter Token Name');
fireEvent.change(inputElement, { target: { value: 'Top Secret' } });
fireEvent.click(screen.getByTestId('create-form-admin-role-btn'));
fireEvent.click(createNewKeyBtn);
});
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -64,9 +64,7 @@ function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element {
});
}
return (
<ResizeTable columns={columns} dataSource={channels} rowKey="id" bordered />
);
return <ResizeTable columns={columns} dataSource={channels} rowKey="id" />;
}
interface AlertChannelsProps {

View File

@@ -13,7 +13,6 @@ import useAnalytics from 'hooks/analytics/useAnalytics';
import useAxiosError from 'hooks/useAxiosError';
import useLicense from 'hooks/useLicense';
import { useNotifications } from 'hooks/useNotifications';
import { pick } from 'lodash-es';
import { useCallback, useEffect, useState } from 'react';
import { useMutation, useQuery } from 'react-query';
import { useSelector } from 'react-redux';
@@ -306,7 +305,7 @@ export default function BillingContainer(): JSX.Element {
const handleBilling = useCallback(async () => {
if (isFreeTrial && !licensesData?.payload?.trialConvertedToSubscription) {
trackEvent('Billing : Upgrade Plan', {
user: pick(user, ['email', 'userId', 'name']),
user,
org,
});
@@ -317,7 +316,7 @@ export default function BillingContainer(): JSX.Element {
});
} else {
trackEvent('Billing : Manage Billing', {
user: pick(user, ['email', 'userId', 'name']),
user,
org,
});

View File

@@ -16,21 +16,16 @@ function Controls({
handleNavigatePrevious,
handleNavigateNext,
handleCountItemsPerPageChange,
isLogPanel = false,
}: ControlsProps): JSX.Element | null {
const isNextAndPreviousDisabled = useMemo(
() => isLoading || countPerPage < 0 || totalCount === 0,
[isLoading, countPerPage, totalCount],
);
const isPreviousDisabled = useMemo(
() => (isLogPanel ? false : offset <= 0 || isNextAndPreviousDisabled),
[isLogPanel, isNextAndPreviousDisabled, offset],
);
const isNextDisabled = useMemo(
() =>
isLogPanel ? false : totalCount < countPerPage || isNextAndPreviousDisabled,
[countPerPage, isLogPanel, isNextAndPreviousDisabled, totalCount],
);
const isPreviousDisabled = useMemo(() => offset <= 0, [offset]);
const isNextDisabled = useMemo(() => totalCount < countPerPage, [
countPerPage,
totalCount,
]);
return (
<Container>
@@ -38,7 +33,7 @@ function Controls({
loading={isLoading}
size="small"
type="link"
disabled={isPreviousDisabled}
disabled={isPreviousDisabled || isNextAndPreviousDisabled}
onClick={handleNavigatePrevious}
>
<LeftOutlined /> Previous
@@ -47,7 +42,7 @@ function Controls({
loading={isLoading}
size="small"
type="link"
disabled={isNextDisabled}
disabled={isNextDisabled || isNextAndPreviousDisabled}
onClick={handleNavigateNext}
>
Next <RightOutlined />
@@ -73,7 +68,6 @@ function Controls({
Controls.defaultProps = {
offset: 0,
perPageOptions: DEFAULT_PER_PAGE_OPTIONS,
isLogPanel: false,
};
export interface ControlsProps {
@@ -85,7 +79,6 @@ export interface ControlsProps {
handleNavigatePrevious: () => void;
handleNavigateNext: () => void;
handleCountItemsPerPageChange: (value: Pagination['limit']) => void;
isLogPanel?: boolean;
}
export default memo(Controls);

View File

@@ -50,8 +50,6 @@ function CreateAlertChannels({
*Summary:* {{ .Annotations.summary }}
*Description:* {{ .Annotations.description }}
*RelatedLogs:* {{ .Annotations.related_logs }}
*RelatedTraces:* {{ .Annotations.related_traces }}
*Details:*
{{ range .Labels.SortedPairs }} • *{{ .Name }}:* {{ .Value }}

View File

@@ -29,7 +29,7 @@ import useErrorNotification from 'hooks/useErrorNotification';
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
import { useNotifications } from 'hooks/useNotifications';
import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery';
import { Check, ConciergeBell, Disc3, Plus, X, XCircle } from 'lucide-react';
import { Check, ConciergeBell, Disc3, Plus, X } from 'lucide-react';
import { CSSProperties, useCallback, useMemo, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { Dashboard } from 'types/api/dashboard/getAll';
@@ -107,7 +107,7 @@ function ExplorerOptions({
const viewName = useGetSearchQueryParam(QueryParams.viewName) || '';
const viewKey = useGetSearchQueryParam(QueryParams.viewKey) || '';
const extraData = viewsData?.data?.data?.find((view) => view.uuid === viewKey)
const extraData = viewsData?.data.data.find((view) => view.uuid === viewKey)
?.extraData;
const extraDataColor = extraData ? JSON.parse(extraData).color : '';
@@ -134,7 +134,7 @@ function ExplorerOptions({
};
const onUpdateQueryHandler = (): void => {
const extraData = viewsData?.data?.data?.find((view) => view.uuid === viewKey)
const extraData = viewsData?.data.data.find((view) => view.uuid === viewKey)
?.extraData;
updateViewAsync(
{
@@ -166,7 +166,7 @@ function ExplorerOptions({
({ key }: { key: string }): void => {
const currentViewDetails = getViewDetailsUsingViewKey(
key,
viewsData?.data?.data,
viewsData?.data.data,
);
if (!currentViewDetails) return;
const {
@@ -290,13 +290,11 @@ function ExplorerOptions({
}}
dropdownStyle={dropdownStyle}
className="views-dropdown"
allowClear={{
clearIcon: <XCircle size={16} style={{ marginTop: '-3px' }} />,
}}
allowClear
onClear={handleClearSelect}
ref={ref}
>
{viewsData?.data?.data?.map((view) => {
{viewsData?.data.data.map((view) => {
const extraData =
view.extraData !== '' ? JSON.parse(view.extraData) : '';
let bgColor = getRandomColor();
@@ -332,21 +330,13 @@ function ExplorerOptions({
<hr />
<div className="actions">
<Tooltip title="Create Alerts">
<Button
disabled={disabled}
shape="circle"
onClick={onCreateAlertsHandler}
>
<ConciergeBell size={16} />
</Button>
</Tooltip>
<Button disabled={disabled} shape="circle" onClick={onCreateAlertsHandler}>
<ConciergeBell size={16} />
</Button>
<Tooltip title="Add to Dashboard">
<Button disabled={disabled} shape="circle" onClick={onAddToDashboard}>
<Plus size={16} />
</Button>
</Tooltip>
<Button disabled={disabled} shape="circle" onClick={onAddToDashboard}>
<Plus size={16} />
</Button>
</div>
</div>

View File

@@ -19,8 +19,6 @@ import { AlertDef } from 'types/api/alerts/def';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { GlobalReducer } from 'types/reducer/globalTime';
import { getGraphType } from 'utils/getGraphType';
import { getSortedSeriesData } from 'utils/getSortedSeriesData';
import { getTimeRange } from 'utils/getTimeRange';
import { ChartContainer, FailedMessageContainer } from './styles';
@@ -88,7 +86,7 @@ function ChartPreview({
{
query: query || initialQueriesMap.metrics,
globalSelectedInterval: selectedInterval,
graphType: getGraphType(graphType),
graphType,
selectedTime,
params: {
allowSelectedIntervalForStepGen,
@@ -116,13 +114,6 @@ function ChartPreview({
setMaxTimeScale(endTime);
}, [maxTime, minTime, globalSelectedInterval, queryResponse]);
if (queryResponse.data && graphType === PANEL_TYPES.BAR) {
const sortedSeriesData = getSortedSeriesData(
queryResponse.data?.payload.data.result,
);
queryResponse.data.payload.data.result = sortedSeriesData;
}
const chartData = getUPlotChartData(queryResponse?.data?.payload);
const containerDimensions = useResizeObserver(graphRef);
@@ -162,7 +153,6 @@ function ChartPreview({
],
softMax: null,
softMin: null,
panelType: graphType,
}),
[
yAxisUnit,
@@ -175,7 +165,6 @@ function ChartPreview({
t,
optionName,
alertDef?.condition.targetUnit,
graphType,
],
);

View File

@@ -8,11 +8,6 @@
display: flex;
align-items: center;
justify-content: center;
.prom-ql-icon {
height: 14px;
width: 14px;
}
}
.ant-btn-default {
border-color: transparent;

View File

@@ -1,10 +1,10 @@
import './QuerySection.styles.scss';
import { Button, Tabs, Tooltip } from 'antd';
import { Button, Tabs } from 'antd';
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { QueryBuilder } from 'container/QueryBuilder';
import { Atom, Play, Terminal } from 'lucide-react';
import { Atom, LucideAccessibility, Play, Terminal } from 'lucide-react';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
@@ -22,7 +22,6 @@ function QuerySection({
setQueryCategory,
alertType,
runQuery,
panelType,
}: QuerySectionProps): JSX.Element {
// init namespace for translations
const { t } = useTranslation('alerts');
@@ -45,7 +44,7 @@ function QuerySection({
const renderMetricUI = (): JSX.Element => (
<QueryBuilder
panelType={panelType}
panelType={PANEL_TYPES.TIME_SERIES}
config={{
queryVariant: 'static',
initialDataSource: ALERTS_DATA_SOURCE_MAP[alertType],
@@ -56,21 +55,17 @@ function QuerySection({
const tabs = [
{
label: (
<Tooltip title="Query Builder">
<Button className="nav-btns">
<Atom size={14} />
</Button>
</Tooltip>
<Button className="nav-btns">
<Atom size={14} />
</Button>
),
key: EQueryType.QUERY_BUILDER,
},
{
label: (
<Tooltip title="ClickHouse">
<Button className="nav-btns">
<Terminal size={14} />
</Button>
</Tooltip>
<Button className="nav-btns">
<Terminal size={14} />
</Button>
),
key: EQueryType.CLICKHOUSE,
},
@@ -80,31 +75,25 @@ function QuerySection({
() => [
{
label: (
<Tooltip title="Query Builder">
<Button className="nav-btns">
<Atom size={14} />
</Button>
</Tooltip>
<Button className="nav-btns">
<Atom size={14} />
</Button>
),
key: EQueryType.QUERY_BUILDER,
},
{
label: (
<Tooltip title="ClickHouse">
<Button className="nav-btns">
<Terminal size={14} />
</Button>
</Tooltip>
<Button className="nav-btns">
<Terminal size={14} />
</Button>
),
key: EQueryType.CLICKHOUSE,
},
{
label: (
<Tooltip title="PromQL">
<Button className="nav-btns">
<img src="/Icons/promQL.svg" alt="Prom Ql" className="prom-ql-icon" />
</Button>
</Tooltip>
<Button className="nav-btns">
<LucideAccessibility size={14} />
</Button>
),
key: EQueryType.PROM,
},
@@ -197,7 +186,6 @@ interface QuerySectionProps {
setQueryCategory: (n: EQueryType) => void;
alertType: AlertTypes;
runQuery: VoidFunction;
panelType: PANEL_TYPES;
}
export default QuerySection;

View File

@@ -83,7 +83,7 @@ function RuleOptions({
</InlineSelect>
);
const renderMatchOpts = (): JSX.Element => (
const renderThresholdMatchOpts = (): JSX.Element => (
<InlineSelect
getPopupContainer={popupContainer}
defaultValue={defaultMatchType}
@@ -98,13 +98,17 @@ function RuleOptions({
</InlineSelect>
);
const onChangeEvalWindow = (value: string | unknown): void => {
const ew = (value as string) || alertDef.evalWindow;
setAlertDef({
...alertDef,
evalWindow: ew,
});
};
const renderPromMatchOpts = (): JSX.Element => (
<InlineSelect
getPopupContainer={popupContainer}
defaultValue={defaultMatchType}
style={{ minWidth: '130px' }}
value={alertDef.condition?.matchType}
onChange={(value: string | unknown): void => handleMatchOptChange(value)}
>
<Select.Option value="1">{t('option_atleastonce')}</Select.Option>
</InlineSelect>
);
const renderEvalWindows = (): JSX.Element => (
<InlineSelect
@@ -112,7 +116,13 @@ function RuleOptions({
defaultValue={defaultEvalWindow}
style={{ minWidth: '120px' }}
value={alertDef.evalWindow}
onChange={onChangeEvalWindow}
onChange={(value: string | unknown): void => {
const ew = (value as string) || alertDef.evalWindow;
setAlertDef({
...alertDef,
evalWindow: ew,
});
}}
>
<Select.Option value="5m0s">{t('option_5min')}</Select.Option>
<Select.Option value="10m0s">{t('option_10min')}</Select.Option>
@@ -123,20 +133,6 @@ function RuleOptions({
</InlineSelect>
);
const renderPromEvalWindows = (): JSX.Element => (
<InlineSelect
getPopupContainer={popupContainer}
defaultValue={defaultEvalWindow}
style={{ minWidth: '120px' }}
value={alertDef.evalWindow}
onChange={onChangeEvalWindow}
>
<Select.Option value="5m0s">{t('option_5min')}</Select.Option>
<Select.Option value="10m0s">{t('option_10min')}</Select.Option>
<Select.Option value="15m0s">{t('option_15min')}</Select.Option>
</InlineSelect>
);
const renderThresholdRuleOpts = (): JSX.Element => (
<Form.Item>
<Typography.Text>
@@ -151,7 +147,7 @@ function RuleOptions({
onChange={onChangeSelectedQueryName}
/>
<Typography.Text>is</Typography.Text>
{renderCompareOps()} {t('text_condition2')} {renderMatchOpts()}{' '}
{renderCompareOps()} {t('text_condition2')} {renderThresholdMatchOpts()}{' '}
{t('text_condition3')} {renderEvalWindows()}
</Typography.Text>
</Form.Item>
@@ -171,8 +167,7 @@ function RuleOptions({
onChange={onChangeSelectedQueryName}
/>
<Typography.Text>is</Typography.Text>
{renderCompareOps()} {t('text_condition2')} {renderMatchOpts()}
{t('text_condition3')} {renderPromEvalWindows()}
{renderCompareOps()} {t('text_condition2')} {renderPromMatchOpts()}
</Typography.Text>
</Form.Item>
);

View File

@@ -10,7 +10,6 @@ import {
import saveAlertApi from 'api/alerts/save';
import testAlertApi from 'api/alerts/testAlert';
import { FeatureKeys } from 'constants/features';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import QueryTypeTag from 'container/NewWidget/LeftContainer/QueryTypeTag';
@@ -21,7 +20,6 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag';
import { useNotifications } from 'hooks/useNotifications';
import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
import { mapQueryDataToApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataToApi';
@@ -70,23 +68,14 @@ function FormAlertRules({
GlobalReducer
>((state) => state.globalTime);
const urlQuery = useUrlQuery();
const panelType = urlQuery.get(QueryParams.panelTypes) as PANEL_TYPES | null;
const {
currentQuery,
panelType,
stagedQuery,
handleRunQuery,
handleSetConfig,
initialDataSource,
redirectWithQueryBuilderData,
} = useQueryBuilder();
useEffect(() => {
handleSetConfig(panelType || PANEL_TYPES.TIME_SERIES, initialDataSource);
}, [handleSetConfig, initialDataSource, panelType]);
// use query client
const ruleCache = useQueryClient();
@@ -288,7 +277,7 @@ function FormAlertRules({
promQueries: mapQueryDataToApi(currentQuery.promql, 'name').data,
chQueries: mapQueryDataToApi(currentQuery.clickhouse_sql, 'name').data,
queryType: currentQuery.queryType,
panelType: panelType || initQuery.panelType,
panelType: initQuery.panelType,
unit: currentQuery.unit,
},
},
@@ -301,7 +290,6 @@ function FormAlertRules({
alertDef,
alertType,
initQuery,
panelType,
]);
const isAlertAvialable = useIsFeatureDisabled(
@@ -435,7 +423,6 @@ function FormAlertRules({
selectedInterval={globalSelectedInterval}
alertDef={alertDef}
yAxisUnit={yAxisUnit || ''}
graphType={panelType || PANEL_TYPES.TIME_SERIES}
/>
);
@@ -452,7 +439,6 @@ function FormAlertRules({
alertDef={alertDef}
selectedInterval={globalSelectedInterval}
yAxisUnit={yAxisUnit || ''}
graphType={panelType || PANEL_TYPES.TIME_SERIES}
/>
);
@@ -509,7 +495,6 @@ function FormAlertRules({
setQueryCategory={onQueryCategoryChange}
alertType={alertType || AlertTypes.METRICS_BASED_ALERT}
runQuery={handleRunQuery}
panelType={panelType || PANEL_TYPES.TIME_SERIES}
/>
<RuleOptions

View File

@@ -3,7 +3,6 @@ import { LoadingOutlined } from '@ant-design/icons';
import { Button, Card, Col, Divider, Modal, Row, Spin, Typography } from 'antd';
import setRetentionApi from 'api/settings/setRetention';
import TextToolTip from 'components/TextToolTip';
import GeneralSettingsCloud from 'container/GeneralSettingsCloud';
import useComponentPermission from 'hooks/useComponentPermission';
import { useNotifications } from 'hooks/useNotifications';
import find from 'lodash-es/find';
@@ -25,7 +24,6 @@ import {
PayloadPropsTraces as GetRetentionPeriodTracesPayload,
} from 'types/api/settings/getRetention';
import AppReducer from 'types/reducer/app';
import { isCloudUser } from 'utils/app';
import Retention from './Retention';
import StatusMessage from './StatusMessage';
@@ -396,8 +394,6 @@ function GeneralSettings({
onModalToggleHandler(type);
};
const isCloudUserVal = isCloudUser();
const renderConfig = [
{
name: 'Metrics',
@@ -525,7 +521,7 @@ function GeneralSettings({
return (
<Fragment key={category.name}>
<Col xs={22} xl={11} key={category.name} style={{ margin: '0.5rem' }}>
<Card style={{ height: '100%' }}>
<Card style={{ height: '100%', minHeight: 300 }}>
<Typography.Title style={{ margin: 0 }} level={3}>
{category.name}
</Typography.Title>
@@ -546,43 +542,38 @@ function GeneralSettings({
hide={!!retentionField.hide}
/>
))}
{!isCloudUserVal && (
<>
<ActionItemsContainer>
<Button
type="primary"
onClick={category.save.modalOpen}
disabled={category.save.isDisabled}
>
{category.save.saveButtonText}
</Button>
{category.statusComponent}
</ActionItemsContainer>
<Modal
title={t('retention_confirmation')}
focusTriggerAfterClose
forceRender
destroyOnClose
closable
onCancel={(): void =>
onModalToggleHandler(category.name.toLowerCase() as TTTLType)
}
onOk={(): Promise<void> =>
onOkHandler(category.name.toLowerCase() as TTTLType)
}
centered
open={category.save.modal}
confirmLoading={category.save.apiLoading}
>
<Typography>
{t('retention_confirmation_description', {
name: category.name.toLowerCase(),
})}
</Typography>
</Modal>
</>
)}
<ActionItemsContainer>
<Button
type="primary"
onClick={category.save.modalOpen}
disabled={category.save.isDisabled}
>
{category.save.saveButtonText}
</Button>
{category.statusComponent}
</ActionItemsContainer>
<Modal
title={t('retention_confirmation')}
focusTriggerAfterClose
forceRender
destroyOnClose
closable
onCancel={(): void =>
onModalToggleHandler(category.name.toLowerCase() as TTTLType)
}
onOk={(): Promise<void> =>
onOkHandler(category.name.toLowerCase() as TTTLType)
}
centered
open={category.save.modal}
confirmLoading={category.save.apiLoading}
>
<Typography>
{t('retention_confirmation_description', {
name: category.name.toLowerCase(),
})}
</Typography>
</Modal>
</Card>
</Col>
</Fragment>
@@ -596,20 +587,16 @@ function GeneralSettings({
{Element}
<Col xs={24} md={22} xl={20} xxl={18} style={{ margin: 'auto' }}>
<ErrorTextContainer>
{!isCloudUserVal && (
<TextToolTip
{...{
text: `More details on how to set retention period`,
url: 'https://signoz.io/docs/userguide/retention-period/',
}}
/>
)}
<TextToolTip
{...{
text: `More details on how to set retention period`,
url: 'https://signoz.io/docs/userguide/retention-period/',
}}
/>
{errorText && <ErrorText>{errorText}</ErrorText>}
</ErrorTextContainer>
<Row justify="start">{renderConfig}</Row>
{isCloudUserVal && <GeneralSettingsCloud />}
</Col>
</>
);

View File

@@ -8,7 +8,6 @@ import {
useRef,
useState,
} from 'react';
import { isCloudUser } from 'utils/app';
import {
Input,
@@ -86,13 +85,9 @@ function Retention({
func(null);
}
};
if (hide) {
return null;
}
const isCloudUserVal = isCloudUser();
return (
<RetentionContainer>
<Row justify="space-between">
@@ -103,14 +98,12 @@ function Retention({
<RetentionFieldInputContainer>
<Input
value={selectedValue && selectedValue >= 0 ? selectedValue : ''}
disabled={isCloudUserVal}
onChange={(e): void => onChangeHandler(e, setSelectedValue)}
style={{ width: 75 }}
/>
<Select
value={selectedTimeUnit}
onChange={currentSelectedOption}
disabled={isCloudUserVal}
style={{ width: 100 }}
>
{menuItems}

View File

@@ -1,6 +1,6 @@
import { green, orange, volcano } from '@ant-design/colors';
import { InfoCircleOutlined } from '@ant-design/icons';
import { Card, Col } from 'antd';
import { Card, Col, Row } from 'antd';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { TStatus } from 'types/api/settings/getRetention';
@@ -43,16 +43,9 @@ function StatusMessage({
width: '100%',
}}
>
<div
style={{
display: 'flex',
gap: '1rem',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Row style={{ gap: '1rem', alignItems: 'center', justifyContent: 'center' }}>
<Col xs={1}>
<InfoCircleOutlined style={{ fontSize: '1rem' }} />
<InfoCircleOutlined style={{ fontSize: '1.5rem' }} />
</Col>
<Col
@@ -63,7 +56,7 @@ function StatusMessage({
>
{statusMessage}
</Col>
</div>
</Row>
</Card>
) : null;
}

View File

@@ -1,11 +0,0 @@
.general-settings-container {
margin: 16px 8px;
.ant-card-body {
display: flex;
align-items: center;
gap: 16px;
padding: 8px;
margin: 16px 0;
}
}

View File

@@ -1,16 +0,0 @@
import './GeneralSettingsCloud.styles.scss';
import { Card, Typography } from 'antd';
import { Info } from 'lucide-react';
export default function GeneralSettingsCloud(): JSX.Element {
return (
<Card className="general-settings-container">
<Info size={16} />
<Typography.Text>
Please <a href="mailto:cloud-support@signoz.io"> email us </a> or connect
with us via intercom support to change the retention period.
</Typography.Text>
</Card>
);
}

View File

@@ -1,3 +0,0 @@
import GeneralSettingsCloud from './GeneralSettingsCloud';
export default GeneralSettingsCloud;

View File

@@ -10,6 +10,7 @@
.graph-container {
height: calc(60% - 40px);
min-height: 300px;
border: 1px solid #333;
width: 100%;
padding: 12px;
box-sizing: border-box;
@@ -17,11 +18,6 @@
border-radius: 3px;
}
.list-graph-container {
height: calc(100% - 40px);
overflow-y: auto;
}
.disabled {
height: calc(100% - 65px);
}

View File

@@ -25,6 +25,5 @@ export const PANEL_TYPES_VS_FULL_VIEW_TABLE: PanelTypeAndGraphManagerVisibilityP
TABLE: false,
LIST: false,
TRACE: false,
BAR: true,
EMPTY_WIDGET: false,
};

View File

@@ -2,11 +2,9 @@ import './WidgetFullView.styles.scss';
import { SyncOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import cx from 'classnames';
import { ToggleGraphProps } from 'components/Graph/types';
import Spinner from 'components/Spinner';
import TimePreference from 'components/TimePreferenceDropDown';
import { PANEL_TYPES } from 'constants/queryBuilder';
import GridPanelSwitch from 'container/GridPanelSwitch';
import {
timeItems,
@@ -25,12 +23,12 @@ import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime';
import uPlot from 'uplot';
import { getSortedSeriesData } from 'utils/getSortedSeriesData';
import { getTimeRange } from 'utils/getTimeRange';
import { getGraphVisibilityStateOnDataChange } from '../utils';
import { PANEL_TYPES_VS_FULL_VIEW_TABLE } from './contants';
import GraphManager from './GraphManager';
// import GraphManager from './GraphManager';
import { GraphContainer, TimeContainer } from './styles';
import { FullViewProps } from './types';
@@ -98,7 +96,7 @@ function FullView({
},
{
queryKey: `FullViewGetMetricsQueryRange-${selectedTime.enum}-${globalSelectedTime}-${widget.id}`,
enabled: !isDependedDataLoaded && widget.panelTypes !== PANEL_TYPES.LIST, // Internally both the list view panel has it's own query range api call, so we don't need to call it again
enabled: !isDependedDataLoaded,
},
);
@@ -107,13 +105,6 @@ function FullView({
panelTypeAndGraphManagerVisibility: PANEL_TYPES_VS_FULL_VIEW_TABLE,
});
if (response.data && widget.panelTypes === PANEL_TYPES.BAR) {
const sortedSeriesData = getSortedSeriesData(
response.data?.payload.data.result,
);
response.data.payload.data.result = sortedSeriesData;
}
const chartData = getUPlotChartData(response?.data?.payload, widget.fillSpans);
const isDarkMode = useIsDarkMode();
@@ -159,7 +150,6 @@ function FullView({
maxTimeScale,
softMax: widget.softMax === undefined ? null : widget.softMax,
softMin: widget.softMin === undefined ? null : widget.softMin,
panelType: widget.panelTypes,
});
setChartOptions(newChartOptions);
@@ -174,8 +164,6 @@ function FullView({
parentGraphVisibilityState(graphsVisibilityStates);
}, [graphsVisibilityStates, parentGraphVisibilityState]);
const isListView = widget.panelTypes === PANEL_TYPES.LIST;
if (response.isFetching) {
return <Spinner height="100%" size="large" tip="Loading..." />;
}
@@ -204,17 +192,14 @@ function FullView({
</div>
<div
className={cx('graph-container', {
disabled: isDashboardLocked,
'list-graph-container': isListView,
})}
className={
isDashboardLocked ? 'graph-container disabled' : 'graph-container'
}
ref={fullViewRef}
>
{chartOptions && (
<GraphContainer
style={{
height: isListView ? '100%' : '90%',
}}
style={{ height: '90%' }}
isGraphLegendToggleAvailable={canModifyChart}
>
<GridPanelSwitch
@@ -229,10 +214,6 @@ function FullView({
query={widget.query}
ref={fullViewChartRef}
thresholds={widget.thresholds}
selectedLogFields={widget.selectedLogFields}
dataSource={widget.query.builder.queryData[0].dataSource}
selectedTracesFields={widget.selectedTracesFields}
selectedTime={selectedTime}
/>
</GraphContainer>
)}

View File

@@ -5,7 +5,6 @@ import cx from 'classnames';
import { ToggleGraphProps } from 'components/Graph/types';
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import GridPanelSwitch from 'container/GridPanelSwitch';
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
import { useNotifications } from 'hooks/useNotifications';
@@ -48,7 +47,6 @@ function WidgetGraphComponent({
onClickHandler,
onDragSelect,
setGraphVisibility,
isFetchingResponse,
}: WidgetGraphComponentProps): JSX.Element {
const [deleteModal, setDeleteModal] = useState(false);
const [hovered, setHovered] = useState(false);
@@ -224,11 +222,7 @@ function WidgetGraphComponent({
});
};
const loadingState =
(queryResponse.isLoading || queryResponse.status === 'idle') &&
widget.panelTypes !== PANEL_TYPES.LIST;
if (loadingState) {
if (queryResponse.isLoading || queryResponse.status === 'idle') {
return (
<Skeleton
style={{
@@ -279,7 +273,6 @@ function WidgetGraphComponent({
onCancel={onToggleModelHandler}
width="85%"
destroyOnClose
className="widget-full-view"
>
<FullView
name={`${name}expanded`}
@@ -307,11 +300,10 @@ function WidgetGraphComponent({
threshold={threshold}
headerMenuList={headerMenuList}
isWarning={isWarning}
isFetchingResponse={isFetchingResponse}
/>
</div>
{queryResponse.isLoading && <Skeleton />}
{(queryResponse.isSuccess || widget.panelTypes === PANEL_TYPES.LIST) && (
{queryResponse.isSuccess && (
<div
className={cx('widget-graph-container', widget.panelTypes)}
ref={graphRef}
@@ -327,9 +319,6 @@ function WidgetGraphComponent({
panelData={queryResponse.data?.payload?.data.newResult.data.result || []}
query={widget.query}
thresholds={widget.thresholds}
selectedLogFields={widget.selectedLogFields}
dataSource={widget.query.builder?.queryData[0]?.dataSource}
selectedTracesFields={widget.selectedTracesFields}
/>
</div>
)}

View File

@@ -21,8 +21,6 @@ import { useLocation } from 'react-router-dom';
import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime';
import { getGraphType } from 'utils/getGraphType';
import { getSortedSeriesData } from 'utils/getSortedSeriesData';
import { getTimeRange } from 'utils/getTimeRange';
import EmptyWidget from '../EmptyWidget';
@@ -118,16 +116,10 @@ function GridCardGraph({
const isEmptyWidget =
widget?.id === PANEL_TYPES.EMPTY_WIDGET || isEmpty(widget);
const queryEnabledCondition =
isVisible &&
!isEmptyWidget &&
isQueryEnabled &&
widget.panelTypes !== PANEL_TYPES.LIST;
const queryResponse = useGetQueryRange(
{
selectedTime: widget?.timePreferance,
graphType: getGraphType(widget.panelTypes),
graphType: widget?.panelTypes,
query: updatedQuery,
globalSelectedInterval,
variables: getDashboardVariables(variables),
@@ -143,7 +135,7 @@ function GridCardGraph({
widget.timePreferance,
],
keepPreviousData: true,
enabled: queryEnabledCondition,
enabled: isVisible && !isEmptyWidget && isQueryEnabled,
refetchOnMount: false,
onError: (error) => {
setErrorMessage(error.message);
@@ -162,20 +154,12 @@ function GridCardGraph({
setMaxTimeScale(endTime);
}, [maxTime, minTime, globalSelectedInterval, queryResponse]);
if (queryResponse.data && widget.panelTypes === PANEL_TYPES.BAR) {
const sortedSeriesData = getSortedSeriesData(
queryResponse.data?.payload.data.result,
);
queryResponse.data.payload.data.result = sortedSeriesData;
}
const chartData = getUPlotChartData(queryResponse?.data?.payload, fillSpans);
const isDarkMode = useIsDarkMode();
const menuList =
widget.panelTypes === PANEL_TYPES.TABLE ||
widget.panelTypes === PANEL_TYPES.LIST
widget.panelTypes === PANEL_TYPES.TABLE
? headerMenuList.filter((menu) => menu !== MenuItemKeys.CreateAlerts)
: headerMenuList;
@@ -200,7 +184,6 @@ function GridCardGraph({
softMin: widget.softMin === undefined ? null : widget.softMin,
graphsVisibilityStates: graphVisibility,
setGraphsVisibilityStates: setGraphVisibility,
panelType: widget.panelTypes,
}),
[
widget?.id,
@@ -217,7 +200,6 @@ function GridCardGraph({
maxTimeScale,
graphVisibility,
setGraphVisibility,
widget.panelTypes,
],
);
@@ -240,7 +222,6 @@ function GridCardGraph({
onClickHandler={onClickHandler}
graphVisibiltyState={graphVisibility}
setGraphVisibility={setGraphVisibility}
isFetchingResponse={queryResponse.isFetching}
/>
)}
</div>

View File

@@ -30,7 +30,6 @@ export interface WidgetGraphComponentProps extends UplotProps {
isWarning: boolean;
graphVisibiltyState: boolean[];
setGraphVisibility: Dispatch<SetStateAction<boolean[]>>;
isFetchingResponse: boolean;
}
export interface GridCardGraphProps {

View File

@@ -16,28 +16,8 @@
}
}
.widget-full-view {
.ant-modal-content {
background-color: var(--bg-ink-400);
.ant-modal-header {
background-color: var(--bg-ink-400);
}
}
}
.lightMode {
.fullscreen-grid-container {
background-color: rgb(250, 250, 250);
}
.widget-full-view {
.ant-modal-content {
background-color: var(--bg-vanilla-100);
}
.ant-modal-header {
background-color: var(--bg-vanilla-100);
}
}
}

View File

@@ -2,7 +2,7 @@
display: flex;
justify-content: space-between;
align-items: center;
height: 30px;
height: 40px;
width: 100%;
padding: 0.5rem;
box-sizing: border-box;

View File

@@ -45,7 +45,6 @@ interface IWidgetHeaderProps {
threshold?: ReactNode;
headerMenuList?: MenuItemKeys[];
isWarning: boolean;
isFetchingResponse: boolean;
}
function WidgetHeader({
@@ -60,7 +59,6 @@ function WidgetHeader({
threshold,
headerMenuList,
isWarning,
isFetchingResponse,
}: IWidgetHeaderProps): JSX.Element | null {
const onEditHandler = useCallback((): void => {
const widgetId = widget.id;
@@ -172,7 +170,7 @@ function WidgetHeader({
</Typography.Text>
<div className="widget-header-actions">
<div className="widget-api-actions">{threshold}</div>
{isFetchingResponse && !queryResponse.isError && (
{queryResponse.isFetching && !queryResponse.isError && (
<Spinner style={{ paddingRight: '0.25rem' }} />
)}
{queryResponse.isError && (

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