mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-30 15:40:27 +01:00
Compare commits
7 Commits
infraM/v2_
...
chore/knip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fc181f84c | ||
|
|
cc3da72aa5 | ||
|
|
755390c4b5 | ||
|
|
adbd89aae9 | ||
|
|
b71de5b561 | ||
|
|
a672335a33 | ||
|
|
f4e5534e53 |
@@ -190,7 +190,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.120.0
|
||||
image: signoz/signoz:v0.121.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
# - "6060:6060" # pprof port
|
||||
|
||||
@@ -117,7 +117,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:v0.120.0
|
||||
image: signoz/signoz:v0.121.0
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
volumes:
|
||||
|
||||
@@ -181,7 +181,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.120.0}
|
||||
image: signoz/signoz:${VERSION:-v0.121.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
|
||||
@@ -109,7 +109,7 @@ services:
|
||||
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
|
||||
signoz:
|
||||
!!merge <<: *db-depend
|
||||
image: signoz/signoz:${VERSION:-v0.120.0}
|
||||
image: signoz/signoz:${VERSION:-v0.121.0}
|
||||
container_name: signoz
|
||||
ports:
|
||||
- "8080:8080" # signoz port
|
||||
|
||||
1174
docs/api/openapi.yml
1174
docs/api/openapi.yml
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/knip@5/schema.json",
|
||||
"project": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"ignore": ["src/api/generated/**/*.ts"]
|
||||
"ignore": ["src/api/generated/**/*.ts", "src/typings/*.ts"]
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
"@signozhq/design-tokens": "2.1.4",
|
||||
"@signozhq/icons": "0.1.0",
|
||||
"@signozhq/resizable": "0.0.2",
|
||||
"@signozhq/ui": "0.0.10",
|
||||
"@signozhq/ui": "0.0.12",
|
||||
"@tanstack/react-table": "8.21.3",
|
||||
"@tanstack/react-virtual": "3.13.22",
|
||||
"@uiw/codemirror-theme-copilot": "4.23.11",
|
||||
@@ -231,6 +231,7 @@
|
||||
"ts-jest": "29.4.6",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript-plugin-css-modules": "5.2.0",
|
||||
"use-sync-external-store": "1.6.0",
|
||||
"vite-plugin-checker": "0.12.0",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-image-optimizer": "2.0.3",
|
||||
@@ -266,4 +267,4 @@
|
||||
"tmp": "0.2.4",
|
||||
"vite": "npm:rolldown-vite@7.3.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,194 +12,16 @@ import type {
|
||||
} from 'react-query';
|
||||
|
||||
import type {
|
||||
InframonitoringtypesPostableClustersDTO,
|
||||
InframonitoringtypesPostableDeploymentsDTO,
|
||||
InframonitoringtypesPostableHostsDTO,
|
||||
InframonitoringtypesPostableNamespacesDTO,
|
||||
InframonitoringtypesPostableNodesDTO,
|
||||
InframonitoringtypesPostablePodsDTO,
|
||||
InframonitoringtypesPostableVolumesDTO,
|
||||
ListClusters200,
|
||||
ListDeployments200,
|
||||
ListHosts200,
|
||||
ListNamespaces200,
|
||||
ListNodes200,
|
||||
ListPods200,
|
||||
ListVolumes200,
|
||||
RenderErrorResponseDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type { ErrorType, BodyType } from '../../../generatedAPIInstance';
|
||||
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes clusters with key aggregated metrics derived by summing per-node values within the group: CPU usage, CPU allocatable, memory working set, memory allocatable. Each row also reports per-group node counts bucketed by each node's latest k8s.node.condition_ready value (readyNodesCount, notReadyNodesCount) and per-group pod counts bucketed by each pod's latest k8s.pod.phase value (pendingPodCount, runningPodCount, succeededPodCount, failedPodCount, unknownPodCount). Each cluster includes metadata attributes (k8s.cluster.name). The response type is 'list' for the default k8s.cluster.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates nodes and pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (clusterCPU, clusterCPUAllocatable, clusterMemory, clusterMemoryAllocatable) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Clusters for Infra Monitoring
|
||||
*/
|
||||
export const listClusters = (
|
||||
inframonitoringtypesPostableClustersDTO: BodyType<InframonitoringtypesPostableClustersDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListClusters200>({
|
||||
url: `/api/v2/infra_monitoring/clusters`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: inframonitoringtypesPostableClustersDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListClustersMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listClusters>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableClustersDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listClusters>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableClustersDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['listClusters'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof listClusters>>,
|
||||
{ data: BodyType<InframonitoringtypesPostableClustersDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return listClusters(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ListClustersMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listClusters>>
|
||||
>;
|
||||
export type ListClustersMutationBody =
|
||||
BodyType<InframonitoringtypesPostableClustersDTO>;
|
||||
export type ListClustersMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List Clusters for Infra Monitoring
|
||||
*/
|
||||
export const useListClusters = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listClusters>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableClustersDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof listClusters>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableClustersDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getListClustersMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes Deployments with key aggregated pod metrics: CPU usage and memory working set summed across pods owned by the deployment, plus average CPU/memory request and limit utilization (deploymentCPURequest, deploymentCPULimit, deploymentMemoryRequest, deploymentMemoryLimit). Each row also reports the latest known desiredPods (k8s.deployment.desired) and availablePods (k8s.deployment.available) replica counts and per-group pod counts bucketed by each pod's latest k8s.pod.phase value (pendingPodCount, runningPodCount, succeededPodCount, failedPodCount, unknownPodCount). Each deployment includes metadata attributes (k8s.deployment.name, k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.deployment.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods owned by deployments in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_request / cpu_limit / memory / memory_request / memory_limit / desired_pods / available_pods, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (deploymentCPU, deploymentCPURequest, deploymentCPULimit, deploymentMemory, deploymentMemoryRequest, deploymentMemoryLimit, desiredPods, availablePods) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Deployments for Infra Monitoring
|
||||
*/
|
||||
export const listDeployments = (
|
||||
inframonitoringtypesPostableDeploymentsDTO: BodyType<InframonitoringtypesPostableDeploymentsDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListDeployments200>({
|
||||
url: `/api/v2/infra_monitoring/deployments`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: inframonitoringtypesPostableDeploymentsDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListDeploymentsMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listDeployments>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableDeploymentsDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listDeployments>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableDeploymentsDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['listDeployments'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof listDeployments>>,
|
||||
{ data: BodyType<InframonitoringtypesPostableDeploymentsDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return listDeployments(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ListDeploymentsMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listDeployments>>
|
||||
>;
|
||||
export type ListDeploymentsMutationBody =
|
||||
BodyType<InframonitoringtypesPostableDeploymentsDTO>;
|
||||
export type ListDeploymentsMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List Deployments for Infra Monitoring
|
||||
*/
|
||||
export const useListDeployments = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listDeployments>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableDeploymentsDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof listDeployments>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableDeploymentsDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getListDeploymentsMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of hosts with key infrastructure metrics: CPU usage (%), memory usage (%), I/O wait (%), disk usage (%), and 15-minute load average. Each host includes its current status (active/inactive based on metrics reported in the last 10 minutes) and metadata attributes (e.g., os.type). Supports filtering via a filter expression, filtering by host status, custom groupBy to aggregate hosts by any attribute, ordering by any of the five metrics, and pagination via offset/limit. The response type is 'list' for the default host.name grouping or 'grouped_list' for custom groupBy keys. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (cpu, memory, wait, load15, diskUsage) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Hosts for Infra Monitoring
|
||||
@@ -284,174 +106,6 @@ export const useListHosts = <
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes namespaces with key aggregated pod metrics: CPU usage and memory working set (summed across pods in the group), plus per-group pod counts bucketed by each pod's latest k8s.pod.phase value in the window (pendingPodCount, runningPodCount, succeededPodCount, failedPodCount, unknownPodCount). Each namespace includes metadata attributes (k8s.namespace.name, k8s.cluster.name). The response type is 'list' for the default k8s.namespace.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates pods in the group. Supports filtering via a filter expression, custom groupBy, ordering by cpu / memory, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (namespaceCPU, namespaceMemory) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Namespaces for Infra Monitoring
|
||||
*/
|
||||
export const listNamespaces = (
|
||||
inframonitoringtypesPostableNamespacesDTO: BodyType<InframonitoringtypesPostableNamespacesDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListNamespaces200>({
|
||||
url: `/api/v2/infra_monitoring/namespaces`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: inframonitoringtypesPostableNamespacesDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListNamespacesMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listNamespaces>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNamespacesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listNamespaces>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNamespacesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['listNamespaces'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof listNamespaces>>,
|
||||
{ data: BodyType<InframonitoringtypesPostableNamespacesDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return listNamespaces(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ListNamespacesMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listNamespaces>>
|
||||
>;
|
||||
export type ListNamespacesMutationBody =
|
||||
BodyType<InframonitoringtypesPostableNamespacesDTO>;
|
||||
export type ListNamespacesMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List Namespaces for Infra Monitoring
|
||||
*/
|
||||
export const useListNamespaces = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listNamespaces>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNamespacesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof listNamespaces>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNamespacesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getListNamespacesMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes nodes with key metrics: CPU usage, CPU allocatable, memory working set, memory allocatable, and per-group readyNodesCount / notReadyNodesCount derived from each node's latest k8s.node.condition_ready value in the window. Each node includes metadata attributes (k8s.node.uid, k8s.cluster.name). The response type is 'list' for the default k8s.node.name grouping (each row is one node with its current condition string: ready / not_ready / '') or 'grouped_list' for custom groupBy keys (each row aggregates nodes in the group with readyNodesCount and notReadyNodesCount; condition stays empty). Supports filtering via a filter expression, custom groupBy, ordering by cpu / cpu_allocatable / memory / memory_allocatable, and pagination via offset/limit. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (nodeCPU, nodeCPUAllocatable, nodeMemory, nodeMemoryAllocatable) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Nodes for Infra Monitoring
|
||||
*/
|
||||
export const listNodes = (
|
||||
inframonitoringtypesPostableNodesDTO: BodyType<InframonitoringtypesPostableNodesDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListNodes200>({
|
||||
url: `/api/v2/infra_monitoring/nodes`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: inframonitoringtypesPostableNodesDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListNodesMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listNodes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNodesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listNodes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNodesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['listNodes'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof listNodes>>,
|
||||
{ data: BodyType<InframonitoringtypesPostableNodesDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return listNodes(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ListNodesMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listNodes>>
|
||||
>;
|
||||
export type ListNodesMutationBody =
|
||||
BodyType<InframonitoringtypesPostableNodesDTO>;
|
||||
export type ListNodesMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List Nodes for Infra Monitoring
|
||||
*/
|
||||
export const useListNodes = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listNodes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNodesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof listNodes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableNodesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getListNodesMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes pods with key metrics: CPU usage, CPU request/limit utilization, memory working set, memory request/limit utilization, current pod phase (pending/running/succeeded/failed/unknown), and pod age (ms since start time). Each pod includes metadata attributes (namespace, node, workload owner such as deployment/statefulset/daemonset/job/cronjob, cluster). Supports filtering via a filter expression, custom groupBy to aggregate pods by any attribute, ordering by any of the six metrics (cpu, cpu_request, cpu_limit, memory, memory_request, memory_limit), and pagination via offset/limit. The response type is 'list' for the default k8s.pod.uid grouping (each row is one pod with its current phase) or 'grouped_list' for custom groupBy keys (each row aggregates pods in the group with per-phase counts: pendingPodCount, runningPodCount, succeededPodCount, failedPodCount, unknownPodCount derived from each pod's latest phase in the window). Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (podCPU, podCPURequest, podCPULimit, podMemory, podMemoryRequest, podMemoryLimit, podAge) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Pods for Infra Monitoring
|
||||
@@ -536,87 +190,3 @@ export const useListPods = <
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a paginated list of Kubernetes persistent volume claims (PVCs) with key volume metrics: available bytes, capacity bytes, usage (capacity - available), inodes, free inodes, and used inodes. Each row also includes metadata attributes (k8s.persistentvolumeclaim.name, k8s.pod.uid, k8s.pod.name, k8s.namespace.name, k8s.node.name, k8s.statefulset.name, k8s.cluster.name). Supports filtering via a filter expression, custom groupBy to aggregate volumes by any attribute, ordering by any of the six metrics (available, capacity, usage, inodes, inodes_free, inodes_used), and pagination via offset/limit. The response type is 'list' for the default k8s.persistentvolumeclaim.name grouping or 'grouped_list' for custom groupBy keys; in both modes every row aggregates volumes in the group. Also reports missing required metrics and whether the requested time range falls before the data retention boundary. Numeric metric fields (volumeAvailable, volumeCapacity, volumeUsage, volumeInodes, volumeInodesFree, volumeInodesUsed) return -1 as a sentinel when no data is available for that field.
|
||||
* @summary List Volumes for Infra Monitoring
|
||||
*/
|
||||
export const listVolumes = (
|
||||
inframonitoringtypesPostableVolumesDTO: BodyType<InframonitoringtypesPostableVolumesDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListVolumes200>({
|
||||
url: `/api/v2/infra_monitoring/pvcs`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: inframonitoringtypesPostableVolumesDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListVolumesMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['listVolumes'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return listVolumes(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type ListVolumesMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listVolumes>>
|
||||
>;
|
||||
export type ListVolumesMutationBody =
|
||||
BodyType<InframonitoringtypesPostableVolumesDTO>;
|
||||
export type ListVolumesMutationError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List Volumes for Infra Monitoring
|
||||
*/
|
||||
export const useListVolumes = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof listVolumes>>,
|
||||
TError,
|
||||
{ data: BodyType<InframonitoringtypesPostableVolumesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getListVolumesMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
|
||||
399
frontend/src/api/generated/services/llmpricingrules/index.ts
Normal file
399
frontend/src/api/generated/services/llmpricingrules/index.ts
Normal file
@@ -0,0 +1,399 @@
|
||||
/**
|
||||
* ! Do not edit manually
|
||||
* * The file has been auto-generated using Orval for SigNoz
|
||||
* * regenerate with 'yarn generate:api'
|
||||
* SigNoz
|
||||
*/
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
import type {
|
||||
InvalidateOptions,
|
||||
MutationFunction,
|
||||
QueryClient,
|
||||
QueryFunction,
|
||||
QueryKey,
|
||||
UseMutationOptions,
|
||||
UseMutationResult,
|
||||
UseQueryOptions,
|
||||
UseQueryResult,
|
||||
} from 'react-query';
|
||||
|
||||
import type {
|
||||
DeleteLLMPricingRulePathParameters,
|
||||
GetLLMPricingRule200,
|
||||
GetLLMPricingRulePathParameters,
|
||||
ListLLMPricingRules200,
|
||||
ListLLMPricingRulesParams,
|
||||
LlmpricingruletypesUpdatableLLMPricingRulesDTO,
|
||||
RenderErrorResponseDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
import { GeneratedAPIInstance } from '../../../generatedAPIInstance';
|
||||
import type { ErrorType, BodyType } from '../../../generatedAPIInstance';
|
||||
|
||||
/**
|
||||
* Returns all LLM pricing rules for the authenticated org, with pagination.
|
||||
* @summary List pricing rules
|
||||
*/
|
||||
export const listLLMPricingRules = (
|
||||
params?: ListLLMPricingRulesParams,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<ListLLMPricingRules200>({
|
||||
url: `/api/v1/llm_pricing_rules`,
|
||||
method: 'GET',
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getListLLMPricingRulesQueryKey = (
|
||||
params?: ListLLMPricingRulesParams,
|
||||
) => {
|
||||
return [`/api/v1/llm_pricing_rules`, ...(params ? [params] : [])] as const;
|
||||
};
|
||||
|
||||
export const getListLLMPricingRulesQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof listLLMPricingRules>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListLLMPricingRulesParams,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listLLMPricingRules>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getListLLMPricingRulesQueryKey(params);
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof listLLMPricingRules>>
|
||||
> = ({ signal }) => listLLMPricingRules(params, signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listLLMPricingRules>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type ListLLMPricingRulesQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof listLLMPricingRules>>
|
||||
>;
|
||||
export type ListLLMPricingRulesQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary List pricing rules
|
||||
*/
|
||||
|
||||
export function useListLLMPricingRules<
|
||||
TData = Awaited<ReturnType<typeof listLLMPricingRules>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: ListLLMPricingRulesParams,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof listLLMPricingRules>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getListLLMPricingRulesQueryOptions(params, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary List pricing rules
|
||||
*/
|
||||
export const invalidateListLLMPricingRules = async (
|
||||
queryClient: QueryClient,
|
||||
params?: ListLLMPricingRulesParams,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getListLLMPricingRulesQueryKey(params) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Single write endpoint used by both the user and the Zeus sync job. Per-rule match is by id, then sourceId, then insert. Override rows (is_override=true) are fully preserved when the request does not provide isOverride; only synced_at is stamped.
|
||||
* @summary Create or update pricing rules
|
||||
*/
|
||||
export const createOrUpdateLLMPricingRules = (
|
||||
llmpricingruletypesUpdatableLLMPricingRulesDTO: BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO>,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/llm_pricing_rules`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: llmpricingruletypesUpdatableLLMPricingRulesDTO,
|
||||
});
|
||||
};
|
||||
|
||||
export const getCreateOrUpdateLLMPricingRulesMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createOrUpdateLLMPricingRules>>,
|
||||
TError,
|
||||
{ data: BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createOrUpdateLLMPricingRules>>,
|
||||
TError,
|
||||
{ data: BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createOrUpdateLLMPricingRules'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createOrUpdateLLMPricingRules>>,
|
||||
{ data: BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
return createOrUpdateLLMPricingRules(data);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type CreateOrUpdateLLMPricingRulesMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createOrUpdateLLMPricingRules>>
|
||||
>;
|
||||
export type CreateOrUpdateLLMPricingRulesMutationBody =
|
||||
BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO>;
|
||||
export type CreateOrUpdateLLMPricingRulesMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Create or update pricing rules
|
||||
*/
|
||||
export const useCreateOrUpdateLLMPricingRules = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createOrUpdateLLMPricingRules>>,
|
||||
TError,
|
||||
{ data: BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createOrUpdateLLMPricingRules>>,
|
||||
TError,
|
||||
{ data: BodyType<LlmpricingruletypesUpdatableLLMPricingRulesDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions =
|
||||
getCreateOrUpdateLLMPricingRulesMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Hard-deletes a pricing rule. If auto-synced, it will be recreated on the next sync cycle.
|
||||
* @summary Delete a pricing rule
|
||||
*/
|
||||
export const deleteLLMPricingRule = ({
|
||||
id,
|
||||
}: DeleteLLMPricingRulePathParameters) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/llm_pricing_rules/${id}`,
|
||||
method: 'DELETE',
|
||||
});
|
||||
};
|
||||
|
||||
export const getDeleteLLMPricingRuleMutationOptions = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteLLMPricingRule>>,
|
||||
TError,
|
||||
{ pathParams: DeleteLLMPricingRulePathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteLLMPricingRule>>,
|
||||
TError,
|
||||
{ pathParams: DeleteLLMPricingRulePathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['deleteLLMPricingRule'];
|
||||
const { mutation: mutationOptions } = options
|
||||
? options.mutation &&
|
||||
'mutationKey' in options.mutation &&
|
||||
options.mutation.mutationKey
|
||||
? options
|
||||
: { ...options, mutation: { ...options.mutation, mutationKey } }
|
||||
: { mutation: { mutationKey } };
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof deleteLLMPricingRule>>,
|
||||
{ pathParams: DeleteLLMPricingRulePathParameters }
|
||||
> = (props) => {
|
||||
const { pathParams } = props ?? {};
|
||||
|
||||
return deleteLLMPricingRule(pathParams);
|
||||
};
|
||||
|
||||
return { mutationFn, ...mutationOptions };
|
||||
};
|
||||
|
||||
export type DeleteLLMPricingRuleMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof deleteLLMPricingRule>>
|
||||
>;
|
||||
|
||||
export type DeleteLLMPricingRuleMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Delete a pricing rule
|
||||
*/
|
||||
export const useDeleteLLMPricingRule = <
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
TContext = unknown,
|
||||
>(options?: {
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof deleteLLMPricingRule>>,
|
||||
TError,
|
||||
{ pathParams: DeleteLLMPricingRulePathParameters },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof deleteLLMPricingRule>>,
|
||||
TError,
|
||||
{ pathParams: DeleteLLMPricingRulePathParameters },
|
||||
TContext
|
||||
> => {
|
||||
const mutationOptions = getDeleteLLMPricingRuleMutationOptions(options);
|
||||
|
||||
return useMutation(mutationOptions);
|
||||
};
|
||||
/**
|
||||
* Returns a single LLM pricing rule by ID.
|
||||
* @summary Get a pricing rule
|
||||
*/
|
||||
export const getLLMPricingRule = (
|
||||
{ id }: GetLLMPricingRulePathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetLLMPricingRule200>({
|
||||
url: `/api/v1/llm_pricing_rules/${id}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetLLMPricingRuleQueryKey = ({
|
||||
id,
|
||||
}: GetLLMPricingRulePathParameters) => {
|
||||
return [`/api/v1/llm_pricing_rules/${id}`] as const;
|
||||
};
|
||||
|
||||
export const getGetLLMPricingRuleQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getLLMPricingRule>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ id }: GetLLMPricingRulePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getLLMPricingRule>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getGetLLMPricingRuleQueryKey({ id });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getLLMPricingRule>>
|
||||
> = ({ signal }) => getLLMPricingRule({ id }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!id,
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getLLMPricingRule>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetLLMPricingRuleQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getLLMPricingRule>>
|
||||
>;
|
||||
export type GetLLMPricingRuleQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get a pricing rule
|
||||
*/
|
||||
|
||||
export function useGetLLMPricingRule<
|
||||
TData = Awaited<ReturnType<typeof getLLMPricingRule>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ id }: GetLLMPricingRulePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getLLMPricingRule>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetLLMPricingRuleQueryOptions({ id }, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
query.queryKey = queryOptions.queryKey;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get a pricing rule
|
||||
*/
|
||||
export const invalidateGetLLMPricingRule = async (
|
||||
queryClient: QueryClient,
|
||||
{ id }: GetLLMPricingRulePathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetLLMPricingRuleQueryKey({ id }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
@@ -3158,188 +3158,6 @@ export interface GlobaltypesTokenizerConfigDTO {
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type InframonitoringtypesClusterRecordDTOMeta = {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
|
||||
export interface InframonitoringtypesClusterRecordDTO {
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
clusterCPU: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
clusterCPUAllocatable: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
clusterMemory: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
clusterMemoryAllocatable: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
clusterName: string;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
failedPodCount: number;
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
meta: InframonitoringtypesClusterRecordDTOMeta;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
notReadyNodesCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
pendingPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
readyNodesCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
runningPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
succeededPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
unknownPodCount: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesClustersDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
records: InframonitoringtypesClusterRecordDTO[] | null;
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
total: number;
|
||||
type: InframonitoringtypesResponseTypeDTO;
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type InframonitoringtypesDeploymentRecordDTOMeta = {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
|
||||
export interface InframonitoringtypesDeploymentRecordDTO {
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
availablePods: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
deploymentCPU: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
deploymentCPULimit: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
deploymentCPURequest: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
deploymentMemory: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
deploymentMemoryLimit: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
deploymentMemoryRequest: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
deploymentName: string;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
desiredPods: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
failedPodCount: number;
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
meta: InframonitoringtypesDeploymentRecordDTOMeta;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
pendingPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
runningPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
succeededPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
unknownPodCount: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesDeploymentsDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
records: InframonitoringtypesDeploymentRecordDTO[] | null;
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
total: number;
|
||||
type: InframonitoringtypesResponseTypeDTO;
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesHostFilterDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -3425,146 +3243,6 @@ export interface InframonitoringtypesHostsDTO {
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type InframonitoringtypesNamespaceRecordDTOMeta = {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
|
||||
export interface InframonitoringtypesNamespaceRecordDTO {
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
failedPodCount: number;
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
meta: InframonitoringtypesNamespaceRecordDTOMeta;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
namespaceCPU: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
namespaceMemory: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
namespaceName: string;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
pendingPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
runningPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
succeededPodCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
unknownPodCount: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesNamespacesDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
records: InframonitoringtypesNamespaceRecordDTO[] | null;
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
total: number;
|
||||
type: InframonitoringtypesResponseTypeDTO;
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export enum InframonitoringtypesNodeConditionDTO {
|
||||
ready = 'ready',
|
||||
not_ready = 'not_ready',
|
||||
'' = '',
|
||||
}
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type InframonitoringtypesNodeRecordDTOMeta = {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
|
||||
export interface InframonitoringtypesNodeRecordDTO {
|
||||
condition: InframonitoringtypesNodeConditionDTO;
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
meta: InframonitoringtypesNodeRecordDTOMeta;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
nodeCPU: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
nodeCPUAllocatable: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
nodeMemory: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
nodeMemoryAllocatable: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
nodeName: string;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
notReadyNodesCount: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
readyNodesCount: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesNodesDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
records: InframonitoringtypesNodeRecordDTO[] | null;
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
total: number;
|
||||
type: InframonitoringtypesResponseTypeDTO;
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export enum InframonitoringtypesPodPhaseDTO {
|
||||
pending = 'pending',
|
||||
running = 'running',
|
||||
@@ -3667,62 +3345,6 @@ export interface InframonitoringtypesPodsDTO {
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableClustersDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
end: number;
|
||||
filter?: Querybuildertypesv5FilterDTO;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset?: number;
|
||||
orderBy?: Querybuildertypesv5OrderByDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableDeploymentsDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
end: number;
|
||||
filter?: Querybuildertypesv5FilterDTO;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset?: number;
|
||||
orderBy?: Querybuildertypesv5OrderByDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableHostsDTO {
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3751,62 +3373,6 @@ export interface InframonitoringtypesPostableHostsDTO {
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableNamespacesDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
end: number;
|
||||
filter?: Querybuildertypesv5FilterDTO;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset?: number;
|
||||
orderBy?: Querybuildertypesv5OrderByDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableNodesDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
end: number;
|
||||
filter?: Querybuildertypesv5FilterDTO;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset?: number;
|
||||
orderBy?: Querybuildertypesv5OrderByDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostablePodsDTO {
|
||||
/**
|
||||
* @type integer
|
||||
@@ -3835,34 +3401,6 @@ export interface InframonitoringtypesPostablePodsDTO {
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesPostableVolumesDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
end: number;
|
||||
filter?: Querybuildertypesv5FilterDTO;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
groupBy?: Querybuildertypesv5GroupByKeyDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset?: number;
|
||||
orderBy?: Querybuildertypesv5OrderByDTO;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
start: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesRequiredMetricsCheckDTO {
|
||||
/**
|
||||
* @type array
|
||||
@@ -3875,72 +3413,168 @@ export enum InframonitoringtypesResponseTypeDTO {
|
||||
list = 'list',
|
||||
grouped_list = 'grouped_list',
|
||||
}
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type InframonitoringtypesVolumeRecordDTOMeta = {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
|
||||
export interface InframonitoringtypesVolumeRecordDTO {
|
||||
/**
|
||||
* @type object
|
||||
* @nullable true
|
||||
*/
|
||||
meta: InframonitoringtypesVolumeRecordDTOMeta;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
persistentVolumeClaimName: string;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeAvailable: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeCapacity: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeInodes: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeInodesFree: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeInodesUsed: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
volumeUsage: number;
|
||||
}
|
||||
|
||||
export interface InframonitoringtypesVolumesDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
endTimeBeforeRetention: boolean;
|
||||
export interface LlmpricingruletypesGettablePricingRulesDTO {
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
records: InframonitoringtypesVolumeRecordDTO[] | null;
|
||||
requiredMetricsCheck: InframonitoringtypesRequiredMetricsCheckDTO;
|
||||
items: LlmpricingruletypesLLMPricingRuleDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
offset: number;
|
||||
/**
|
||||
* @type integer
|
||||
*/
|
||||
total: number;
|
||||
type: InframonitoringtypesResponseTypeDTO;
|
||||
warning?: Querybuildertypesv5QueryWarnDataDTO;
|
||||
}
|
||||
|
||||
export interface LlmpricingruletypesLLMPricingCacheCostsDTO {
|
||||
mode: LlmpricingruletypesLLMPricingRuleCacheModeDTO;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
read?: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
write?: number;
|
||||
}
|
||||
|
||||
export interface LlmpricingruletypesLLMPricingRuleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
createdBy?: string;
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
isOverride: boolean;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
modelName: string;
|
||||
modelPattern: LlmpricingruletypesStringSliceDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
orgId: string;
|
||||
pricing: LlmpricingruletypesLLMRulePricingDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
provider: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
sourceId?: string;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
* @nullable true
|
||||
*/
|
||||
syncedAt?: Date | null;
|
||||
unit: LlmpricingruletypesLLMPricingRuleUnitDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export enum LlmpricingruletypesLLMPricingRuleCacheModeDTO {
|
||||
subtract = 'subtract',
|
||||
additive = 'additive',
|
||||
unknown = 'unknown',
|
||||
}
|
||||
export enum LlmpricingruletypesLLMPricingRuleUnitDTO {
|
||||
per_million_tokens = 'per_million_tokens',
|
||||
}
|
||||
export interface LlmpricingruletypesLLMRulePricingDTO {
|
||||
cache?: LlmpricingruletypesLLMPricingCacheCostsDTO;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
input: number;
|
||||
/**
|
||||
* @type number
|
||||
* @format double
|
||||
*/
|
||||
output: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type LlmpricingruletypesStringSliceDTO = string[] | null;
|
||||
|
||||
export interface LlmpricingruletypesUpdatableLLMPricingRuleDTO {
|
||||
/**
|
||||
* @type boolean
|
||||
*/
|
||||
enabled: boolean;
|
||||
/**
|
||||
* @type string
|
||||
* @nullable true
|
||||
*/
|
||||
id?: string | null;
|
||||
/**
|
||||
* @type boolean
|
||||
* @nullable true
|
||||
*/
|
||||
isOverride?: boolean | null;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
modelName: string;
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
modelPattern: string[] | null;
|
||||
pricing: LlmpricingruletypesLLMRulePricingDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
provider: string;
|
||||
/**
|
||||
* @type string
|
||||
* @nullable true
|
||||
*/
|
||||
sourceId?: string | null;
|
||||
unit: LlmpricingruletypesLLMPricingRuleUnitDTO;
|
||||
}
|
||||
|
||||
export interface LlmpricingruletypesUpdatableLLMPricingRulesDTO {
|
||||
/**
|
||||
* @type array
|
||||
* @nullable true
|
||||
*/
|
||||
rules: LlmpricingruletypesUpdatableLLMPricingRuleDTO[] | null;
|
||||
}
|
||||
|
||||
export interface MetricsexplorertypesInspectMetricsRequestDTO {
|
||||
@@ -7534,6 +7168,41 @@ export type CreateInvite201 = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListLLMPricingRulesParams = {
|
||||
/**
|
||||
* @type integer
|
||||
* @description undefined
|
||||
*/
|
||||
offset?: number;
|
||||
/**
|
||||
* @type integer
|
||||
* @description undefined
|
||||
*/
|
||||
limit?: number;
|
||||
};
|
||||
|
||||
export type ListLLMPricingRules200 = {
|
||||
data: LlmpricingruletypesGettablePricingRulesDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type DeleteLLMPricingRulePathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetLLMPricingRulePathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetLLMPricingRule200 = {
|
||||
data: LlmpricingruletypesLLMPricingRuleDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListPromotedAndIndexedPaths200 = {
|
||||
/**
|
||||
* @type array
|
||||
@@ -8039,22 +7708,6 @@ export type Healthz503 = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListClusters200 = {
|
||||
data: InframonitoringtypesClustersDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListDeployments200 = {
|
||||
data: InframonitoringtypesDeploymentsDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListHosts200 = {
|
||||
data: InframonitoringtypesHostsDTO;
|
||||
/**
|
||||
@@ -8063,22 +7716,6 @@ export type ListHosts200 = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListNamespaces200 = {
|
||||
data: InframonitoringtypesNamespacesDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListNodes200 = {
|
||||
data: InframonitoringtypesNodesDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListPods200 = {
|
||||
data: InframonitoringtypesPodsDTO;
|
||||
/**
|
||||
@@ -8087,14 +7724,6 @@ export type ListPods200 = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type ListVolumes200 = {
|
||||
data: InframonitoringtypesVolumesDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type Livez200 = {
|
||||
data: FactoryResponseDTO;
|
||||
/**
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
.error-state-container {
|
||||
height: 240px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
border-radius: 3px;
|
||||
|
||||
.error-state-container-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.error-state-text {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.error-state-additional-messages {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.error-state-additional-text {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
import { Typography } from 'antd';
|
||||
|
||||
import APIError from '../../types/api/error';
|
||||
|
||||
import './Common.styles.scss';
|
||||
|
||||
interface ErrorStateComponentProps {
|
||||
message?: string;
|
||||
error?: APIError;
|
||||
}
|
||||
|
||||
const defaultProps: Partial<ErrorStateComponentProps> = {
|
||||
message: undefined,
|
||||
error: undefined,
|
||||
};
|
||||
|
||||
function ErrorStateComponent({
|
||||
message,
|
||||
error,
|
||||
}: ErrorStateComponentProps): JSX.Element {
|
||||
// Handle API Error object
|
||||
if (error) {
|
||||
const mainMessage = error.getErrorMessage();
|
||||
const additionalErrors = error.getErrorDetails().error.errors || [];
|
||||
|
||||
return (
|
||||
<div className="error-state-container">
|
||||
<div className="error-state-container-content">
|
||||
<Typography className="error-state-text">{mainMessage}</Typography>
|
||||
{additionalErrors.length > 0 && (
|
||||
<div className="error-state-additional-messages">
|
||||
{additionalErrors.map((additionalError) => (
|
||||
<Typography
|
||||
key={`error-${additionalError.message}`}
|
||||
className="error-state-additional-text"
|
||||
>
|
||||
• {additionalError.message}
|
||||
</Typography>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Handle simple string message (backwards compatibility)
|
||||
return (
|
||||
<div className="error-state-container">
|
||||
<div className="error-state-container-content">
|
||||
<Typography className="error-state-text">{message}</Typography>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ErrorStateComponent.defaultProps = defaultProps;
|
||||
|
||||
export default ErrorStateComponent;
|
||||
@@ -1,4 +0,0 @@
|
||||
.custom-date-picker {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import { Dispatch, SetStateAction, useMemo } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { DatePicker } from 'antd';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { DateTimeRangeType } from 'container/TopNav/CustomDateTimeModal';
|
||||
import {
|
||||
CustomTimeType,
|
||||
LexicalContext,
|
||||
Time,
|
||||
} from 'container/TopNav/DateTimeSelectionV2/types';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import './RangePickerModal.styles.scss';
|
||||
|
||||
interface RangePickerModalProps {
|
||||
setCustomDTPickerVisible: Dispatch<SetStateAction<boolean>>;
|
||||
setIsOpen: Dispatch<SetStateAction<boolean>>;
|
||||
onCustomDateHandler: (
|
||||
dateTimeRange: DateTimeRangeType,
|
||||
lexicalContext?: LexicalContext | undefined,
|
||||
) => void;
|
||||
selectedTime: string;
|
||||
onTimeChange?: (
|
||||
interval: Time | CustomTimeType,
|
||||
dateTimeRange?: [number, number],
|
||||
) => void;
|
||||
}
|
||||
|
||||
function RangePickerModal(props: RangePickerModalProps): JSX.Element {
|
||||
const {
|
||||
setCustomDTPickerVisible,
|
||||
setIsOpen,
|
||||
onCustomDateHandler,
|
||||
selectedTime,
|
||||
onTimeChange,
|
||||
} = props;
|
||||
const { RangePicker } = DatePicker;
|
||||
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
|
||||
(state) => state.globalTime,
|
||||
);
|
||||
|
||||
// Using any type here because antd's DatePicker expects its own internal Dayjs type
|
||||
// which conflicts with our project's Dayjs type that has additional plugins (tz, utc etc).
|
||||
const disabledDate = (current: any): boolean => {
|
||||
const currentDay = dayjs(current);
|
||||
return currentDay.isAfter(dayjs());
|
||||
};
|
||||
|
||||
const onPopoverClose = (visible: boolean): void => {
|
||||
if (!visible) {
|
||||
setCustomDTPickerVisible(false);
|
||||
}
|
||||
setIsOpen(visible);
|
||||
};
|
||||
|
||||
const onModalOkHandler = (date_time: any): void => {
|
||||
if (date_time?.[1]) {
|
||||
onPopoverClose(false);
|
||||
}
|
||||
onCustomDateHandler(date_time, LexicalContext.CUSTOM_DATE_PICKER);
|
||||
};
|
||||
const { timezone } = useTimezone();
|
||||
|
||||
const rangeValue: [Dayjs, Dayjs] = useMemo(
|
||||
() => [
|
||||
dayjs(minTime / 1000_000).tz(timezone.value),
|
||||
dayjs(maxTime / 1000_000).tz(timezone.value),
|
||||
],
|
||||
[maxTime, minTime, timezone.value],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="custom-date-picker">
|
||||
<RangePicker
|
||||
disabledDate={disabledDate}
|
||||
allowClear
|
||||
showTime
|
||||
format={(date: Dayjs): string =>
|
||||
date.tz(timezone.value).format(DATE_TIME_FORMATS.ISO_DATETIME)
|
||||
}
|
||||
onOk={onModalOkHandler}
|
||||
data-1p-ignore
|
||||
{...(selectedTime === 'custom' &&
|
||||
!onTimeChange && {
|
||||
value: rangeValue,
|
||||
})}
|
||||
// use default value if onTimeChange is provided
|
||||
{...(selectedTime === 'custom' &&
|
||||
onTimeChange && {
|
||||
defaultValue: rangeValue,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
RangePickerModal.defaultProps = {
|
||||
onTimeChange: undefined,
|
||||
};
|
||||
|
||||
export default RangePickerModal;
|
||||
@@ -1,93 +0,0 @@
|
||||
.details-drawer {
|
||||
.ant-drawer-wrapper-body {
|
||||
border-left: 1px solid var(--l1-border);
|
||||
}
|
||||
.ant-drawer-header {
|
||||
background: var(--l2-background);
|
||||
border-bottom: 1px solid var(--l1-border);
|
||||
|
||||
.ant-drawer-header-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.ant-drawer-close {
|
||||
margin-inline-end: 0px;
|
||||
padding: 0px;
|
||||
padding-right: 16px;
|
||||
border-right: 1px solid var(--l1-border);
|
||||
}
|
||||
|
||||
.ant-drawer-title {
|
||||
padding-left: 16px;
|
||||
color: var(--l2-foreground);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-drawer-body {
|
||||
padding: 16px;
|
||||
background: var(--l2-background);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.details-drawer-tabs {
|
||||
margin-top: 32px;
|
||||
|
||||
.ant-tabs-tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 114px;
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
padding: 7px 20px;
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l2-background);
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
|
||||
color: var(--l1-foreground);
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 150% */
|
||||
letter-spacing: -0.06px;
|
||||
|
||||
.ant-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.ant-btn:hover {
|
||||
background: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-tab-active {
|
||||
background: var(--l3-background);
|
||||
}
|
||||
|
||||
.ant-tabs-tab + .ant-tabs-tab {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
.ant-tabs-nav::before {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.ant-tabs-ink-bar {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Drawer, Tabs, TabsProps } from 'antd';
|
||||
import cx from 'classnames';
|
||||
|
||||
import './DetailsDrawer.styles.scss';
|
||||
|
||||
interface IDetailsDrawerProps {
|
||||
open: boolean;
|
||||
setOpen: Dispatch<SetStateAction<boolean>>;
|
||||
title: string;
|
||||
descriptiveContent: JSX.Element;
|
||||
defaultActiveKey: string;
|
||||
items: TabsProps['items'];
|
||||
detailsDrawerClassName?: string;
|
||||
tabBarExtraContent?: JSX.Element;
|
||||
}
|
||||
|
||||
function DetailsDrawer(props: IDetailsDrawerProps): JSX.Element {
|
||||
const {
|
||||
open,
|
||||
setOpen,
|
||||
title,
|
||||
descriptiveContent,
|
||||
defaultActiveKey,
|
||||
detailsDrawerClassName,
|
||||
items,
|
||||
tabBarExtraContent,
|
||||
} = props;
|
||||
return (
|
||||
<Drawer
|
||||
width="60%"
|
||||
open={open}
|
||||
afterOpenChange={setOpen}
|
||||
mask={false}
|
||||
title={title}
|
||||
onClose={(): void => setOpen(false)}
|
||||
className="details-drawer"
|
||||
>
|
||||
<div>{descriptiveContent}</div>
|
||||
<Tabs
|
||||
items={items}
|
||||
addIcon
|
||||
defaultActiveKey={defaultActiveKey}
|
||||
animated
|
||||
className={cx('details-drawer-tabs', detailsDrawerClassName)}
|
||||
tabBarExtraContent={tabBarExtraContent}
|
||||
/>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
DetailsDrawer.defaultProps = {
|
||||
detailsDrawerClassName: '',
|
||||
tabBarExtraContent: null,
|
||||
};
|
||||
|
||||
export default DetailsDrawer;
|
||||
@@ -46,6 +46,7 @@ function DeleteMemberDialog({
|
||||
color="destructive"
|
||||
disabled={isDeleting}
|
||||
onClick={onConfirm}
|
||||
loading={isDeleting}
|
||||
>
|
||||
<Trash2 size={12} />
|
||||
{isDeleting ? 'Processing...' : title}
|
||||
@@ -63,7 +64,6 @@ function DeleteMemberDialog({
|
||||
}}
|
||||
title={title}
|
||||
width="narrow"
|
||||
className="alert-dialog delete-dialog"
|
||||
showCloseButton={false}
|
||||
disableOutsideClick={false}
|
||||
footer={footer}
|
||||
|
||||
@@ -28,18 +28,6 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&__input {
|
||||
height: 32px;
|
||||
background: var(--l2-background);
|
||||
border-color: var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
box-shadow: none;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--l3-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
&__input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -48,7 +36,7 @@
|
||||
padding: var(--padding-1) var(--padding-2);
|
||||
border-radius: 2px;
|
||||
background: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--border);
|
||||
box-sizing: border-box;
|
||||
|
||||
&--disabled {
|
||||
@@ -65,8 +53,8 @@
|
||||
}
|
||||
|
||||
&__email-text {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-normal);
|
||||
font-size: var(--paragraph-base-400-font-size);
|
||||
font-weight: var(--paragraph-base-400-font-weight);
|
||||
color: var(--foreground);
|
||||
line-height: var(--line-height-18);
|
||||
letter-spacing: -0.07px;
|
||||
@@ -178,36 +166,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.delete-dialog {
|
||||
background: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
|
||||
[data-slot='dialog-title'] {
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
|
||||
&__body {
|
||||
font-size: var(--paragraph-base-400-font-size);
|
||||
font-weight: var(--paragraph-base-400-font-weight);
|
||||
color: var(--l2-foreground);
|
||||
line-height: var(--paragraph-base-400-line-height);
|
||||
letter-spacing: -0.065px;
|
||||
margin: 0;
|
||||
|
||||
strong {
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--spacing-4);
|
||||
margin-top: var(--margin-6);
|
||||
}
|
||||
}
|
||||
|
||||
.reset-link-dialog {
|
||||
background: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
@@ -264,13 +222,6 @@
|
||||
}
|
||||
|
||||
&__copy-btn {
|
||||
flex-shrink: 0;
|
||||
height: 32px;
|
||||
border-radius: 0 2px 2px 0;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
border-left: 1px solid var(--l1-border);
|
||||
min-width: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ function EditMemberDrawer({
|
||||
try {
|
||||
await rawRetry();
|
||||
setSaveErrors((prev) => prev.filter((e) => e.context !== context));
|
||||
refetchUser();
|
||||
void refetchUser();
|
||||
} catch (err) {
|
||||
setSaveErrors((prev) =>
|
||||
prev.map((e) =>
|
||||
@@ -250,7 +250,7 @@ function EditMemberDrawer({
|
||||
});
|
||||
}
|
||||
setSaveErrors((prev) => prev.filter((e) => e.context !== 'Name update'));
|
||||
refetchUser();
|
||||
void refetchUser();
|
||||
} catch (err) {
|
||||
setSaveErrors((prev) =>
|
||||
prev.map((e) =>
|
||||
@@ -319,7 +319,7 @@ function EditMemberDrawer({
|
||||
}),
|
||||
];
|
||||
});
|
||||
refetchUser();
|
||||
void refetchUser();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
@@ -340,7 +340,7 @@ function EditMemberDrawer({
|
||||
onComplete();
|
||||
}
|
||||
|
||||
refetchUser();
|
||||
void refetchUser();
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
@@ -465,7 +465,6 @@ function EditMemberDrawer({
|
||||
prev.filter((err) => err.context !== 'Name update'),
|
||||
);
|
||||
}}
|
||||
className="edit-member-drawer__input"
|
||||
placeholder="Enter name"
|
||||
disabled={isRootUser || isDeleted}
|
||||
/>
|
||||
@@ -631,7 +630,7 @@ function EditMemberDrawer({
|
||||
</div>
|
||||
|
||||
<div className="edit-member-drawer__footer-right">
|
||||
<Button variant="solid" color="secondary" onClick={handleClose}>
|
||||
<Button variant="outlined" color="secondary" onClick={handleClose}>
|
||||
<X size={14} />
|
||||
Cancel
|
||||
</Button>
|
||||
@@ -641,6 +640,7 @@ function EditMemberDrawer({
|
||||
color="primary"
|
||||
disabled={!isDirty || isSaving || isRootUser}
|
||||
onClick={handleSave}
|
||||
loading={isSaving}
|
||||
>
|
||||
{isSaving ? 'Saving...' : 'Save Member Details'}
|
||||
</Button>
|
||||
|
||||
@@ -44,9 +44,8 @@ function ResetLinkDialog({
|
||||
<span className="reset-link-dialog__link-text">{resetLink}</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="outlined"
|
||||
variant="link"
|
||||
color="secondary"
|
||||
size="sm"
|
||||
onClick={onCopy}
|
||||
prefix={hasCopied ? <Check size={12} /> : <Copy size={12} />}
|
||||
className="reset-link-dialog__copy-btn"
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from 'antd';
|
||||
|
||||
import { withErrorBoundary } from './index';
|
||||
|
||||
/**
|
||||
* Example component that can throw errors
|
||||
*/
|
||||
function ProblematicComponent(): JSX.Element {
|
||||
const [shouldThrow, setShouldThrow] = useState(false);
|
||||
|
||||
if (shouldThrow) {
|
||||
throw new Error('This is a test error from ProblematicComponent!');
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<h3>Problematic Component</h3>
|
||||
<p>This component can throw errors when the button is clicked.</p>
|
||||
<Button type="primary" onClick={(): void => setShouldThrow(true)} danger>
|
||||
Trigger Error
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic usage - wraps component with default error boundary
|
||||
*/
|
||||
export const SafeProblematicComponent = withErrorBoundary(ProblematicComponent);
|
||||
|
||||
/**
|
||||
* Usage with custom fallback component
|
||||
*/
|
||||
function CustomErrorFallback(): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
style={{ padding: '20px', border: '1px solid red', borderRadius: '4px' }}
|
||||
>
|
||||
<h4 style={{ color: 'red' }}>Custom Error Fallback</h4>
|
||||
<p>Something went wrong in this specific component!</p>
|
||||
<Button onClick={(): void => window.location.reload()}>Reload Page</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const SafeProblematicComponentWithCustomFallback = withErrorBoundary(
|
||||
ProblematicComponent,
|
||||
{
|
||||
fallback: <CustomErrorFallback />,
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Usage with custom error handler
|
||||
*/
|
||||
export const SafeProblematicComponentWithErrorHandler = withErrorBoundary(
|
||||
ProblematicComponent,
|
||||
{
|
||||
onError: (error, errorInfo) => {
|
||||
console.error('Custom error handler:', error);
|
||||
console.error('Error info:', errorInfo);
|
||||
// You could also send to analytics, logging service, etc.
|
||||
},
|
||||
sentryOptions: {
|
||||
tags: {
|
||||
section: 'dashboard',
|
||||
priority: 'high',
|
||||
},
|
||||
level: 'error',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Example of wrapping an existing component from the codebase
|
||||
*/
|
||||
function ExistingComponent({
|
||||
title,
|
||||
data,
|
||||
}: {
|
||||
title: string;
|
||||
data: any[];
|
||||
}): JSX.Element {
|
||||
// This could be any existing component that might throw errors
|
||||
return (
|
||||
<div>
|
||||
<h4>{title}</h4>
|
||||
<ul>
|
||||
{data.map((item, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<li key={index}>{item.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const SafeExistingComponent = withErrorBoundary(ExistingComponent, {
|
||||
sentryOptions: {
|
||||
tags: {
|
||||
component: 'ExistingComponent',
|
||||
feature: 'data-display',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Usage examples in a container component
|
||||
*/
|
||||
export function ErrorBoundaryExamples(): JSX.Element {
|
||||
const sampleData = [
|
||||
{ name: 'Item 1' },
|
||||
{ name: 'Item 2' },
|
||||
{ name: 'Item 3' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<h2>Error Boundary HOC Examples</h2>
|
||||
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<h3>1. Basic Usage</h3>
|
||||
<SafeProblematicComponent />
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<h3>2. With Custom Fallback</h3>
|
||||
<SafeProblematicComponentWithCustomFallback />
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<h3>3. With Custom Error Handler</h3>
|
||||
<SafeProblematicComponentWithErrorHandler />
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<h3>4. Wrapped Existing Component</h3>
|
||||
<SafeExistingComponent title="Sample Data" data={sampleData} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Style } from '@signozhq/design-tokens';
|
||||
import { ChevronDown, CircleAlert, Plus, Trash2, X } from '@signozhq/icons';
|
||||
import { ChevronDown, Plus, Trash2, X } from '@signozhq/icons';
|
||||
import {
|
||||
Button,
|
||||
Callout,
|
||||
@@ -294,10 +294,8 @@ function InviteMembersModal({
|
||||
type="error"
|
||||
size="small"
|
||||
showIcon
|
||||
icon={<CircleAlert size={12} />}
|
||||
>
|
||||
{getValidationErrorMessage()}
|
||||
</Callout>
|
||||
title={getValidationErrorMessage()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
.query-builder-search-wrapper {
|
||||
margin-top: 10px;
|
||||
border: 1px solid var(--l1-border);
|
||||
border-bottom: none;
|
||||
|
||||
.ant-select-selector {
|
||||
border: none !important;
|
||||
|
||||
input {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import { Dispatch, SetStateAction, useEffect } from 'react';
|
||||
import useInitialQuery from 'container/LogsExplorerContext/useInitialQuery';
|
||||
import QueryBuilderSearch from 'container/QueryBuilder/filters/QueryBuilderSearch';
|
||||
import { ILog } from 'types/api/logs/log';
|
||||
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import './QueryBuilderSearchWrapper.styles.scss';
|
||||
|
||||
function QueryBuilderSearchWrapper({
|
||||
log,
|
||||
filters,
|
||||
contextQuery,
|
||||
isEdit,
|
||||
suffixIcon,
|
||||
setFilters,
|
||||
setContextQuery,
|
||||
}: QueryBuilderSearchWraperProps): JSX.Element {
|
||||
const initialContextQuery = useInitialQuery(log);
|
||||
|
||||
useEffect(() => {
|
||||
setContextQuery(initialContextQuery);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const handleSearch = (tagFilters: TagFilter): void => {
|
||||
const tagFiltersLength = tagFilters.items.length;
|
||||
|
||||
if (
|
||||
(!tagFiltersLength && (!filters || !filters.items.length)) ||
|
||||
tagFiltersLength === filters?.items.length ||
|
||||
!contextQuery
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextQuery: Query = {
|
||||
...contextQuery,
|
||||
builder: {
|
||||
...contextQuery.builder,
|
||||
queryData: contextQuery.builder.queryData.map((item) => ({
|
||||
...item,
|
||||
filters: tagFilters,
|
||||
})),
|
||||
},
|
||||
};
|
||||
|
||||
setFilters({ ...tagFilters });
|
||||
setContextQuery({ ...nextQuery });
|
||||
};
|
||||
|
||||
if (!contextQuery || !isEdit) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<QueryBuilderSearch
|
||||
query={contextQuery?.builder.queryData[0]}
|
||||
onChange={handleSearch}
|
||||
className="query-builder-search-wrapper"
|
||||
suffixIcon={suffixIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
interface QueryBuilderSearchWraperProps {
|
||||
log: ILog;
|
||||
isEdit: boolean;
|
||||
contextQuery: Query | undefined;
|
||||
setContextQuery: Dispatch<SetStateAction<Query | undefined>>;
|
||||
filters: TagFilter | null;
|
||||
setFilters: Dispatch<SetStateAction<TagFilter | null>>;
|
||||
suffixIcon?: React.ReactNode;
|
||||
}
|
||||
|
||||
QueryBuilderSearchWrapper.defaultProps = {
|
||||
suffixIcon: undefined,
|
||||
};
|
||||
|
||||
export default QueryBuilderSearchWrapper;
|
||||
@@ -1,3 +0,0 @@
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
export const rawLineStyle: CSSProperties = {};
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Button } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const ButtonContainer = styled(Button)`
|
||||
&&& {
|
||||
padding-left: 0;
|
||||
}
|
||||
`;
|
||||
@@ -1,13 +0,0 @@
|
||||
.custom-multiselect-dropdown {
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: #e8e8e8;
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.all-option {
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
.loading-panel-data {
|
||||
padding: 24px 0;
|
||||
height: 240px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
|
||||
.loading-panel-data-content {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
|
||||
.loading-gif {
|
||||
height: 72px;
|
||||
margin-left: -24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Typography } from 'antd';
|
||||
|
||||
import loadingPlaneUrl from '@/assets/Icons/loading-plane.gif';
|
||||
|
||||
import './PanelDataLoading.styles.scss';
|
||||
|
||||
export function PanelDataLoading(): JSX.Element {
|
||||
return (
|
||||
<div className="loading-panel-data">
|
||||
<div className="loading-panel-data-content">
|
||||
<img className="loading-gif" src={loadingPlaneUrl} alt="wait-icon" />
|
||||
|
||||
<Typography.Text>Fetching data...</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -87,7 +87,7 @@
|
||||
|
||||
input {
|
||||
color: var(--l1-foreground);
|
||||
font-size: var(--font-size-sm);
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.ant-picker-suffix {
|
||||
@@ -126,12 +126,6 @@
|
||||
}
|
||||
|
||||
&__copy-btn {
|
||||
flex-shrink: 0;
|
||||
height: 32px;
|
||||
border-radius: 0 2px 2px 0;
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
border-left: 1px solid var(--l1-border);
|
||||
min-width: 40px;
|
||||
}
|
||||
@@ -152,6 +146,7 @@
|
||||
color: var(--foreground);
|
||||
letter-spacing: 0.48px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: var(--spacing-4);
|
||||
}
|
||||
|
||||
&__footer {
|
||||
|
||||
@@ -22,9 +22,8 @@ function KeyCreatedPhase({
|
||||
<div className="add-key-modal__key-display">
|
||||
<span className="add-key-modal__key-text">{createdKey.key}</span>
|
||||
<Button
|
||||
variant="outlined"
|
||||
variant="link"
|
||||
color="secondary"
|
||||
size="sm"
|
||||
onClick={onCopy}
|
||||
className="add-key-modal__copy-btn"
|
||||
>
|
||||
|
||||
@@ -106,7 +106,7 @@ function KeyFormPhase({
|
||||
|
||||
<div className="add-key-modal__footer">
|
||||
<div className="add-key-modal__footer-right">
|
||||
<Button variant="solid" color="secondary" size="sm" onClick={onClose}>
|
||||
<Button variant="solid" color="secondary" onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
@@ -115,7 +115,6 @@ function KeyFormPhase({
|
||||
form={FORM_ID}
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="sm"
|
||||
loading={isSubmitting}
|
||||
disabled={!isValid}
|
||||
>
|
||||
|
||||
@@ -136,7 +136,7 @@ function EditKeyForm({
|
||||
</form>
|
||||
|
||||
<div className="edit-key-modal__footer">
|
||||
<Button variant="ghost" color="destructive" onClick={onRevokeClick}>
|
||||
<Button variant="link" color="destructive" onClick={onRevokeClick}>
|
||||
<Trash2 size={12} />
|
||||
Revoke Key
|
||||
</Button>
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
|
||||
input {
|
||||
color: var(--l1-foreground);
|
||||
font-size: 13px;
|
||||
font-size: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.ant-picker-suffix {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
import { RevokeKeyContent } from '../RevokeKeyModal';
|
||||
import { RevokeKeyFooter } from '../RevokeKeyModal';
|
||||
import EditKeyForm from './EditKeyForm';
|
||||
import type { FormValues } from './types';
|
||||
import { DEFAULT_FORM_VALUES, ExpiryMode } from './types';
|
||||
@@ -158,17 +158,25 @@ function EditKeyModal({ keyItem }: EditKeyModalProps): JSX.Element {
|
||||
}
|
||||
width={isRevokeConfirmOpen ? 'narrow' : 'base'}
|
||||
className={
|
||||
isRevokeConfirmOpen ? 'alert-dialog delete-dialog' : 'edit-key-modal'
|
||||
isRevokeConfirmOpen ? 'alert-dialog sa-delete-dialog' : 'edit-key-modal'
|
||||
}
|
||||
showCloseButton={!isRevokeConfirmOpen}
|
||||
disableOutsideClick={isErrorModalVisible}
|
||||
footer={
|
||||
isRevokeConfirmOpen ? (
|
||||
<RevokeKeyFooter
|
||||
isRevoking={isRevoking}
|
||||
onCancel={(): void => setIsRevokeConfirmOpen(false)}
|
||||
onConfirm={handleRevoke}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{isRevokeConfirmOpen ? (
|
||||
<RevokeKeyContent
|
||||
isRevoking={isRevoking}
|
||||
onCancel={(): void => setIsRevokeConfirmOpen(false)}
|
||||
onConfirm={handleRevoke}
|
||||
/>
|
||||
<>
|
||||
Revoking this key will permanently invalidate it. Any systems using this
|
||||
key will lose access immediately.
|
||||
</>
|
||||
) : (
|
||||
<EditKeyForm
|
||||
register={register}
|
||||
|
||||
@@ -72,7 +72,6 @@ function OverviewTab({
|
||||
id="sa-name"
|
||||
value={localName}
|
||||
onChange={(e): void => onNameChange(e.target.value)}
|
||||
className="sa-drawer__input"
|
||||
placeholder="Enter name"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -17,39 +17,32 @@ import { parseAsString, useQueryState } from 'nuqs';
|
||||
import { useErrorModal } from 'providers/ErrorModalProvider';
|
||||
import APIError from 'types/api/error';
|
||||
|
||||
export interface RevokeKeyContentProps {
|
||||
export interface RevokeKeyFooterProps {
|
||||
isRevoking: boolean;
|
||||
onCancel: () => void;
|
||||
onConfirm: () => void;
|
||||
}
|
||||
|
||||
export function RevokeKeyContent({
|
||||
export function RevokeKeyFooter({
|
||||
isRevoking,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
}: RevokeKeyContentProps): JSX.Element {
|
||||
}: RevokeKeyFooterProps): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<p className="delete-dialog__body">
|
||||
Revoking this key will permanently invalidate it. Any systems using this key
|
||||
will lose access immediately.
|
||||
</p>
|
||||
<div className="delete-dialog__footer">
|
||||
<Button variant="solid" color="secondary" size="sm" onClick={onCancel}>
|
||||
<X size={12} />
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="destructive"
|
||||
size="sm"
|
||||
loading={isRevoking}
|
||||
onClick={onConfirm}
|
||||
>
|
||||
<Trash2 size={12} />
|
||||
Revoke Key
|
||||
</Button>
|
||||
</div>
|
||||
<Button variant="solid" color="secondary" onClick={onCancel}>
|
||||
<X size={12} />
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="destructive"
|
||||
loading={isRevoking}
|
||||
onClick={onConfirm}
|
||||
>
|
||||
<Trash2 size={12} />
|
||||
Revoke Key
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -112,15 +105,19 @@ function RevokeKeyModal(): JSX.Element {
|
||||
}}
|
||||
title={`Revoke ${keyName ?? 'key'}?`}
|
||||
width="narrow"
|
||||
className="alert-dialog delete-dialog"
|
||||
className="alert-dialog sa-delete-dialog"
|
||||
showCloseButton={false}
|
||||
disableOutsideClick={isErrorModalVisible}
|
||||
footer={
|
||||
<RevokeKeyFooter
|
||||
isRevoking={isRevoking}
|
||||
onCancel={handleCancel}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<RevokeKeyContent
|
||||
isRevoking={isRevoking}
|
||||
onCancel={handleCancel}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
Revoking this key will permanently invalidate it. Any systems using this key
|
||||
will lose access immediately.
|
||||
</DialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
color: var(--l1-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
&__tab {
|
||||
@@ -166,18 +168,6 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&__input {
|
||||
height: 32px;
|
||||
background: var(--l2-background);
|
||||
border-color: var(--l1-border);
|
||||
color: var(--l1-foreground);
|
||||
box-shadow: none;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--l3-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
&__input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -186,7 +176,7 @@
|
||||
padding: 0 var(--padding-2);
|
||||
border-radius: 2px;
|
||||
background: var(--l2-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
border: 1px solid var(--border);
|
||||
|
||||
&--disabled {
|
||||
cursor: not-allowed;
|
||||
@@ -195,8 +185,8 @@
|
||||
}
|
||||
|
||||
&__input-text {
|
||||
font-size: var(--font-size-sm);
|
||||
font-weight: var(--font-weight-normal);
|
||||
font-size: var(--paragraph-base-400-font-size);
|
||||
font-weight: var(--paragraph-base-400-font-weight);
|
||||
color: var(--foreground);
|
||||
line-height: var(--line-height-18);
|
||||
letter-spacing: -0.07px;
|
||||
|
||||
@@ -129,7 +129,7 @@ function ServiceAccountDrawer({
|
||||
useEffect(() => {
|
||||
if (account?.id) {
|
||||
setLocalName(account?.name ?? '');
|
||||
setKeysPage(1);
|
||||
void setKeysPage(1);
|
||||
}
|
||||
}, [account?.id, account?.name, setKeysPage]);
|
||||
|
||||
@@ -176,7 +176,7 @@ function ServiceAccountDrawer({
|
||||
}
|
||||
const maxPage = Math.max(1, Math.ceil(keys.length / PAGE_SIZE));
|
||||
if (keysPage > maxPage) {
|
||||
setKeysPage(maxPage);
|
||||
void setKeysPage(maxPage);
|
||||
}
|
||||
}, [keysLoading, keys.length, keysPage, setKeysPage]);
|
||||
|
||||
@@ -214,8 +214,8 @@ function ServiceAccountDrawer({
|
||||
data: { name: localName },
|
||||
});
|
||||
setSaveErrors((prev) => prev.filter((e) => e.context !== 'Name update'));
|
||||
refetchAccount();
|
||||
queryClient.invalidateQueries(getListServiceAccountsQueryKey());
|
||||
void refetchAccount();
|
||||
void queryClient.invalidateQueries(getListServiceAccountsQueryKey());
|
||||
} catch (err) {
|
||||
setSaveErrors((prev) =>
|
||||
prev.map((e) =>
|
||||
@@ -337,8 +337,8 @@ function ServiceAccountDrawer({
|
||||
onSuccess({ closeDrawer: false });
|
||||
}
|
||||
|
||||
refetchAccount();
|
||||
queryClient.invalidateQueries(getListServiceAccountsQueryKey());
|
||||
void refetchAccount();
|
||||
void queryClient.invalidateQueries(getListServiceAccountsQueryKey());
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
@@ -357,12 +357,12 @@ function ServiceAccountDrawer({
|
||||
]);
|
||||
|
||||
const handleClose = useCallback((): void => {
|
||||
setIsDeleteOpen(null);
|
||||
setIsAddKeyOpen(null);
|
||||
setSelectedAccountId(null);
|
||||
setActiveTab(null);
|
||||
setKeysPage(null);
|
||||
setEditKeyId(null);
|
||||
void setIsDeleteOpen(null);
|
||||
void setIsAddKeyOpen(null);
|
||||
void setSelectedAccountId(null);
|
||||
void setActiveTab(null);
|
||||
void setKeysPage(null);
|
||||
void setEditKeyId(null);
|
||||
setSaveErrors([]);
|
||||
}, [
|
||||
setSelectedAccountId,
|
||||
@@ -379,12 +379,13 @@ function ServiceAccountDrawer({
|
||||
<ToggleGroup
|
||||
type="single"
|
||||
value={activeTab}
|
||||
size="sm"
|
||||
onChange={(val): void => {
|
||||
if (val) {
|
||||
setActiveTab(val as ServiceAccountDrawerTab);
|
||||
void setActiveTab(val as ServiceAccountDrawerTab);
|
||||
if (val !== ServiceAccountDrawerTab.Keys) {
|
||||
setKeysPage(null);
|
||||
setEditKeyId(null);
|
||||
void setKeysPage(null);
|
||||
void setEditKeyId(null);
|
||||
}
|
||||
}
|
||||
}}
|
||||
@@ -415,7 +416,7 @@ function ServiceAccountDrawer({
|
||||
color="secondary"
|
||||
disabled={isDeleted}
|
||||
onClick={(): void => {
|
||||
setIsAddKeyOpen(true);
|
||||
void setIsAddKeyOpen(true);
|
||||
}}
|
||||
>
|
||||
<Plus size={12} />
|
||||
@@ -503,7 +504,7 @@ function ServiceAccountDrawer({
|
||||
variant="link"
|
||||
color="destructive"
|
||||
onClick={(): void => {
|
||||
setIsDeleteOpen(true);
|
||||
void setIsDeleteOpen(true);
|
||||
}}
|
||||
>
|
||||
<Trash2 size={12} />
|
||||
@@ -512,7 +513,7 @@ function ServiceAccountDrawer({
|
||||
)}
|
||||
{!isDeleted && (
|
||||
<div className="sa-drawer__footer-right">
|
||||
<Button variant="solid" color="secondary" onClick={handleClose}>
|
||||
<Button variant="outlined" color="secondary" onClick={handleClose}>
|
||||
<X size={14} />
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { css, FlattenSimpleInterpolation } from 'styled-components';
|
||||
|
||||
const cssProperty = (key: any, value: any): FlattenSimpleInterpolation =>
|
||||
key &&
|
||||
value &&
|
||||
css`
|
||||
${key}: ${value};
|
||||
`;
|
||||
|
||||
interface IFlexProps {
|
||||
flexDirection?: string; // Need to replace this with exact css props. Not able to find any :(
|
||||
flex?: number | string;
|
||||
}
|
||||
export const Flex = ({
|
||||
flexDirection,
|
||||
flex,
|
||||
}: IFlexProps): FlattenSimpleInterpolation => css`
|
||||
${cssProperty('flex-direction', flexDirection)}
|
||||
${cssProperty('flex', flex)}
|
||||
`;
|
||||
|
||||
interface IDisplayProps {
|
||||
display?: string;
|
||||
}
|
||||
export const Display = ({
|
||||
display,
|
||||
}: IDisplayProps): FlattenSimpleInterpolation => css`
|
||||
${cssProperty('display', display)}
|
||||
`;
|
||||
|
||||
interface ISpacingProps {
|
||||
margin?: string;
|
||||
padding?: string;
|
||||
}
|
||||
export const Spacing = ({
|
||||
margin,
|
||||
padding,
|
||||
}: ISpacingProps): FlattenSimpleInterpolation => css`
|
||||
${cssProperty('margin', margin)}
|
||||
${cssProperty('padding', padding)}
|
||||
`;
|
||||
@@ -1,5 +0,0 @@
|
||||
export type TabLabelProps = {
|
||||
isDisabled: boolean;
|
||||
label: string;
|
||||
tooltipText?: string;
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
import { memo } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
|
||||
import { TabLabelProps } from './TabLabel.interfaces';
|
||||
|
||||
function TabLabel({
|
||||
label,
|
||||
isDisabled,
|
||||
tooltipText,
|
||||
}: TabLabelProps): JSX.Element {
|
||||
const currentLabel = <span data-testid={`${label}`}>{label}</span>;
|
||||
|
||||
if (isDisabled) {
|
||||
return (
|
||||
<Tooltip
|
||||
trigger="hover"
|
||||
autoAdjustOverflow
|
||||
placement="top"
|
||||
title={tooltipText}
|
||||
>
|
||||
{currentLabel}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return currentLabel;
|
||||
}
|
||||
|
||||
export default memo(TabLabel);
|
||||
@@ -1,5 +0,0 @@
|
||||
.tab-title {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { Radio } from 'antd';
|
||||
import type { RadioChangeEvent } from 'antd/lib';
|
||||
import { History, Table } from 'lucide-react';
|
||||
|
||||
import { ALERT_TABS } from '../constants';
|
||||
|
||||
import './Tabs.styles.scss';
|
||||
|
||||
export function Tabs(): JSX.Element {
|
||||
const [selectedTab, setSelectedTab] = useState('overview');
|
||||
|
||||
const handleTabChange = (e: RadioChangeEvent): void => {
|
||||
setSelectedTab(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Radio.Group className="tabs" onChange={handleTabChange} value={selectedTab}>
|
||||
<Radio.Button
|
||||
className={
|
||||
selectedTab === ALERT_TABS.OVERVIEW ? 'selected_view tab' : 'tab'
|
||||
}
|
||||
value={ALERT_TABS.OVERVIEW}
|
||||
>
|
||||
<div className="tab-title">
|
||||
<Table size={14} />
|
||||
Overview
|
||||
</div>
|
||||
</Radio.Button>
|
||||
<Radio.Button
|
||||
className={selectedTab === ALERT_TABS.HISTORY ? 'selected_view tab' : 'tab'}
|
||||
value={ALERT_TABS.HISTORY}
|
||||
>
|
||||
<div className="tab-title">
|
||||
<History size={14} />
|
||||
History
|
||||
</div>
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@mixin flex-center {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tabs-and-filters {
|
||||
@include flex-center;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
.filters {
|
||||
@include flex-center;
|
||||
gap: 16px;
|
||||
.reset-button {
|
||||
@include flex-center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Filters } from 'components/AlertDetailsFilters/Filters';
|
||||
|
||||
import { Tabs } from './Tabs/Tabs';
|
||||
|
||||
import './TabsAndFilters.styles.scss';
|
||||
|
||||
function TabsAndFilters(): JSX.Element {
|
||||
return (
|
||||
<div className="tabs-and-filters">
|
||||
<Tabs />
|
||||
<Filters />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TabsAndFilters;
|
||||
@@ -1,5 +0,0 @@
|
||||
export const ALERT_TABS = {
|
||||
OVERVIEW: 'OVERVIEW',
|
||||
HISTORY: 'HISTORY',
|
||||
ACTIVITY: 'ACTIVITY',
|
||||
} as const;
|
||||
@@ -1,73 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { ColumnSizingState } from '@tanstack/react-table';
|
||||
import { Skeleton } from 'antd';
|
||||
|
||||
import { TableColumnDef } from './types';
|
||||
import { getColumnWidthStyle } from './utils';
|
||||
|
||||
import tableStyles from './TanStackTable.module.scss';
|
||||
import styles from './TanStackTableSkeleton.module.scss';
|
||||
|
||||
type TanStackTableSkeletonProps<TData> = {
|
||||
columns: TableColumnDef<TData>[];
|
||||
rowCount: number;
|
||||
isDarkMode: boolean;
|
||||
columnSizing?: ColumnSizingState;
|
||||
};
|
||||
|
||||
export function TanStackTableSkeleton<TData>({
|
||||
columns,
|
||||
rowCount,
|
||||
isDarkMode,
|
||||
columnSizing,
|
||||
}: TanStackTableSkeletonProps<TData>): JSX.Element {
|
||||
const rows = useMemo(
|
||||
() => Array.from({ length: rowCount }, (_, i) => i),
|
||||
[rowCount],
|
||||
);
|
||||
|
||||
return (
|
||||
<table className={tableStyles.tanStackTable}>
|
||||
<colgroup>
|
||||
{columns.map((column, index) => (
|
||||
<col
|
||||
key={column.id}
|
||||
style={getColumnWidthStyle(
|
||||
column,
|
||||
columnSizing?.[column.id],
|
||||
index === columns.length - 1,
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
{columns.map((column) => (
|
||||
<th
|
||||
key={column.id}
|
||||
className={tableStyles.tableHeaderCell}
|
||||
data-dark-mode={isDarkMode}
|
||||
>
|
||||
{typeof column.header === 'function' ? (
|
||||
<Skeleton.Input active size="small" className={styles.headerSkeleton} />
|
||||
) : (
|
||||
column.header
|
||||
)}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((rowIndex) => (
|
||||
<tr key={rowIndex} className={tableStyles.tableRow}>
|
||||
{columns.map((column) => (
|
||||
<td key={column.id} className={tableStyles.tableCell}>
|
||||
<Skeleton.Input active size="small" className={styles.cellSkeleton} />
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface TextContainerProps {
|
||||
noButtonMargin?: boolean;
|
||||
}
|
||||
|
||||
export const TextContainer = styled.div<TextContainerProps>`
|
||||
display: flex;
|
||||
|
||||
> button {
|
||||
margin-left: ${({ noButtonMargin }): string =>
|
||||
noButtonMargin ? '0' : '0.5rem'}
|
||||
`;
|
||||
@@ -1,42 +0,0 @@
|
||||
import { ReactChild } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card, Space, Typography } from 'antd';
|
||||
|
||||
import signozBrandLogoUrl from '@/assets/Logos/signoz-brand-logo.svg';
|
||||
|
||||
import { Container, LeftContainer, Logo } from './styles';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
function WelcomeLeftContainer({
|
||||
version,
|
||||
children,
|
||||
}: WelcomeLeftContainerProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<LeftContainer direction="vertical">
|
||||
<Space align="center">
|
||||
<Logo src={signozBrandLogoUrl} alt="logo" />
|
||||
<Title style={{ fontSize: '46px', margin: 0 }}>SigNoz</Title>
|
||||
</Space>
|
||||
<Typography>{t('monitor_signup')}</Typography>
|
||||
<Card
|
||||
style={{ width: 'max-content' }}
|
||||
bodyStyle={{ padding: '1px 8px', width: '100%' }}
|
||||
>
|
||||
SigNoz {version}
|
||||
</Card>
|
||||
</LeftContainer>
|
||||
{children}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
interface WelcomeLeftContainerProps {
|
||||
version: string;
|
||||
children: ReactChild;
|
||||
}
|
||||
|
||||
export default WelcomeLeftContainer;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { Space } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const LeftContainer = styled(Space)`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
export const Logo = styled.img`
|
||||
width: 60px;
|
||||
`;
|
||||
|
||||
export const Container = styled.div`
|
||||
&&& {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
|
||||
max-width: 1024px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
`;
|
||||
@@ -1,9 +0,0 @@
|
||||
import {
|
||||
AlertRuleTimelineTableResponse,
|
||||
AlertRuleTimelineTableResponsePayload,
|
||||
} from 'types/api/alerts/def';
|
||||
|
||||
export type TimelineTableProps = {
|
||||
timelineData: AlertRuleTimelineTableResponse[];
|
||||
totalItems: AlertRuleTimelineTableResponsePayload['data']['total'];
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
// setting to 25 hours because we want to display the horizontal graph when the user selects 'Last 1 day' from date and time selector
|
||||
export const HORIZONTAL_GRAPH_HOURS_THRESHOLD = 25;
|
||||
@@ -1,42 +0,0 @@
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
|
||||
import noDataUrl from '@/assets/Icons/no-data.svg';
|
||||
|
||||
import EndPointsDropDown from './EndPointsDropDown';
|
||||
|
||||
function EndPointDetailsZeroState({
|
||||
setSelectedEndPointName,
|
||||
endPointDropDownDataQuery,
|
||||
}: {
|
||||
setSelectedEndPointName: (endPointName: string) => void;
|
||||
endPointDropDownDataQuery: UseQueryResult<SuccessResponse<any>>;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<div className="end-point-details-zero-state-wrapper">
|
||||
<div className="end-point-details-zero-state-content">
|
||||
<img
|
||||
src={noDataUrl}
|
||||
alt="no-data"
|
||||
width={32}
|
||||
height={32}
|
||||
className="end-point-details-zero-state-icon"
|
||||
/>
|
||||
<div className="end-point-details-zero-state-content-wrapper">
|
||||
<div className="end-point-details-zero-state-text-content">
|
||||
<div className="title">No endpoint selected yet</div>
|
||||
<div className="description">Select an endpoint to see the details</div>
|
||||
</div>
|
||||
<EndPointsDropDown
|
||||
setSelectedEndPointName={setSelectedEndPointName}
|
||||
endPointDropDownDataQuery={endPointDropDownDataQuery}
|
||||
parentContainerDiv=".end-point-details-zero-state-wrapper"
|
||||
dropdownStyle={{ width: '60%' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default EndPointDetailsZeroState;
|
||||
@@ -1,136 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useQueries } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { Spin, Table } from 'antd';
|
||||
import type { ColumnType } from 'antd/lib/table';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { ENTITY_VERSION_V4 } from 'constants/app';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import {
|
||||
createFiltersForSelectedRowData,
|
||||
EndPointsTableRowData,
|
||||
formatEndPointsDataForTable,
|
||||
getEndPointsColumnsConfig,
|
||||
getEndPointsQueryPayload,
|
||||
} from 'container/ApiMonitoring/utils';
|
||||
import LoadingContainer from 'container/InfraMonitoringK8s/LoadingContainer';
|
||||
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { SuccessResponse } from 'types/api';
|
||||
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
|
||||
import { OrderByPayload } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { VIEW_TYPES, VIEWS } from '../constants';
|
||||
|
||||
function ExpandedRow({
|
||||
domainName,
|
||||
selectedRowData,
|
||||
setSelectedEndPointName,
|
||||
setSelectedView,
|
||||
orderBy,
|
||||
}: {
|
||||
domainName: string;
|
||||
selectedRowData: EndPointsTableRowData;
|
||||
setSelectedEndPointName: (name: string) => void;
|
||||
setSelectedView: (view: VIEWS) => void;
|
||||
orderBy: OrderByPayload | null;
|
||||
}): JSX.Element {
|
||||
const nestedColumns = useMemo(() => getEndPointsColumnsConfig(false, []), []);
|
||||
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
|
||||
(state) => state.globalTime,
|
||||
);
|
||||
const groupedByRowDataQueryPayload = useMemo(() => {
|
||||
if (!selectedRowData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const filters = createFiltersForSelectedRowData(selectedRowData);
|
||||
|
||||
const baseQueryPayload = getEndPointsQueryPayload(
|
||||
[],
|
||||
domainName,
|
||||
Math.floor(minTime / 1e9),
|
||||
Math.floor(maxTime / 1e9),
|
||||
);
|
||||
|
||||
return baseQueryPayload.map((currentQueryPayload) => ({
|
||||
...currentQueryPayload,
|
||||
query: {
|
||||
...currentQueryPayload.query,
|
||||
builder: {
|
||||
...currentQueryPayload.query.builder,
|
||||
queryData: currentQueryPayload.query.builder.queryData.map(
|
||||
(queryData) => ({
|
||||
...queryData,
|
||||
filters: {
|
||||
items: [...(queryData.filters?.items || []), ...(filters?.items || [])],
|
||||
op: 'AND',
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
},
|
||||
}));
|
||||
}, [domainName, minTime, maxTime, selectedRowData]);
|
||||
|
||||
const groupedByRowQueries = useQueries(
|
||||
groupedByRowDataQueryPayload
|
||||
? groupedByRowDataQueryPayload.map((payload) => ({
|
||||
queryKey: [
|
||||
`${REACT_QUERY_KEY.GET_NESTED_ENDPOINTS_LIST}-${domainName}-${selectedRowData?.key}`,
|
||||
payload,
|
||||
ENTITY_VERSION_V4,
|
||||
selectedRowData?.key,
|
||||
],
|
||||
queryFn: (): Promise<SuccessResponse<MetricRangePayloadProps>> =>
|
||||
GetMetricQueryRange(payload, ENTITY_VERSION_V4),
|
||||
enabled: !!payload && !!selectedRowData,
|
||||
}))
|
||||
: [],
|
||||
);
|
||||
|
||||
const groupedByRowQuery = groupedByRowQueries[0];
|
||||
return (
|
||||
<div className="expanded-table-container">
|
||||
{groupedByRowQuery?.isFetching || groupedByRowQuery?.isLoading ? (
|
||||
<LoadingContainer />
|
||||
) : (
|
||||
<div className="expanded-table">
|
||||
<Table
|
||||
columns={nestedColumns as ColumnType<EndPointsTableRowData>[]}
|
||||
dataSource={
|
||||
groupedByRowQuery?.data
|
||||
? formatEndPointsDataForTable(
|
||||
groupedByRowQuery.data?.payload.data.result[0].table?.rows,
|
||||
[],
|
||||
orderBy,
|
||||
)
|
||||
: []
|
||||
}
|
||||
pagination={false}
|
||||
scroll={{ x: true }}
|
||||
tableLayout="fixed"
|
||||
showHeader={false}
|
||||
loading={{
|
||||
spinning: groupedByRowQuery?.isFetching || groupedByRowQuery?.isLoading,
|
||||
indicator: <Spin indicator={<LoadingOutlined size={14} spin />} />,
|
||||
}}
|
||||
onRow={(record): { onClick: () => void; className: string } => ({
|
||||
onClick: (): void => {
|
||||
setSelectedEndPointName(record.endpointName);
|
||||
setSelectedView(VIEW_TYPES.ENDPOINT_STATS);
|
||||
logEvent('API Monitoring: Endpoint name row clicked', {});
|
||||
},
|
||||
className: 'expanded-clickable-row',
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExpandedRow;
|
||||
@@ -1,33 +0,0 @@
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
children: JSX.Element;
|
||||
}
|
||||
|
||||
class ErrorLink extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { hasError: false };
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(): State {
|
||||
return { hasError: true };
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
const { children } = this.props;
|
||||
const { hasError } = this.state;
|
||||
|
||||
if (hasError) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
export default ErrorLink;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
function LinkContainer({ children, href }: LinkContainerProps): JSX.Element {
|
||||
const isInternalLink = href.startsWith('/');
|
||||
|
||||
if (isInternalLink) {
|
||||
return <Link to={href}>{children}</Link>;
|
||||
}
|
||||
|
||||
return (
|
||||
<a rel="noreferrer" target="_blank" href={href}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
interface LinkContainerProps {
|
||||
children: ReactNode;
|
||||
href: string;
|
||||
}
|
||||
|
||||
export default LinkContainer;
|
||||
@@ -1,49 +0,0 @@
|
||||
import { lazy, Suspense, useMemo } from 'react';
|
||||
import { Menu, Space } from 'antd';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { ConfigProps } from 'types/api/dynamicConfigs/getDynamicConfigs';
|
||||
import { lazyRetry } from 'utils/lazyWithRetries';
|
||||
|
||||
import ErrorLink from './ErrorLink';
|
||||
import LinkContainer from './Link';
|
||||
|
||||
function HelpToolTip({ config }: HelpToolTipProps): JSX.Element {
|
||||
const sortedConfig = useMemo(
|
||||
() => config.components.sort((a, b) => a.position - b.position),
|
||||
[config.components],
|
||||
);
|
||||
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const items = sortedConfig.map((item) => {
|
||||
const iconName = `${isDarkMode ? item.darkIcon : item.lightIcon}`;
|
||||
|
||||
const Component = lazy(() =>
|
||||
lazyRetry(() => import(`@ant-design/icons/es/icons/${iconName}.js`)),
|
||||
);
|
||||
return {
|
||||
key: item.text + item.href,
|
||||
label: (
|
||||
<ErrorLink key={item.text + item.href}>
|
||||
<Suspense fallback={<Spinner height="5vh" />}>
|
||||
<LinkContainer href={item.href}>
|
||||
<Space size="small" align="start">
|
||||
<Component />
|
||||
{item.text}
|
||||
</Space>
|
||||
</LinkContainer>
|
||||
</Suspense>
|
||||
</ErrorLink>
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
return <Menu items={items} />;
|
||||
}
|
||||
|
||||
interface HelpToolTipProps {
|
||||
config: ConfigProps;
|
||||
}
|
||||
|
||||
export default HelpToolTip;
|
||||
@@ -1,76 +0,0 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import {
|
||||
CaretDownFilled,
|
||||
CaretUpFilled,
|
||||
QuestionCircleFilled,
|
||||
QuestionCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Space } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { ConfigProps } from 'types/api/dynamicConfigs/getDynamicConfigs';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import HelpToolTip from './Config';
|
||||
import { ConfigDropdown } from './styles';
|
||||
|
||||
function DynamicConfigDropdown({
|
||||
frontendId,
|
||||
}: DynamicConfigDropdownProps): JSX.Element {
|
||||
const { configs } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const [isHelpDropDownOpen, setIsHelpDropDownOpen] = useState<boolean>(false);
|
||||
|
||||
const config = useMemo(
|
||||
() =>
|
||||
Object.values(configs).find(
|
||||
(config) => config.frontendPositionId === frontendId,
|
||||
),
|
||||
[frontendId, configs],
|
||||
);
|
||||
|
||||
const onToggleHandler = (): void => {
|
||||
setIsHelpDropDownOpen(!isHelpDropDownOpen);
|
||||
};
|
||||
|
||||
const menu = useMemo(
|
||||
() => ({
|
||||
items: [
|
||||
{
|
||||
key: '1',
|
||||
label: <HelpToolTip config={config as ConfigProps} />,
|
||||
},
|
||||
],
|
||||
}),
|
||||
[config],
|
||||
);
|
||||
|
||||
if (!config) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
const Icon = isDarkMode ? QuestionCircleOutlined : QuestionCircleFilled;
|
||||
const DropDownIcon = isHelpDropDownOpen ? CaretUpFilled : CaretDownFilled;
|
||||
|
||||
return (
|
||||
<ConfigDropdown
|
||||
onOpenChange={onToggleHandler}
|
||||
trigger={['click']}
|
||||
menu={menu}
|
||||
open={isHelpDropDownOpen}
|
||||
>
|
||||
<Space align="center">
|
||||
<Icon style={{ fontSize: 26, color: 'white', paddingTop: 26 }} />
|
||||
<DropDownIcon style={{ color: 'white' }} />
|
||||
</Space>
|
||||
</ConfigDropdown>
|
||||
);
|
||||
}
|
||||
|
||||
interface DynamicConfigDropdownProps {
|
||||
frontendId: string;
|
||||
}
|
||||
|
||||
export default DynamicConfigDropdown;
|
||||
@@ -1,6 +0,0 @@
|
||||
import { Dropdown } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const ConfigDropdown = styled(Dropdown)`
|
||||
cursor: pointer;
|
||||
`;
|
||||
@@ -1,3 +0,0 @@
|
||||
import EvaluationSettings from './EvaluationSettings';
|
||||
|
||||
export default EvaluationSettings;
|
||||
@@ -78,6 +78,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-10);
|
||||
padding-left: 18px;
|
||||
}
|
||||
|
||||
.custom-domain-card-meta-row.workspace-name-hidden {
|
||||
@@ -124,30 +125,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.workspace-url-trigger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-3);
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
color: var(--l1-foreground);
|
||||
font-size: var(--font-size-xs);
|
||||
line-height: var(--line-height-18);
|
||||
letter-spacing: -0.06px;
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
svg {
|
||||
flex-shrink: 0;
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.workspace-url-dropdown {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--l1-border);
|
||||
|
||||
@@ -204,6 +204,7 @@ export default function CustomDomainSettings(): JSX.Element {
|
||||
>
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
disabled={isFetchingHosts}
|
||||
dropdownRender={(): JSX.Element => (
|
||||
<div className="workspace-url-dropdown">
|
||||
<span className="workspace-url-dropdown-header">
|
||||
@@ -239,12 +240,7 @@ export default function CustomDomainSettings(): JSX.Element {
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
className="workspace-url-trigger"
|
||||
disabled={isFetchingHosts}
|
||||
variant="link"
|
||||
color="none"
|
||||
>
|
||||
<Button variant="link" color="none">
|
||||
<Link2 size={12} />
|
||||
<span>{stripProtocol(activeHost?.url ?? '')}</span>
|
||||
<ChevronDown size={12} />
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import { ChangeEvent, Dispatch, SetStateAction, useCallback } from 'react';
|
||||
import Input from 'components/Input';
|
||||
|
||||
function DashboardName({ setName, name }: DashboardNameProps): JSX.Element {
|
||||
const onChangeHandler = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
setName(e.target.value);
|
||||
},
|
||||
[setName],
|
||||
);
|
||||
|
||||
return (
|
||||
<Input
|
||||
size="middle"
|
||||
placeholder="Title"
|
||||
value={name}
|
||||
onChangeHandler={onChangeHandler}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
interface DashboardNameProps {
|
||||
name: string;
|
||||
setName: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export default DashboardName;
|
||||
@@ -1,100 +0,0 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import { CopyFilled, DownloadOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal } from 'antd';
|
||||
import Editor from 'components/Editor';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { DashboardData } from 'types/api/dashboard/getAll';
|
||||
|
||||
import { downloadObjectAsJson } from './utils';
|
||||
|
||||
function ShareModal({
|
||||
isJSONModalVisible,
|
||||
onToggleHandler,
|
||||
selectedData,
|
||||
}: ShareModalProps): JSX.Element {
|
||||
const getParsedValue = (): string => JSON.stringify(selectedData, null, 2);
|
||||
|
||||
const [jsonValue, setJSONValue] = useState<string>(getParsedValue());
|
||||
const { t } = useTranslation(['dashboard', 'common']);
|
||||
const [state, setCopy] = useCopyToClipboard();
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
useEffect(() => {
|
||||
if (state.error) {
|
||||
notifications.error({
|
||||
message: t('something_went_wrong', {
|
||||
ns: 'common',
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
if (state.value) {
|
||||
notifications.success({
|
||||
message: t('success', {
|
||||
ns: 'common',
|
||||
}),
|
||||
});
|
||||
}
|
||||
}, [state.error, state.value, t, notifications]);
|
||||
|
||||
const GetFooterComponent = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
style={{
|
||||
marginTop: '16px',
|
||||
}}
|
||||
onClick={(): void => setCopy(jsonValue)}
|
||||
type="primary"
|
||||
size="small"
|
||||
>
|
||||
<CopyFilled /> {t('copy_to_clipboard')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={(): void => {
|
||||
downloadObjectAsJson(selectedData, selectedData.title);
|
||||
}}
|
||||
>
|
||||
<DownloadOutlined /> {t('download_json')}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}, [jsonValue, selectedData, setCopy, t]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={isJSONModalVisible}
|
||||
onCancel={(): void => {
|
||||
onToggleHandler();
|
||||
}}
|
||||
width="80vw"
|
||||
centered
|
||||
title={t('share', {
|
||||
ns: 'common',
|
||||
})}
|
||||
okText={t('download_json')}
|
||||
cancelText={t('cancel')}
|
||||
destroyOnClose
|
||||
footer={GetFooterComponent}
|
||||
>
|
||||
<Editor
|
||||
height="70vh"
|
||||
onChange={(value): void => setJSONValue(value)}
|
||||
value={jsonValue}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
interface ShareModalProps {
|
||||
isJSONModalVisible: boolean;
|
||||
onToggleHandler: VoidFunction;
|
||||
selectedData: DashboardData;
|
||||
}
|
||||
|
||||
export default ShareModal;
|
||||
@@ -1,35 +0,0 @@
|
||||
import { ChangeEvent, Dispatch, SetStateAction, useCallback } from 'react';
|
||||
import { Input } from 'antd';
|
||||
|
||||
import { Container } from './styles';
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
function Description({
|
||||
description,
|
||||
setDescription,
|
||||
}: DescriptionProps): JSX.Element {
|
||||
const onChangeHandler = useCallback(
|
||||
(e: ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setDescription(e.target.value);
|
||||
},
|
||||
[setDescription],
|
||||
);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<TextArea
|
||||
placeholder="Description of the dashboard"
|
||||
onChange={onChangeHandler}
|
||||
value={description}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
interface DescriptionProps {
|
||||
description: string;
|
||||
setDescription: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export default Description;
|
||||
@@ -1,5 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Container = styled.div`
|
||||
margin-top: 1rem;
|
||||
`;
|
||||
@@ -104,7 +104,12 @@ export const usePanelContextMenu = ({
|
||||
}
|
||||
|
||||
if (data && data?.record?.queryName) {
|
||||
onClick(data.coord, { ...data.record, label: data.label, timeRange });
|
||||
onClick(data.coord, {
|
||||
...data.record,
|
||||
label: data.label,
|
||||
seriesColor: data.seriesColor,
|
||||
timeRange,
|
||||
});
|
||||
}
|
||||
},
|
||||
[onClick, queryResponse],
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
.download-logs-popover {
|
||||
.ant-popover-inner {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: linear-gradient(
|
||||
139deg,
|
||||
color-mix(in srgb, var(--card) 80%, transparent) 0%,
|
||||
color-mix(in srgb, var(--card) 90%, transparent) 98.68%
|
||||
);
|
||||
box-shadow: 4px 10px 16px 2px rgba(0, 0, 0, 0.2);
|
||||
backdrop-filter: blur(20px);
|
||||
padding: 12px 18px 12px 14px;
|
||||
|
||||
.download-logs-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
|
||||
.action-btns {
|
||||
padding: 4px 0px !important;
|
||||
width: 159px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--l2-foreground);
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
letter-spacing: 0.14px;
|
||||
gap: 6px;
|
||||
|
||||
.ant-btn-icon {
|
||||
margin-inline-end: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.action-btns:hover {
|
||||
&.ant-btn-text {
|
||||
background-color: color-mix(
|
||||
in srgb,
|
||||
var(--bg-robin-200) 4%,
|
||||
transparent
|
||||
) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.export-heading {
|
||||
color: var(--muted-foreground);
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 18px; /* 163.636% */
|
||||
letter-spacing: 0.88px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Popover, Typography } from 'antd';
|
||||
import { FileDigit, FileDown, Sheet } from 'lucide-react';
|
||||
import { unparse } from 'papaparse';
|
||||
|
||||
import { DownloadProps } from './DownloadV2.types';
|
||||
|
||||
import './DownloadV2.styles.scss';
|
||||
|
||||
function Download({ data, isLoading, fileName }: DownloadProps): JSX.Element {
|
||||
const [isDownloading, setIsDownloading] = useState(false);
|
||||
|
||||
const downloadExcelFile = async (): Promise<void> => {
|
||||
setIsDownloading(true);
|
||||
|
||||
try {
|
||||
const headers = Object.keys(Object.assign({}, ...data)).map((item) => {
|
||||
const updatedTitle = item
|
||||
.split('_')
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ');
|
||||
return {
|
||||
title: updatedTitle,
|
||||
dataIndex: item,
|
||||
};
|
||||
});
|
||||
const excelLib = await import('antd-table-saveas-excel');
|
||||
const excel = new excelLib.Excel();
|
||||
excel
|
||||
.addSheet(fileName)
|
||||
.addColumns(headers)
|
||||
.addDataSource(data, {
|
||||
str2Percent: true,
|
||||
})
|
||||
.saveAs(`${fileName}.xlsx`);
|
||||
} finally {
|
||||
setIsDownloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const downloadCsvFile = (): void => {
|
||||
const csv = unparse(data);
|
||||
const csvBlob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
||||
const csvUrl = URL.createObjectURL(csvBlob);
|
||||
const downloadLink = document.createElement('a');
|
||||
downloadLink.href = csvUrl;
|
||||
downloadLink.download = `${fileName}.csv`;
|
||||
downloadLink.click();
|
||||
downloadLink.remove();
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
trigger={['click']}
|
||||
placement="bottomRight"
|
||||
rootClassName="download-logs-popover"
|
||||
arrow={false}
|
||||
content={
|
||||
<div className="download-logs-content">
|
||||
<Typography.Text className="export-heading">Export As</Typography.Text>
|
||||
<Button
|
||||
icon={<Sheet size={14} />}
|
||||
type="text"
|
||||
onClick={downloadExcelFile}
|
||||
className="action-btns"
|
||||
loading={isDownloading}
|
||||
>
|
||||
Excel (.xlsx)
|
||||
</Button>
|
||||
<Button
|
||||
icon={<FileDigit size={14} />}
|
||||
type="text"
|
||||
onClick={downloadCsvFile}
|
||||
className="action-btns"
|
||||
>
|
||||
CSV
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Button
|
||||
className="periscope-btn ghost"
|
||||
loading={isLoading}
|
||||
icon={<FileDown size={14} />}
|
||||
/>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
Download.defaultProps = {
|
||||
isLoading: undefined,
|
||||
};
|
||||
|
||||
export default Download;
|
||||
@@ -1,10 +0,0 @@
|
||||
export type DownloadOptions = {
|
||||
isDownloadEnabled: boolean;
|
||||
fileName: string;
|
||||
};
|
||||
|
||||
export type DownloadProps = {
|
||||
data: Record<string, string>[];
|
||||
isLoading?: boolean;
|
||||
fileName: string;
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const ButtonContainer = styled.div`
|
||||
&&& {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
margin-top: 2rem;
|
||||
}
|
||||
`;
|
||||
@@ -1,8 +0,0 @@
|
||||
import { OptionsMenuConfig } from 'container/OptionsMenu/types';
|
||||
|
||||
export type ExplorerControlPanelProps = {
|
||||
selectedOptionFormat: string;
|
||||
isShowPageSize: boolean;
|
||||
isLoading: boolean;
|
||||
optionsMenuConfig?: OptionsMenuConfig;
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
import { Col, Row } from 'antd';
|
||||
import OptionsMenu from 'container/OptionsMenu';
|
||||
import PageSizeSelect from 'container/PageSizeSelect';
|
||||
|
||||
import { ExplorerControlPanelProps } from './ExplorerControlPanel.interfaces';
|
||||
import { ContainerStyled } from './styles';
|
||||
|
||||
function ExplorerControlPanel({
|
||||
selectedOptionFormat,
|
||||
isLoading,
|
||||
isShowPageSize,
|
||||
optionsMenuConfig,
|
||||
}: ExplorerControlPanelProps): JSX.Element {
|
||||
return (
|
||||
<ContainerStyled>
|
||||
<Row justify="end" gutter={30}>
|
||||
{optionsMenuConfig && (
|
||||
<Col>
|
||||
<OptionsMenu
|
||||
selectedOptionFormat={selectedOptionFormat}
|
||||
config={optionsMenuConfig}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
<Col>
|
||||
<PageSizeSelect isLoading={isLoading} isShow={isShowPageSize} />
|
||||
</Col>
|
||||
</Row>
|
||||
</ContainerStyled>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExplorerControlPanel;
|
||||
@@ -1,5 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const ContainerStyled = styled.div`
|
||||
margin-bottom: 0.3rem;
|
||||
`;
|
||||
@@ -1,61 +0,0 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Form, Input, Select } from 'antd';
|
||||
import { LabelFilterStatement } from 'container/CreateAlertChannels/config';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
// LabelFilterForm supports filters or matchers on alert notifications
|
||||
// presently un-used but will be introduced to the channel creation at some
|
||||
// point
|
||||
function LabelFilterForm({ setFilter }: LabelFilterProps): JSX.Element {
|
||||
return (
|
||||
<Form.Item name="label_filter" label="Notify When (Optional)">
|
||||
<Input.Group compact>
|
||||
<Select
|
||||
defaultValue="Severity"
|
||||
style={{ width: '15%' }}
|
||||
onChange={(event): void => {
|
||||
setFilter((value) => {
|
||||
const first: LabelFilterStatement = value[0] as LabelFilterStatement;
|
||||
first.name = event;
|
||||
return [first];
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Option value="severity">Severity</Option>
|
||||
<Option value="service">Service</Option>
|
||||
</Select>
|
||||
<Select
|
||||
defaultValue="="
|
||||
onChange={(event): void => {
|
||||
setFilter((value) => {
|
||||
const first: LabelFilterStatement = value[0] as LabelFilterStatement;
|
||||
first.comparator = event;
|
||||
return [first];
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Option value="=">=</Option>
|
||||
<Option value="!=">!=</Option>
|
||||
</Select>
|
||||
<Input
|
||||
style={{ width: '20%' }}
|
||||
placeholder="enter a text here"
|
||||
onChange={(event): void => {
|
||||
setFilter((value) => {
|
||||
const first: LabelFilterStatement = value[0] as LabelFilterStatement;
|
||||
first.value = event.target.value;
|
||||
return [first];
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Input.Group>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
export interface LabelFilterProps {
|
||||
setFilter: Dispatch<SetStateAction<Partial<Array<LabelFilterStatement>>>>;
|
||||
}
|
||||
|
||||
export default LabelFilterForm;
|
||||
@@ -1,164 +0,0 @@
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Col, Row, Typography } from 'antd';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
|
||||
import {
|
||||
StyledList,
|
||||
StyledListItem,
|
||||
StyledMainContainer,
|
||||
StyledTopic,
|
||||
} from './styles';
|
||||
|
||||
function UserGuide({ queryType }: UserGuideProps): JSX.Element {
|
||||
// init namespace for translations
|
||||
const { t } = useTranslation('alerts');
|
||||
|
||||
const renderStep1QB = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_qb_step1')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_qb_step1a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step1b')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step1c')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step1d')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
const renderStep2QB = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_qb_step2')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_qb_step2a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step2b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderStep3QB = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_qb_step3')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_qb_step3a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_qb_step3b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderGuideForQB = (): JSX.Element => (
|
||||
<>
|
||||
{renderStep1QB()}
|
||||
{renderStep2QB()}
|
||||
{renderStep3QB()}
|
||||
</>
|
||||
);
|
||||
const renderStep1PQL = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_pql_step1')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_pql_step1a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_pql_step1b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
const renderStep2PQL = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_pql_step2')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_pql_step2a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_pql_step2b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderStep3PQL = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_pql_step3')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_pql_step3a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_pql_step3b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderGuideForPQL = (): JSX.Element => (
|
||||
<>
|
||||
{renderStep1PQL()}
|
||||
{renderStep2PQL()}
|
||||
{renderStep3PQL()}
|
||||
</>
|
||||
);
|
||||
|
||||
const renderStep1CH = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_ch_step1')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>
|
||||
<Trans
|
||||
i18nKey="user_guide_ch_step1a"
|
||||
t={t}
|
||||
components={[
|
||||
<a
|
||||
key={1}
|
||||
target="_blank"
|
||||
href=" https://signoz.io/docs/tutorial/writing-clickhouse-queries-in-dashboard/?utm_source=frontend&utm_medium=product&utm_id=alerts</>"
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_ch_step1b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
const renderStep2CH = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_ch_step2')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_ch_step2a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_ch_step2b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderStep3CH = (): JSX.Element => (
|
||||
<>
|
||||
<StyledTopic>{t('user_guide_ch_step3')}</StyledTopic>
|
||||
<StyledList>
|
||||
<StyledListItem>{t('user_guide_ch_step3a')}</StyledListItem>
|
||||
<StyledListItem>{t('user_guide_ch_step3b')}</StyledListItem>
|
||||
</StyledList>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderGuideForCH = (): JSX.Element => (
|
||||
<>
|
||||
{renderStep1CH()}
|
||||
{renderStep2CH()}
|
||||
{renderStep3CH()}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<StyledMainContainer>
|
||||
<Row>
|
||||
<Col flex="auto">
|
||||
<Typography.Paragraph> {t('user_guide_headline')} </Typography.Paragraph>
|
||||
</Col>
|
||||
<Col flex="none">
|
||||
<TextToolTip
|
||||
text={t('user_tooltip_more_help')}
|
||||
url="https://signoz.io/docs/userguide/alerts-management/?utm_source=product&utm_medium=create-alert#creating-a-new-alert-in-signoz"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
{queryType === EQueryType.QUERY_BUILDER && renderGuideForQB()}
|
||||
{queryType === EQueryType.PROM && renderGuideForPQL()}
|
||||
{queryType === EQueryType.CLICKHOUSE && renderGuideForCH()}
|
||||
</StyledMainContainer>
|
||||
);
|
||||
}
|
||||
|
||||
interface UserGuideProps {
|
||||
queryType: EQueryType;
|
||||
}
|
||||
|
||||
export default UserGuide;
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Card, Typography } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledMainContainer = styled(Card)``;
|
||||
|
||||
export const StyledTopic = styled(Typography.Paragraph)`
|
||||
font-weight: 600;
|
||||
`;
|
||||
|
||||
export const StyledList = styled.ul`
|
||||
padding-left: 18px;
|
||||
`;
|
||||
|
||||
export const StyledListItem = styled.li`
|
||||
font-style: italic;
|
||||
padding-bottom: 0.5rem;
|
||||
`;
|
||||
@@ -1,158 +0,0 @@
|
||||
import { memo, useCallback, useEffect, useState } from 'react';
|
||||
import { Button, Input } from 'antd';
|
||||
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
|
||||
import { ResizeTable } from 'components/ResizeTable';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import {
|
||||
selectIsDashboardLocked,
|
||||
useDashboardStore,
|
||||
} from 'providers/Dashboard/store/useDashboardStore';
|
||||
|
||||
import { getGraphManagerTableColumns } from './TableRender/GraphManagerColumns';
|
||||
import { ExtendedChartDataset, GraphManagerProps } from './types';
|
||||
import {
|
||||
getDefaultTableDataSet,
|
||||
saveLegendEntriesToLocalStorage,
|
||||
} from './utils';
|
||||
|
||||
import './WidgetFullView.styles.scss';
|
||||
|
||||
function GraphManager({
|
||||
data,
|
||||
name,
|
||||
yAxisUnit,
|
||||
onToggleModelHandler,
|
||||
setGraphsVisibilityStates,
|
||||
graphsVisibilityStates = [], // not trimed
|
||||
lineChartRef,
|
||||
parentChartRef,
|
||||
options,
|
||||
}: GraphManagerProps): JSX.Element {
|
||||
const [tableDataSet, setTableDataSet] = useState<ExtendedChartDataset[]>(
|
||||
getDefaultTableDataSet(options, data),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setTableDataSet(getDefaultTableDataSet(options, data));
|
||||
}, [data, options]);
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
const isDashboardLocked = useDashboardStore(selectIsDashboardLocked);
|
||||
|
||||
const checkBoxOnChangeHandler = useCallback(
|
||||
(e: CheckboxChangeEvent, index: number): void => {
|
||||
const newStates = [...graphsVisibilityStates];
|
||||
newStates[index] = e.target.checked;
|
||||
lineChartRef?.current?.toggleGraph(index, e.target.checked);
|
||||
parentChartRef?.current?.toggleGraph(index, e.target.checked);
|
||||
setGraphsVisibilityStates([...newStates]);
|
||||
},
|
||||
[
|
||||
graphsVisibilityStates,
|
||||
lineChartRef,
|
||||
parentChartRef,
|
||||
setGraphsVisibilityStates,
|
||||
],
|
||||
);
|
||||
|
||||
const labelClickedHandler = useCallback(
|
||||
(labelIndex: number): void => {
|
||||
const newGraphVisibilityStates = Array<boolean>(data.length).fill(false);
|
||||
newGraphVisibilityStates[labelIndex] = true;
|
||||
|
||||
newGraphVisibilityStates.forEach((state, index) => {
|
||||
lineChartRef?.current?.toggleGraph(index, state);
|
||||
parentChartRef?.current?.toggleGraph(index, state);
|
||||
});
|
||||
setGraphsVisibilityStates(newGraphVisibilityStates);
|
||||
},
|
||||
[data.length, lineChartRef, parentChartRef, setGraphsVisibilityStates],
|
||||
);
|
||||
|
||||
const columns = getGraphManagerTableColumns({
|
||||
tableDataSet,
|
||||
checkBoxOnChangeHandler,
|
||||
graphVisibilityState: graphsVisibilityStates,
|
||||
labelClickedHandler,
|
||||
yAxisUnit,
|
||||
isGraphDisabled: isDashboardLocked,
|
||||
});
|
||||
|
||||
const filterHandler = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const value = event.target.value.toString().toLowerCase();
|
||||
const updatedDataSet = tableDataSet.map((item) => {
|
||||
if (item.label?.toLocaleLowerCase().includes(value)) {
|
||||
return { ...item, show: true };
|
||||
}
|
||||
return { ...item, show: false };
|
||||
});
|
||||
setTableDataSet(updatedDataSet);
|
||||
},
|
||||
[tableDataSet],
|
||||
);
|
||||
|
||||
const saveHandler = useCallback((): void => {
|
||||
saveLegendEntriesToLocalStorage({
|
||||
options,
|
||||
graphVisibilityState: graphsVisibilityStates || [],
|
||||
name,
|
||||
});
|
||||
notifications.success({
|
||||
message: 'The updated graphs & legends are saved',
|
||||
});
|
||||
if (onToggleModelHandler) {
|
||||
onToggleModelHandler();
|
||||
}
|
||||
}, [
|
||||
graphsVisibilityStates,
|
||||
name,
|
||||
notifications,
|
||||
onToggleModelHandler,
|
||||
options,
|
||||
]);
|
||||
|
||||
const dataSource = tableDataSet.filter(
|
||||
(item, index) => index !== 0 && item.show,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="graph-manager-container">
|
||||
<div className="graph-manager-header">
|
||||
<Input onChange={filterHandler} placeholder="Filter Series" />
|
||||
<div className="save-cancel-container">
|
||||
<span className="save-cancel-button">
|
||||
<Button type="default" onClick={onToggleModelHandler}>
|
||||
Cancel
|
||||
</Button>
|
||||
</span>
|
||||
<span className="save-cancel-button">
|
||||
<Button type="primary" onClick={saveHandler}>
|
||||
Save
|
||||
</Button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="legends-list-container">
|
||||
<ResizeTable
|
||||
columns={columns}
|
||||
dataSource={dataSource}
|
||||
rowKey="index"
|
||||
pagination={false}
|
||||
style={{
|
||||
maxHeight: 200,
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
GraphManager.defaultProps = {
|
||||
graphVisibilityStateHandler: undefined,
|
||||
};
|
||||
|
||||
export default memo(GraphManager);
|
||||
@@ -1,18 +0,0 @@
|
||||
import { TableColumnType as ColumnType } from 'antd';
|
||||
|
||||
import { DataSetProps } from '../types';
|
||||
import Label from './Label';
|
||||
|
||||
export const getLabel = (
|
||||
labelClickedHandler: (labelIndex: number) => void,
|
||||
disabled?: boolean,
|
||||
): ColumnType<DataSetProps> => ({
|
||||
render: (label: string, record): JSX.Element => (
|
||||
<Label
|
||||
label={label}
|
||||
labelIndex={record.index}
|
||||
labelClickedHandler={labelClickedHandler}
|
||||
disabled={disabled}
|
||||
/>
|
||||
),
|
||||
});
|
||||
@@ -1,85 +0,0 @@
|
||||
import { TableColumnType as ColumnType } from 'antd';
|
||||
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
|
||||
|
||||
import { ColumnsKeyAndDataIndex, ColumnsTitle } from '../contants';
|
||||
import { DataSetProps, ExtendedChartDataset } from '../types';
|
||||
import { getGraphManagerTableHeaderTitle } from '../utils';
|
||||
import CustomCheckBox from './CustomCheckBox';
|
||||
import { getLabel } from './GetLabel';
|
||||
|
||||
export const getGraphManagerTableColumns = ({
|
||||
tableDataSet,
|
||||
checkBoxOnChangeHandler,
|
||||
graphVisibilityState,
|
||||
labelClickedHandler,
|
||||
yAxisUnit,
|
||||
isGraphDisabled,
|
||||
}: GetGraphManagerTableColumnsProps): ColumnType<DataSetProps>[] => [
|
||||
{
|
||||
title: '',
|
||||
width: 50,
|
||||
dataIndex: ColumnsKeyAndDataIndex.Index,
|
||||
key: ColumnsKeyAndDataIndex.Index,
|
||||
render: (_: string, record: DataSetProps): JSX.Element => (
|
||||
<CustomCheckBox
|
||||
data={tableDataSet}
|
||||
index={record.index}
|
||||
checkBoxOnChangeHandler={checkBoxOnChangeHandler}
|
||||
graphVisibilityState={graphVisibilityState}
|
||||
disabled={isGraphDisabled}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: ColumnsTitle[ColumnsKeyAndDataIndex.Label],
|
||||
width: 300,
|
||||
dataIndex: ColumnsKeyAndDataIndex.Label,
|
||||
key: ColumnsKeyAndDataIndex.Label,
|
||||
...getLabel(labelClickedHandler, isGraphDisabled),
|
||||
},
|
||||
{
|
||||
title: getGraphManagerTableHeaderTitle(
|
||||
ColumnsTitle[ColumnsKeyAndDataIndex.Avg],
|
||||
yAxisUnit,
|
||||
),
|
||||
width: 90,
|
||||
dataIndex: ColumnsKeyAndDataIndex.Avg,
|
||||
key: ColumnsKeyAndDataIndex.Avg,
|
||||
},
|
||||
{
|
||||
title: getGraphManagerTableHeaderTitle(
|
||||
ColumnsTitle[ColumnsKeyAndDataIndex.Sum],
|
||||
yAxisUnit,
|
||||
),
|
||||
width: 90,
|
||||
dataIndex: ColumnsKeyAndDataIndex.Sum,
|
||||
key: ColumnsKeyAndDataIndex.Sum,
|
||||
},
|
||||
{
|
||||
title: getGraphManagerTableHeaderTitle(
|
||||
ColumnsTitle[ColumnsKeyAndDataIndex.Max],
|
||||
yAxisUnit,
|
||||
),
|
||||
width: 90,
|
||||
dataIndex: ColumnsKeyAndDataIndex.Max,
|
||||
key: ColumnsKeyAndDataIndex.Max,
|
||||
},
|
||||
{
|
||||
title: getGraphManagerTableHeaderTitle(
|
||||
ColumnsTitle[ColumnsKeyAndDataIndex.Min],
|
||||
yAxisUnit,
|
||||
),
|
||||
width: 90,
|
||||
dataIndex: ColumnsKeyAndDataIndex.Min,
|
||||
key: ColumnsKeyAndDataIndex.Min,
|
||||
},
|
||||
];
|
||||
|
||||
interface GetGraphManagerTableColumnsProps {
|
||||
tableDataSet: ExtendedChartDataset[];
|
||||
checkBoxOnChangeHandler: (e: CheckboxChangeEvent, index: number) => void;
|
||||
labelClickedHandler: (labelIndex: number) => void;
|
||||
graphVisibilityState: boolean[];
|
||||
yAxisUnit?: string;
|
||||
isGraphDisabled?: boolean;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Tooltip } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
|
||||
import { LabelContainer } from '../styles';
|
||||
import { LabelProps } from '../types';
|
||||
import { getAbbreviatedLabel } from '../utils';
|
||||
|
||||
function Label({
|
||||
labelClickedHandler,
|
||||
labelIndex,
|
||||
label,
|
||||
disabled = false,
|
||||
}: LabelProps): JSX.Element {
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const onClickHandler = (): void => {
|
||||
labelClickedHandler(labelIndex);
|
||||
};
|
||||
|
||||
return (
|
||||
<LabelContainer
|
||||
isDarkMode={isDarkMode}
|
||||
type="button"
|
||||
disabled={disabled}
|
||||
onClick={onClickHandler}
|
||||
>
|
||||
<Tooltip title={label} placement="topLeft">
|
||||
{getAbbreviatedLabel(label)}
|
||||
</Tooltip>
|
||||
</LabelContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default Label;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ChartData } from 'chart.js';
|
||||
|
||||
export const mockTestData: ChartData = {
|
||||
labels: ['test1', 'test2'],
|
||||
datasets: [
|
||||
{
|
||||
label: 'customer',
|
||||
data: [481.60377358490564, 730.0000000000002],
|
||||
},
|
||||
{
|
||||
label: 'demo-app',
|
||||
data: [4471.4285714285725],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
import { LegendEntryProps } from '../FullView/types';
|
||||
|
||||
export const mocklegendEntryResult: LegendEntryProps[] = [
|
||||
{
|
||||
label: 'customer',
|
||||
show: true,
|
||||
},
|
||||
{
|
||||
label: 'demo-app',
|
||||
show: false,
|
||||
},
|
||||
];
|
||||
@@ -1,3 +0,0 @@
|
||||
import { GridValueComponentProps } from './types';
|
||||
|
||||
export const GridValueConfig: Pick<GridValueComponentProps, 'title'> = {};
|
||||
@@ -1,3 +0,0 @@
|
||||
import Home from './Home';
|
||||
|
||||
export default Home;
|
||||
@@ -1,19 +0,0 @@
|
||||
.loading-host-metrics {
|
||||
padding: 24px 0;
|
||||
height: 600px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.loading-host-metrics-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
.loading-gif {
|
||||
height: 72px;
|
||||
margin-left: -24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Typography } from 'antd';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import loadingPlaneUrl from '@/assets/Icons/loading-plane.gif';
|
||||
|
||||
import './HostMetricsLoading.styles.scss';
|
||||
|
||||
export function HostMetricsLoading(): JSX.Element {
|
||||
const { t } = useTranslation('common');
|
||||
return (
|
||||
<div className="loading-host-metrics">
|
||||
<div className="loading-host-metrics-content">
|
||||
<img className="loading-gif" src={loadingPlaneUrl} alt="wait-icon" />
|
||||
|
||||
<Typography>
|
||||
{t('pending_data_placeholder', {
|
||||
dataSource: `host ${DataSource.METRICS}`,
|
||||
})}
|
||||
</Typography>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -37,10 +37,7 @@ import {
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
import { isCustomTimeRange, useGlobalTimeStore } from 'store/globalTime';
|
||||
import {
|
||||
getAutoRefreshQueryKey,
|
||||
NANO_SECOND_MULTIPLIER,
|
||||
} from 'store/globalTime/utils';
|
||||
import { NANO_SECOND_MULTIPLIER } from 'store/globalTime/utils';
|
||||
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import {
|
||||
IBuilderQuery,
|
||||
@@ -190,16 +187,19 @@ function K8sBaseDetails<T>({
|
||||
);
|
||||
|
||||
const selectedTime = useGlobalTimeStore((s) => s.selectedTime);
|
||||
const lastComputedMinMax = useGlobalTimeStore((s) => s.lastComputedMinMax);
|
||||
const getMinMaxTime = useGlobalTimeStore((s) => s.getMinMaxTime);
|
||||
const getAutoRefreshQueryKey = useGlobalTimeStore(
|
||||
(s) => s.getAutoRefreshQueryKey,
|
||||
);
|
||||
|
||||
const { startMs, endMs } = useMemo(() => {
|
||||
const { minTime: startNs, maxTime: endNs } = getMinMaxTime(selectedTime);
|
||||
|
||||
return {
|
||||
startMs: Math.floor(startNs / NANO_SECOND_MULTIPLIER),
|
||||
endMs: Math.floor(endNs / NANO_SECOND_MULTIPLIER),
|
||||
};
|
||||
}, [getMinMaxTime, selectedTime]);
|
||||
const { startMs, endMs } = useMemo(
|
||||
() => ({
|
||||
startMs: Math.floor(lastComputedMinMax.minTime / NANO_SECOND_MULTIPLIER),
|
||||
endMs: Math.floor(lastComputedMinMax.maxTime / NANO_SECOND_MULTIPLIER),
|
||||
}),
|
||||
[lastComputedMinMax],
|
||||
);
|
||||
|
||||
const [modalTimeRange, setModalTimeRange] = useState(() => ({
|
||||
startTime: startMs,
|
||||
@@ -246,7 +246,7 @@ function K8sBaseDetails<T>({
|
||||
`${queryKeyPrefix}EntityDetails`,
|
||||
selectedItem,
|
||||
),
|
||||
[queryKeyPrefix, selectedItem, selectedTime],
|
||||
[getAutoRefreshQueryKey, queryKeyPrefix, selectedItem, selectedTime],
|
||||
);
|
||||
|
||||
const {
|
||||
|
||||
@@ -16,10 +16,7 @@ import { InfraMonitoringEvents } from 'constants/events';
|
||||
import { ChevronDown, ChevronRight } from 'lucide-react';
|
||||
import { parseAsString, useQueryState } from 'nuqs';
|
||||
import { useGlobalTimeStore } from 'store/globalTime';
|
||||
import {
|
||||
getAutoRefreshQueryKey,
|
||||
NANO_SECOND_MULTIPLIER,
|
||||
} from 'store/globalTime/utils';
|
||||
import { NANO_SECOND_MULTIPLIER } from 'store/globalTime/utils';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { buildAbsolutePath, isModifierKeyPressed } from 'utils/app';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
@@ -114,6 +111,9 @@ export function K8sBaseList<T>({
|
||||
const refreshInterval = useGlobalTimeStore((s) => s.refreshInterval);
|
||||
const isRefreshEnabled = useGlobalTimeStore((s) => s.isRefreshEnabled);
|
||||
const getMinMaxTime = useGlobalTimeStore((s) => s.getMinMaxTime);
|
||||
const getAutoRefreshQueryKey = useGlobalTimeStore(
|
||||
(s) => s.getAutoRefreshQueryKey,
|
||||
);
|
||||
|
||||
const queryKey = useMemo(() => {
|
||||
return getAutoRefreshQueryKey(
|
||||
@@ -127,6 +127,7 @@ export function K8sBaseList<T>({
|
||||
JSON.stringify(groupBy),
|
||||
);
|
||||
}, [
|
||||
getAutoRefreshQueryKey,
|
||||
selectedTime,
|
||||
entity,
|
||||
pageSize,
|
||||
|
||||
@@ -11,10 +11,7 @@ import {
|
||||
} from 'antd';
|
||||
import { CornerDownRight } from 'lucide-react';
|
||||
import { useGlobalTimeStore } from 'store/globalTime';
|
||||
import {
|
||||
getAutoRefreshQueryKey,
|
||||
NANO_SECOND_MULTIPLIER,
|
||||
} from 'store/globalTime/utils';
|
||||
import { NANO_SECOND_MULTIPLIER } from 'store/globalTime/utils';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { buildAbsolutePath, isModifierKeyPressed } from 'utils/app';
|
||||
@@ -118,6 +115,9 @@ export function K8sExpandedRow<T>({
|
||||
const refreshInterval = useGlobalTimeStore((s) => s.refreshInterval);
|
||||
const isRefreshEnabled = useGlobalTimeStore((s) => s.isRefreshEnabled);
|
||||
const getMinMaxTime = useGlobalTimeStore((s) => s.getMinMaxTime);
|
||||
const getAutoRefreshQueryKey = useGlobalTimeStore(
|
||||
(s) => s.getAutoRefreshQueryKey,
|
||||
);
|
||||
|
||||
const queryKey = useMemo(() => {
|
||||
return getAutoRefreshQueryKey(selectedTime, [
|
||||
@@ -126,7 +126,7 @@ export function K8sExpandedRow<T>({
|
||||
JSON.stringify(queryFilters),
|
||||
JSON.stringify(orderBy),
|
||||
]);
|
||||
}, [selectedTime, record.key, queryFilters, orderBy]);
|
||||
}, [getAutoRefreshQueryKey, selectedTime, record.key, queryFilters, orderBy]);
|
||||
|
||||
const { data, isFetching, isLoading, isError } = useQuery({
|
||||
queryKey,
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
.config-connection-status-popover {
|
||||
.ant-popover-inner {
|
||||
padding: 0;
|
||||
background-color: var(--l2-background);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--l3-background);
|
||||
padding: 8px;
|
||||
|
||||
width: 240px;
|
||||
|
||||
.ant-popover-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.config-connection-status-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.config-connection-status-icon {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.config-connection-status-category-display-name {
|
||||
color: var(--l2-foreground);
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 18px; /* 138.462% */
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { IConfigConnectionStatus } from 'container/Integrations/types';
|
||||
import { CheckCircle, TriangleAlert } from 'lucide-react';
|
||||
|
||||
import './ConfigConnectionStatus.styles.scss';
|
||||
|
||||
export function ConfigConnectionStatus({
|
||||
status,
|
||||
}: {
|
||||
status: IConfigConnectionStatus[] | null;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<div className="config-connection-status-container">
|
||||
{status?.map((status) => (
|
||||
<div key={status.category} className="config-connection-status-item">
|
||||
<div className="config-connection-status-icon">
|
||||
{status.last_received_ts_ms && status.last_received_ts_ms > 0 ? (
|
||||
<CheckCircle size={16} color={Color.BG_FOREST_500} />
|
||||
) : (
|
||||
<TriangleAlert size={16} color={Color.BG_AMBER_500} />
|
||||
)}
|
||||
</div>
|
||||
<div className="config-connection-status-category-display-name">
|
||||
{status.category_display_name}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
import cx from 'classnames';
|
||||
import LineClampedText from 'periscope/components/LineClampedText/LineClampedText';
|
||||
|
||||
import { Service } from './AmazonWebServices/types';
|
||||
|
||||
function ServiceItem({
|
||||
service,
|
||||
onClick,
|
||||
isActive,
|
||||
}: {
|
||||
service: Service;
|
||||
onClick: (serviceName: string) => void;
|
||||
isActive?: boolean;
|
||||
}): JSX.Element {
|
||||
return (
|
||||
<button
|
||||
className={cx('service-item', { active: isActive })}
|
||||
onClick={(): void => onClick(service.id)}
|
||||
type="button"
|
||||
>
|
||||
<div className="service-item__icon-wrapper">
|
||||
<img
|
||||
src={service.icon}
|
||||
alt={service.title}
|
||||
className="service-item__icon"
|
||||
/>
|
||||
</div>
|
||||
<div className="service-item__title">
|
||||
<LineClampedText text={service.title} />
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
ServiceItem.defaultProps = {
|
||||
isActive: false,
|
||||
};
|
||||
|
||||
export default ServiceItem;
|
||||
@@ -1,111 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { Button, Input, Space, Typography } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { IntegrationType } from 'container/Integrations/types';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { Check } from 'lucide-react';
|
||||
|
||||
import './Integrations.styles.scss';
|
||||
|
||||
interface RequestIntegrationBtnProps {
|
||||
type?: IntegrationType;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export function RequestIntegrationBtn({
|
||||
type,
|
||||
message,
|
||||
}: RequestIntegrationBtnProps): JSX.Element {
|
||||
const [
|
||||
isSubmittingRequestForIntegration,
|
||||
setIsSubmittingRequestForIntegration,
|
||||
] = useState(false);
|
||||
|
||||
const [requestedIntegrationName, setRequestedIntegrationName] = useState('');
|
||||
|
||||
const { notifications } = useNotifications();
|
||||
const { t } = useTranslation(['common']);
|
||||
|
||||
const handleRequestIntegrationSubmit = async (): Promise<void> => {
|
||||
try {
|
||||
setIsSubmittingRequestForIntegration(true);
|
||||
const eventName =
|
||||
type === IntegrationType.AWS_SERVICES
|
||||
? 'AWS service integration requested'
|
||||
: 'Integration requested';
|
||||
const screenName =
|
||||
type === IntegrationType.AWS_SERVICES
|
||||
? 'AWS integration details'
|
||||
: 'Integration list page';
|
||||
|
||||
const response = await logEvent(eventName, {
|
||||
screen: screenName,
|
||||
integration: requestedIntegrationName,
|
||||
});
|
||||
|
||||
if (response.statusCode === 200) {
|
||||
notifications.success({
|
||||
message: 'Integration Request Submitted',
|
||||
});
|
||||
|
||||
setIsSubmittingRequestForIntegration(false);
|
||||
} else {
|
||||
notifications.error({
|
||||
message:
|
||||
response.error ||
|
||||
t('something_went_wrong', {
|
||||
ns: 'common',
|
||||
}),
|
||||
});
|
||||
|
||||
setIsSubmittingRequestForIntegration(false);
|
||||
}
|
||||
} catch (error) {
|
||||
notifications.error({
|
||||
message: t('something_went_wrong', {
|
||||
ns: 'common',
|
||||
}),
|
||||
});
|
||||
|
||||
setIsSubmittingRequestForIntegration(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="request-entity-container">
|
||||
<Typography.Text>{message}</Typography.Text>
|
||||
|
||||
<div className="form-section">
|
||||
<Space.Compact style={{ width: '100%' }}>
|
||||
<Input
|
||||
placeholder="Enter integration name..."
|
||||
style={{ width: 300, marginBottom: 0 }}
|
||||
value={requestedIntegrationName}
|
||||
onChange={(e): void => setRequestedIntegrationName(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
className="periscope-btn primary"
|
||||
icon={
|
||||
isSubmittingRequestForIntegration ? (
|
||||
<LoadingOutlined />
|
||||
) : (
|
||||
<Check size={12} />
|
||||
)
|
||||
}
|
||||
type="primary"
|
||||
onClick={handleRequestIntegrationSubmit}
|
||||
disabled={
|
||||
isSubmittingRequestForIntegration ||
|
||||
!requestedIntegrationName ||
|
||||
requestedIntegrationName?.trim().length === 0
|
||||
}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import Integrations from './Integrations';
|
||||
|
||||
export default Integrations;
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Typography } from 'antd';
|
||||
import convertDateToAmAndPm from 'lib/convertDateToAmAndPm';
|
||||
import getFormattedDate from 'lib/getFormatedDate';
|
||||
|
||||
import { Data } from '../DashboardsList';
|
||||
|
||||
function Created(createdBy: Data['createdBy']): JSX.Element {
|
||||
const time = new Date(createdBy);
|
||||
|
||||
const date = getFormattedDate(time);
|
||||
|
||||
const timeString = `${date} ${convertDateToAmAndPm(time)}`;
|
||||
|
||||
return <Typography>{`${timeString}`}</Typography>;
|
||||
}
|
||||
|
||||
export default Created;
|
||||
@@ -1,29 +0,0 @@
|
||||
import { LockFilled } from '@ant-design/icons';
|
||||
import ROUTES from 'constants/routes';
|
||||
import history from 'lib/history';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
|
||||
import { Data } from '../DashboardsList';
|
||||
import { TableLinkText } from './styles';
|
||||
|
||||
function Name(name: Data['name'], data: Data): JSX.Element {
|
||||
const { id: DashboardId, isLocked } = data;
|
||||
|
||||
const getLink = (): string => `${ROUTES.ALL_DASHBOARD}/${DashboardId}`;
|
||||
|
||||
const onClickHandler = (event: React.MouseEvent<HTMLElement>): void => {
|
||||
if (event.metaKey || event.ctrlKey) {
|
||||
openInNewTab(getLink());
|
||||
} else {
|
||||
history.push(getLink());
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TableLinkText onClick={onClickHandler}>
|
||||
{isLocked && <LockFilled />} {name}
|
||||
</TableLinkText>
|
||||
);
|
||||
}
|
||||
|
||||
export default Name;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user