mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-20 08:50:29 +01:00
Compare commits
1 Commits
issue-5004
...
chore/butt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e01b0b293 |
@@ -8,14 +8,6 @@ packages:
|
||||
filename: "alertmanager.go"
|
||||
structname: 'Mock{{.InterfaceName}}'
|
||||
pkgname: '{{.SrcPackageName}}test'
|
||||
github.com/SigNoz/signoz/pkg/types/alertmanagertypes:
|
||||
interfaces:
|
||||
MaintenanceStore:
|
||||
config:
|
||||
dir: '{{.InterfaceDir}}/alertmanagertypestest'
|
||||
filename: "maintenance.go"
|
||||
structname: 'Mock{{.InterfaceName}}'
|
||||
pkgname: '{{.SrcPackageName}}test'
|
||||
github.com/SigNoz/signoz/pkg/tokenizer:
|
||||
config:
|
||||
all: true
|
||||
|
||||
@@ -96,53 +96,6 @@ components:
|
||||
- createdAt
|
||||
- updatedAt
|
||||
type: object
|
||||
AlertmanagertypesMaintenanceKind:
|
||||
enum:
|
||||
- fixed
|
||||
- recurring
|
||||
type: string
|
||||
AlertmanagertypesMaintenanceStatus:
|
||||
enum:
|
||||
- active
|
||||
- upcoming
|
||||
- expired
|
||||
type: string
|
||||
AlertmanagertypesPlannedMaintenance:
|
||||
properties:
|
||||
alertIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
createdBy:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
kind:
|
||||
$ref: '#/components/schemas/AlertmanagertypesMaintenanceKind'
|
||||
name:
|
||||
type: string
|
||||
schedule:
|
||||
$ref: '#/components/schemas/AlertmanagertypesSchedule'
|
||||
status:
|
||||
$ref: '#/components/schemas/AlertmanagertypesMaintenanceStatus'
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
updatedBy:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- schedule
|
||||
- status
|
||||
- kind
|
||||
type: object
|
||||
AlertmanagertypesPostableChannel:
|
||||
oneOf:
|
||||
- required:
|
||||
@@ -259,23 +212,6 @@ components:
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
AlertmanagertypesPostablePlannedMaintenance:
|
||||
properties:
|
||||
alertIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
schedule:
|
||||
$ref: '#/components/schemas/AlertmanagertypesSchedule'
|
||||
required:
|
||||
- name
|
||||
- schedule
|
||||
type: object
|
||||
AlertmanagertypesPostableRoutePolicy:
|
||||
properties:
|
||||
channels:
|
||||
@@ -301,60 +237,6 @@ components:
|
||||
- channels
|
||||
- name
|
||||
type: object
|
||||
AlertmanagertypesRecurrence:
|
||||
properties:
|
||||
duration:
|
||||
type: string
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
repeatOn:
|
||||
items:
|
||||
$ref: '#/components/schemas/AlertmanagertypesRepeatOn'
|
||||
nullable: true
|
||||
type: array
|
||||
repeatType:
|
||||
$ref: '#/components/schemas/AlertmanagertypesRepeatType'
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- startTime
|
||||
- duration
|
||||
- repeatType
|
||||
type: object
|
||||
AlertmanagertypesRepeatOn:
|
||||
enum:
|
||||
- sunday
|
||||
- monday
|
||||
- tuesday
|
||||
- wednesday
|
||||
- thursday
|
||||
- friday
|
||||
- saturday
|
||||
type: string
|
||||
AlertmanagertypesRepeatType:
|
||||
enum:
|
||||
- daily
|
||||
- weekly
|
||||
- monthly
|
||||
type: string
|
||||
AlertmanagertypesSchedule:
|
||||
properties:
|
||||
endTime:
|
||||
format: date-time
|
||||
type: string
|
||||
recurrence:
|
||||
$ref: '#/components/schemas/AlertmanagertypesRecurrence'
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
timezone:
|
||||
type: string
|
||||
required:
|
||||
- timezone
|
||||
type: object
|
||||
AuthtypesAttributeMapping:
|
||||
properties:
|
||||
email:
|
||||
@@ -2342,8 +2224,6 @@ components:
|
||||
type: boolean
|
||||
org_id:
|
||||
type: string
|
||||
source:
|
||||
$ref: '#/components/schemas/DashboardtypesSource'
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
@@ -2373,12 +2253,6 @@ components:
|
||||
timeRangeEnabled:
|
||||
type: boolean
|
||||
type: object
|
||||
DashboardtypesSource:
|
||||
enum:
|
||||
- user
|
||||
- system
|
||||
- integration
|
||||
type: string
|
||||
DashboardtypesStorableDashboardData:
|
||||
additionalProperties: {}
|
||||
type: object
|
||||
@@ -5263,6 +5137,17 @@ components:
|
||||
message:
|
||||
type: string
|
||||
type: object
|
||||
RuletypesMaintenanceKind:
|
||||
enum:
|
||||
- fixed
|
||||
- recurring
|
||||
type: string
|
||||
RuletypesMaintenanceStatus:
|
||||
enum:
|
||||
- active
|
||||
- upcoming
|
||||
- expired
|
||||
type: string
|
||||
RuletypesMatchType:
|
||||
enum:
|
||||
- at_least_once
|
||||
@@ -5290,6 +5175,59 @@ components:
|
||||
- table
|
||||
- graph
|
||||
type: string
|
||||
RuletypesPlannedMaintenance:
|
||||
properties:
|
||||
alertIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
createdAt:
|
||||
format: date-time
|
||||
type: string
|
||||
createdBy:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
kind:
|
||||
$ref: '#/components/schemas/RuletypesMaintenanceKind'
|
||||
name:
|
||||
type: string
|
||||
schedule:
|
||||
$ref: '#/components/schemas/RuletypesSchedule'
|
||||
status:
|
||||
$ref: '#/components/schemas/RuletypesMaintenanceStatus'
|
||||
updatedAt:
|
||||
format: date-time
|
||||
type: string
|
||||
updatedBy:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- schedule
|
||||
- status
|
||||
- kind
|
||||
type: object
|
||||
RuletypesPostablePlannedMaintenance:
|
||||
properties:
|
||||
alertIds:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
description:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
schedule:
|
||||
$ref: '#/components/schemas/RuletypesSchedule'
|
||||
required:
|
||||
- name
|
||||
- schedule
|
||||
type: object
|
||||
RuletypesPostableRule:
|
||||
properties:
|
||||
alert:
|
||||
@@ -5342,6 +5280,29 @@ components:
|
||||
- clickhouse_sql
|
||||
- promql
|
||||
type: string
|
||||
RuletypesRecurrence:
|
||||
properties:
|
||||
duration:
|
||||
type: string
|
||||
endTime:
|
||||
format: date-time
|
||||
nullable: true
|
||||
type: string
|
||||
repeatOn:
|
||||
items:
|
||||
$ref: '#/components/schemas/RuletypesRepeatOn'
|
||||
nullable: true
|
||||
type: array
|
||||
repeatType:
|
||||
$ref: '#/components/schemas/RuletypesRepeatType'
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- startTime
|
||||
- duration
|
||||
- repeatType
|
||||
type: object
|
||||
RuletypesRenotify:
|
||||
properties:
|
||||
alertStates:
|
||||
@@ -5353,6 +5314,22 @@ components:
|
||||
interval:
|
||||
type: string
|
||||
type: object
|
||||
RuletypesRepeatOn:
|
||||
enum:
|
||||
- sunday
|
||||
- monday
|
||||
- tuesday
|
||||
- wednesday
|
||||
- thursday
|
||||
- friday
|
||||
- saturday
|
||||
type: string
|
||||
RuletypesRepeatType:
|
||||
enum:
|
||||
- daily
|
||||
- weekly
|
||||
- monthly
|
||||
type: string
|
||||
RuletypesRollingWindow:
|
||||
properties:
|
||||
evalWindow:
|
||||
@@ -5472,6 +5449,21 @@ components:
|
||||
- promql_rule
|
||||
- anomaly_rule
|
||||
type: string
|
||||
RuletypesSchedule:
|
||||
properties:
|
||||
endTime:
|
||||
format: date-time
|
||||
type: string
|
||||
recurrence:
|
||||
$ref: '#/components/schemas/RuletypesRecurrence'
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
timezone:
|
||||
type: string
|
||||
required:
|
||||
- timezone
|
||||
type: object
|
||||
RuletypesScheduleType:
|
||||
enum:
|
||||
- hourly
|
||||
@@ -8032,7 +8024,7 @@ paths:
|
||||
properties:
|
||||
data:
|
||||
items:
|
||||
$ref: '#/components/schemas/AlertmanagertypesPlannedMaintenance'
|
||||
$ref: '#/components/schemas/RuletypesPlannedMaintenance'
|
||||
type: array
|
||||
status:
|
||||
type: string
|
||||
@@ -8075,7 +8067,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AlertmanagertypesPostablePlannedMaintenance'
|
||||
$ref: '#/components/schemas/RuletypesPostablePlannedMaintenance'
|
||||
responses:
|
||||
"201":
|
||||
content:
|
||||
@@ -8083,7 +8075,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/AlertmanagertypesPlannedMaintenance'
|
||||
$ref: '#/components/schemas/RuletypesPlannedMaintenance'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -8186,7 +8178,7 @@ paths:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/AlertmanagertypesPlannedMaintenance'
|
||||
$ref: '#/components/schemas/RuletypesPlannedMaintenance'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
@@ -8240,7 +8232,7 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AlertmanagertypesPostablePlannedMaintenance'
|
||||
$ref: '#/components/schemas/RuletypesPostablePlannedMaintenance'
|
||||
responses:
|
||||
"204":
|
||||
description: No Content
|
||||
|
||||
@@ -49,14 +49,6 @@ func (module *module) CreatePublic(ctx context.Context, orgID valuer.UUID, publi
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
dashboard, err := module.Get(ctx, orgID, publicDashboard.DashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dashboard.ErrIfNotPublishable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
storablePublicDashboard, err := module.store.GetPublic(ctx, publicDashboard.DashboardID.StringValue())
|
||||
if err != nil && !errors.Ast(err, errors.TypeNotFound) {
|
||||
return err
|
||||
@@ -137,14 +129,6 @@ func (module *module) UpdatePublic(ctx context.Context, orgID valuer.UUID, publi
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
dashboard, err := module.Get(ctx, orgID, publicDashboard.DashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dashboard.ErrIfNotPublishable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return module.store.UpdatePublic(ctx, dashboardtypes.NewStorablePublicDashboardFromPublicDashboard(publicDashboard))
|
||||
}
|
||||
|
||||
@@ -154,10 +138,6 @@ func (module *module) Delete(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dashboard.ErrIfNotDeletable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dashboard.Locked {
|
||||
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "dashboard is locked, please unlock the dashboard to be delete it")
|
||||
}
|
||||
@@ -188,14 +168,6 @@ func (module *module) DeletePublic(ctx context.Context, orgID valuer.UUID, dashb
|
||||
return errors.New(errors.TypeLicenseUnavailable, errors.CodeLicenseUnavailable, "a valid license is not available").WithAdditional("this feature requires a valid license").WithAdditional(err.Error())
|
||||
}
|
||||
|
||||
dashboard, err := module.Get(ctx, orgID, dashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dashboard.ErrIfNotPublishable(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = module.store.DeletePublic(ctx, dashboardID.StringValue())
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -80,15 +80,6 @@ func (ah *APIHandler) getFeatureFlags(w http.ResponseWriter, r *http.Request) {
|
||||
Route: "",
|
||||
})
|
||||
|
||||
fineGrainedAuthz := ah.Signoz.Flagger.BooleanOrEmpty(ctx, flagger.FeatureUseFineGrainedAuthz, evalCtx)
|
||||
featureSet = append(featureSet, &licensetypes.Feature{
|
||||
Name: valuer.NewString(flagger.FeatureUseFineGrainedAuthz.String()),
|
||||
Active: fineGrainedAuthz,
|
||||
Usage: 0,
|
||||
UsageLimit: -1,
|
||||
Route: "",
|
||||
})
|
||||
|
||||
if constants.IsDotMetricsEnabled {
|
||||
for idx, feature := range featureSet {
|
||||
if feature.Name == licensetypes.DotMetricsEnabled {
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
baserules "github.com/SigNoz/signoz/pkg/query-service/rules"
|
||||
"github.com/SigNoz/signoz/pkg/types/ruletypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error) {
|
||||
@@ -48,7 +49,7 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
|
||||
rules = append(rules, tr)
|
||||
|
||||
// create ch rule task for evaluation
|
||||
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc)
|
||||
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc, opts.MaintenanceStore, opts.OrgID)
|
||||
|
||||
} else if opts.Rule.RuleType == ruletypes.RuleTypeProm {
|
||||
|
||||
@@ -72,7 +73,7 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
|
||||
rules = append(rules, pr)
|
||||
|
||||
// create promql rule task for evaluation
|
||||
task = newTask(baserules.TaskTypeProm, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc)
|
||||
task = newTask(baserules.TaskTypeProm, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc, opts.MaintenanceStore, opts.OrgID)
|
||||
|
||||
} else if opts.Rule.RuleType == ruletypes.RuleTypeAnomaly {
|
||||
// create anomaly rule
|
||||
@@ -95,7 +96,7 @@ func PrepareTaskFunc(opts baserules.PrepareTaskOptions) (baserules.Task, error)
|
||||
rules = append(rules, ar)
|
||||
|
||||
// create anomaly rule task for evaluation
|
||||
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc)
|
||||
task = newTask(baserules.TaskTypeCh, opts.TaskName, evaluation.GetFrequency().Duration(), rules, opts.ManagerOpts, opts.NotifyFunc, opts.MaintenanceStore, opts.OrgID)
|
||||
|
||||
} else {
|
||||
return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "unsupported rule type %s. Supported types: %s, %s", opts.Rule.RuleType, ruletypes.RuleTypeProm, ruletypes.RuleTypeThreshold)
|
||||
@@ -209,9 +210,9 @@ func TestNotification(opts baserules.PrepareTestRuleOptions) (int, error) {
|
||||
}
|
||||
|
||||
// newTask returns an appropriate group for the rule type
|
||||
func newTask(taskType baserules.TaskType, name string, frequency time.Duration, rules []baserules.Rule, opts *baserules.ManagerOptions, notify baserules.NotifyFunc) baserules.Task {
|
||||
func newTask(taskType baserules.TaskType, name string, frequency time.Duration, rules []baserules.Rule, opts *baserules.ManagerOptions, notify baserules.NotifyFunc, maintenanceStore ruletypes.MaintenanceStore, orgID valuer.UUID) baserules.Task {
|
||||
if taskType == baserules.TaskTypeCh {
|
||||
return baserules.NewRuleTask(name, "", frequency, rules, opts, notify)
|
||||
return baserules.NewRuleTask(name, "", frequency, rules, opts, notify, maintenanceStore, orgID)
|
||||
}
|
||||
return baserules.NewPromRuleTask(name, "", frequency, rules, opts, notify)
|
||||
return baserules.NewPromRuleTask(name, "", frequency, rules, opts, notify, maintenanceStore, orgID)
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export default defineConfig({
|
||||
signal: true,
|
||||
useOperationIdAsQueryKey: false,
|
||||
},
|
||||
useDates: false,
|
||||
useDates: true,
|
||||
useNamedParameters: true,
|
||||
enumGenerationType: 'enum',
|
||||
mutator: {
|
||||
|
||||
@@ -18,7 +18,6 @@ import type {
|
||||
} from 'react-query';
|
||||
|
||||
import type {
|
||||
AlertmanagertypesPostablePlannedMaintenanceDTO,
|
||||
CreateDowntimeSchedule201,
|
||||
DeleteDowntimeScheduleByIDPathParameters,
|
||||
GetDowntimeScheduleByID200,
|
||||
@@ -26,6 +25,7 @@ import type {
|
||||
ListDowntimeSchedules200,
|
||||
ListDowntimeSchedulesParams,
|
||||
RenderErrorResponseDTO,
|
||||
RuletypesPostablePlannedMaintenanceDTO,
|
||||
UpdateDowntimeScheduleByIDPathParameters,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
@@ -135,14 +135,14 @@ export const invalidateListDowntimeSchedules = async (
|
||||
* @summary Create downtime schedule
|
||||
*/
|
||||
export const createDowntimeSchedule = (
|
||||
alertmanagertypesPostablePlannedMaintenanceDTO?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>,
|
||||
ruletypesPostablePlannedMaintenanceDTO?: BodyType<RuletypesPostablePlannedMaintenanceDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<CreateDowntimeSchedule201>({
|
||||
url: `/api/v1/downtime_schedules`,
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: alertmanagertypesPostablePlannedMaintenanceDTO,
|
||||
data: ruletypesPostablePlannedMaintenanceDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -154,13 +154,13 @@ export const getCreateDowntimeScheduleMutationOptions = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createDowntimeSchedule>>,
|
||||
TError,
|
||||
{ data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO> },
|
||||
{ data?: BodyType<RuletypesPostablePlannedMaintenanceDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createDowntimeSchedule>>,
|
||||
TError,
|
||||
{ data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO> },
|
||||
{ data?: BodyType<RuletypesPostablePlannedMaintenanceDTO> },
|
||||
TContext
|
||||
> => {
|
||||
const mutationKey = ['createDowntimeSchedule'];
|
||||
@@ -174,7 +174,7 @@ export const getCreateDowntimeScheduleMutationOptions = <
|
||||
|
||||
const mutationFn: MutationFunction<
|
||||
Awaited<ReturnType<typeof createDowntimeSchedule>>,
|
||||
{ data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO> }
|
||||
{ data?: BodyType<RuletypesPostablePlannedMaintenanceDTO> }
|
||||
> = (props) => {
|
||||
const { data } = props ?? {};
|
||||
|
||||
@@ -188,7 +188,7 @@ export type CreateDowntimeScheduleMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof createDowntimeSchedule>>
|
||||
>;
|
||||
export type CreateDowntimeScheduleMutationBody =
|
||||
| BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>
|
||||
| BodyType<RuletypesPostablePlannedMaintenanceDTO>
|
||||
| undefined;
|
||||
export type CreateDowntimeScheduleMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
@@ -203,13 +203,13 @@ export const useCreateDowntimeSchedule = <
|
||||
mutation?: UseMutationOptions<
|
||||
Awaited<ReturnType<typeof createDowntimeSchedule>>,
|
||||
TError,
|
||||
{ data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO> },
|
||||
{ data?: BodyType<RuletypesPostablePlannedMaintenanceDTO> },
|
||||
TContext
|
||||
>;
|
||||
}): UseMutationResult<
|
||||
Awaited<ReturnType<typeof createDowntimeSchedule>>,
|
||||
TError,
|
||||
{ data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO> },
|
||||
{ data?: BodyType<RuletypesPostablePlannedMaintenanceDTO> },
|
||||
TContext
|
||||
> => {
|
||||
return useMutation(getCreateDowntimeScheduleMutationOptions(options));
|
||||
@@ -403,14 +403,14 @@ export const invalidateGetDowntimeScheduleByID = async (
|
||||
*/
|
||||
export const updateDowntimeScheduleByID = (
|
||||
{ id }: UpdateDowntimeScheduleByIDPathParameters,
|
||||
alertmanagertypesPostablePlannedMaintenanceDTO?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>,
|
||||
ruletypesPostablePlannedMaintenanceDTO?: BodyType<RuletypesPostablePlannedMaintenanceDTO>,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<void>({
|
||||
url: `/api/v1/downtime_schedules/${id}`,
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
data: alertmanagertypesPostablePlannedMaintenanceDTO,
|
||||
data: ruletypesPostablePlannedMaintenanceDTO,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
@@ -424,7 +424,7 @@ export const getUpdateDowntimeScheduleByIDMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDowntimeScheduleByIDPathParameters;
|
||||
data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>;
|
||||
data?: BodyType<RuletypesPostablePlannedMaintenanceDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -433,7 +433,7 @@ export const getUpdateDowntimeScheduleByIDMutationOptions = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDowntimeScheduleByIDPathParameters;
|
||||
data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>;
|
||||
data?: BodyType<RuletypesPostablePlannedMaintenanceDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
@@ -450,7 +450,7 @@ export const getUpdateDowntimeScheduleByIDMutationOptions = <
|
||||
Awaited<ReturnType<typeof updateDowntimeScheduleByID>>,
|
||||
{
|
||||
pathParams: UpdateDowntimeScheduleByIDPathParameters;
|
||||
data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>;
|
||||
data?: BodyType<RuletypesPostablePlannedMaintenanceDTO>;
|
||||
}
|
||||
> = (props) => {
|
||||
const { pathParams, data } = props ?? {};
|
||||
@@ -465,7 +465,7 @@ export type UpdateDowntimeScheduleByIDMutationResult = NonNullable<
|
||||
Awaited<ReturnType<typeof updateDowntimeScheduleByID>>
|
||||
>;
|
||||
export type UpdateDowntimeScheduleByIDMutationBody =
|
||||
| BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>
|
||||
| BodyType<RuletypesPostablePlannedMaintenanceDTO>
|
||||
| undefined;
|
||||
export type UpdateDowntimeScheduleByIDMutationError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
@@ -482,7 +482,7 @@ export const useUpdateDowntimeScheduleByID = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDowntimeScheduleByIDPathParameters;
|
||||
data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>;
|
||||
data?: BodyType<RuletypesPostablePlannedMaintenanceDTO>;
|
||||
},
|
||||
TContext
|
||||
>;
|
||||
@@ -491,7 +491,7 @@ export const useUpdateDowntimeScheduleByID = <
|
||||
TError,
|
||||
{
|
||||
pathParams: UpdateDowntimeScheduleByIDPathParameters;
|
||||
data?: BodyType<AlertmanagertypesPostablePlannedMaintenanceDTO>;
|
||||
data?: BodyType<RuletypesPostablePlannedMaintenanceDTO>;
|
||||
},
|
||||
TContext
|
||||
> => {
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface AlertmanagertypesChannelDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -34,7 +34,7 @@ export interface AlertmanagertypesChannelDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ModelLabelSetDTO {
|
||||
@@ -62,7 +62,7 @@ export interface AlertmanagertypesDeprecatedGettableAlertDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
endsAt?: string;
|
||||
endsAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -80,7 +80,7 @@ export interface AlertmanagertypesDeprecatedGettableAlertDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startsAt?: string;
|
||||
startsAt?: Date;
|
||||
status?: TypesAlertStatusDTO;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ export interface AlertmanagertypesGettableRoutePolicyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt: string;
|
||||
createdAt: Date;
|
||||
/**
|
||||
* @type string,null
|
||||
*/
|
||||
@@ -127,116 +127,13 @@ export interface AlertmanagertypesGettableRoutePolicyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt: string;
|
||||
updatedAt: Date;
|
||||
/**
|
||||
* @type string,null
|
||||
*/
|
||||
updatedBy?: string | null;
|
||||
}
|
||||
|
||||
export enum AlertmanagertypesMaintenanceKindDTO {
|
||||
fixed = 'fixed',
|
||||
recurring = 'recurring',
|
||||
}
|
||||
export enum AlertmanagertypesMaintenanceStatusDTO {
|
||||
active = 'active',
|
||||
upcoming = 'upcoming',
|
||||
expired = 'expired',
|
||||
}
|
||||
export enum AlertmanagertypesRepeatOnDTO {
|
||||
sunday = 'sunday',
|
||||
monday = 'monday',
|
||||
tuesday = 'tuesday',
|
||||
wednesday = 'wednesday',
|
||||
thursday = 'thursday',
|
||||
friday = 'friday',
|
||||
saturday = 'saturday',
|
||||
}
|
||||
export enum AlertmanagertypesRepeatTypeDTO {
|
||||
daily = 'daily',
|
||||
weekly = 'weekly',
|
||||
monthly = 'monthly',
|
||||
}
|
||||
export interface AlertmanagertypesRecurrenceDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
duration: string;
|
||||
/**
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: string | null;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
repeatOn?: AlertmanagertypesRepeatOnDTO[] | null;
|
||||
repeatType: AlertmanagertypesRepeatTypeDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime: string;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesScheduleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: string;
|
||||
recurrence?: AlertmanagertypesRecurrenceDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
timezone: string;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesPlannedMaintenanceDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
alertIds?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
createdBy?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
kind: AlertmanagertypesMaintenanceKindDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
schedule: AlertmanagertypesScheduleDTO;
|
||||
status: AlertmanagertypesMaintenanceStatusDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export interface ConfigAuthorizationDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -1700,22 +1597,6 @@ export type AlertmanagertypesPostableChannelDTO = unknown & {
|
||||
wechat_configs?: ConfigWechatConfigDTO[];
|
||||
};
|
||||
|
||||
export interface AlertmanagertypesPostablePlannedMaintenanceDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
alertIds?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
schedule: AlertmanagertypesScheduleDTO;
|
||||
}
|
||||
|
||||
export interface AlertmanagertypesPostableRoutePolicyDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
@@ -1953,7 +1834,7 @@ export interface AuthtypesGettableAuthDomainDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -1970,7 +1851,7 @@ export interface AuthtypesGettableAuthDomainDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface AuthtypesGettableTokenDTO {
|
||||
@@ -2128,7 +2009,7 @@ export interface AuthtypesRoleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2153,7 +2034,7 @@ export interface AuthtypesRoleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface AuthtypesSessionContextDTO {
|
||||
@@ -2181,7 +2062,7 @@ export interface AuthtypesUserRoleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt: string;
|
||||
createdAt: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2195,7 +2076,7 @@ export interface AuthtypesUserRoleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt: string;
|
||||
updatedAt: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2207,7 +2088,7 @@ export interface AuthtypesUserWithRolesDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2236,7 +2117,7 @@ export interface AuthtypesUserWithRolesDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
@@ -2403,7 +2284,7 @@ export interface CloudintegrationtypesAccountDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2424,12 +2305,12 @@ export interface CloudintegrationtypesAccountDTO {
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
removedAt: string | null;
|
||||
removedAt: Date | null;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface DashboardtypesStorableDashboardDataDTO {
|
||||
@@ -2560,7 +2441,7 @@ export type CloudintegrationtypesCloudIntegrationServiceDTOAnyOf = {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -2570,7 +2451,7 @@ export type CloudintegrationtypesCloudIntegrationServiceDTOAnyOf = {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2764,12 +2645,12 @@ export interface CloudintegrationtypesGettableAgentCheckInDTO {
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
removed_at: string | null;
|
||||
removed_at: Date | null;
|
||||
/**
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
removedAt: string | null;
|
||||
removedAt: Date | null;
|
||||
}
|
||||
|
||||
export interface CloudintegrationtypesServiceMetadataDTO {
|
||||
@@ -2999,17 +2880,12 @@ export interface CoretypesPatchableObjectsDTO {
|
||||
deletions: CoretypesObjectGroupDTO[] | null;
|
||||
}
|
||||
|
||||
export enum DashboardtypesSourceDTO {
|
||||
user = 'user',
|
||||
system = 'system',
|
||||
integration = 'integration',
|
||||
}
|
||||
export interface DashboardtypesDashboardDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3027,12 +2903,11 @@ export interface DashboardtypesDashboardDTO {
|
||||
* @type string
|
||||
*/
|
||||
org_id?: string;
|
||||
source?: DashboardtypesSourceDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3214,7 +3089,7 @@ export interface GatewaytypesLimitDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
created_at?: string;
|
||||
created_at?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3236,7 +3111,7 @@ export interface GatewaytypesLimitDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updated_at?: string;
|
||||
updated_at?: Date;
|
||||
}
|
||||
|
||||
export interface GatewaytypesIngestionKeyDTO {
|
||||
@@ -3244,12 +3119,12 @@ export interface GatewaytypesIngestionKeyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
created_at?: string;
|
||||
created_at?: Date;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
expires_at?: string;
|
||||
expires_at?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3270,7 +3145,7 @@ export interface GatewaytypesIngestionKeyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updated_at?: string;
|
||||
updated_at?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3294,7 +3169,7 @@ export interface GatewaytypesPostableIngestionKeyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
expires_at?: string;
|
||||
expires_at?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -4564,7 +4439,7 @@ export interface LlmpricingruletypesLLMPricingRuleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -4603,13 +4478,13 @@ export interface LlmpricingruletypesLLMPricingRuleDTO {
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
syncedAt?: string | null;
|
||||
syncedAt?: Date | null;
|
||||
unit: LlmpricingruletypesLLMPricingRuleUnitDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -5835,7 +5710,7 @@ export interface Querybuildertypesv5RawRowDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
timestamp?: string;
|
||||
timestamp?: Date;
|
||||
}
|
||||
|
||||
export interface Querybuildertypesv5RawDataDTO {
|
||||
@@ -6241,6 +6116,15 @@ export interface RuletypesGettableTestRuleDTO {
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export enum RuletypesMaintenanceKindDTO {
|
||||
fixed = 'fixed',
|
||||
recurring = 'recurring',
|
||||
}
|
||||
export enum RuletypesMaintenanceStatusDTO {
|
||||
active = 'active',
|
||||
upcoming = 'upcoming',
|
||||
expired = 'expired',
|
||||
}
|
||||
export interface RuletypesRenotifyDTO {
|
||||
/**
|
||||
* @type array
|
||||
@@ -6272,6 +6156,116 @@ export interface RuletypesNotificationSettingsDTO {
|
||||
usePolicy?: boolean;
|
||||
}
|
||||
|
||||
export enum RuletypesRepeatOnDTO {
|
||||
sunday = 'sunday',
|
||||
monday = 'monday',
|
||||
tuesday = 'tuesday',
|
||||
wednesday = 'wednesday',
|
||||
thursday = 'thursday',
|
||||
friday = 'friday',
|
||||
saturday = 'saturday',
|
||||
}
|
||||
export enum RuletypesRepeatTypeDTO {
|
||||
daily = 'daily',
|
||||
weekly = 'weekly',
|
||||
monthly = 'monthly',
|
||||
}
|
||||
export interface RuletypesRecurrenceDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
duration: string;
|
||||
/**
|
||||
* @type string,null
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: Date | null;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
repeatOn?: RuletypesRepeatOnDTO[] | null;
|
||||
repeatType: RuletypesRepeatTypeDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime: Date;
|
||||
}
|
||||
|
||||
export interface RuletypesScheduleDTO {
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
endTime?: Date;
|
||||
recurrence?: RuletypesRecurrenceDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
startTime?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
timezone: string;
|
||||
}
|
||||
|
||||
export interface RuletypesPlannedMaintenanceDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
alertIds?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
createdBy?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
id: string;
|
||||
kind: RuletypesMaintenanceKindDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
schedule: RuletypesScheduleDTO;
|
||||
status: RuletypesMaintenanceStatusDTO;
|
||||
/**
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
updatedBy?: string;
|
||||
}
|
||||
|
||||
export interface RuletypesPostablePlannedMaintenanceDTO {
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
alertIds?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
name: string;
|
||||
schedule: RuletypesScheduleDTO;
|
||||
}
|
||||
|
||||
export type RuletypesPostableRuleDTOAnnotations = { [key: string]: string };
|
||||
|
||||
export type RuletypesPostableRuleDTOLabels = { [key: string]: string };
|
||||
@@ -6412,7 +6406,7 @@ export interface RuletypesRuleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6461,7 +6455,7 @@ export interface RuletypesRuleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6480,7 +6474,7 @@ export interface ServiceaccounttypesGettableFactorAPIKeyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
@@ -6494,7 +6488,7 @@ export interface ServiceaccounttypesGettableFactorAPIKeyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
lastObservedAt: string;
|
||||
lastObservedAt: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6507,7 +6501,7 @@ export interface ServiceaccounttypesGettableFactorAPIKeyDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesGettableFactorAPIKeyWithKeyDTO {
|
||||
@@ -6552,7 +6546,7 @@ export interface ServiceaccounttypesServiceAccountDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6577,7 +6571,7 @@ export interface ServiceaccounttypesServiceAccountDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesServiceAccountRoleDTO {
|
||||
@@ -6585,7 +6579,7 @@ export interface ServiceaccounttypesServiceAccountRoleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6603,7 +6597,7 @@ export interface ServiceaccounttypesServiceAccountRoleDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesServiceAccountWithRolesDTO {
|
||||
@@ -6611,7 +6605,7 @@ export interface ServiceaccounttypesServiceAccountWithRolesDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6640,7 +6634,7 @@ export interface ServiceaccounttypesServiceAccountWithRolesDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ServiceaccounttypesUpdatableFactorAPIKeyDTO {
|
||||
@@ -6682,7 +6676,7 @@ export interface SpantypesSpanMapperGroupDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6707,7 +6701,7 @@ export interface SpantypesSpanMapperGroupDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6776,7 +6770,7 @@ export interface SpantypesSpanMapperDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -6802,7 +6796,7 @@ export interface SpantypesSpanMapperDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7169,7 +7163,7 @@ export interface TypesDeprecatedUserDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7202,7 +7196,7 @@ export interface TypesDeprecatedUserDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface TypesIdentifiableDTO {
|
||||
@@ -7217,7 +7211,7 @@ export interface TypesInviteDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7250,7 +7244,7 @@ export interface TypesInviteDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface TypesOrganizationDTO {
|
||||
@@ -7262,7 +7256,7 @@ export interface TypesOrganizationDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7284,7 +7278,7 @@ export interface TypesOrganizationDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface TypesPostableInviteDTO {
|
||||
@@ -7351,7 +7345,7 @@ export interface TypesResetPasswordTokenDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
expiresAt?: string;
|
||||
expiresAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7378,7 +7372,7 @@ export interface TypesUserDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
createdAt?: string;
|
||||
createdAt?: Date;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7407,7 +7401,7 @@ export interface TypesUserDTO {
|
||||
* @type string
|
||||
* @format date-time
|
||||
*/
|
||||
updatedAt?: string;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
export interface ZeustypesHostDTO {
|
||||
@@ -7799,7 +7793,7 @@ export type ListDowntimeSchedules200 = {
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
data: AlertmanagertypesPlannedMaintenanceDTO[];
|
||||
data: RuletypesPlannedMaintenanceDTO[];
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7807,7 +7801,7 @@ export type ListDowntimeSchedules200 = {
|
||||
};
|
||||
|
||||
export type CreateDowntimeSchedule201 = {
|
||||
data: AlertmanagertypesPlannedMaintenanceDTO;
|
||||
data: RuletypesPlannedMaintenanceDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7821,7 +7815,7 @@ export type GetDowntimeScheduleByIDPathParameters = {
|
||||
id: string;
|
||||
};
|
||||
export type GetDowntimeScheduleByID200 = {
|
||||
data: AlertmanagertypesPlannedMaintenanceDTO;
|
||||
data: RuletypesPlannedMaintenanceDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useSelector } from 'react-redux';
|
||||
import { Loader, Search } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import {
|
||||
Button,
|
||||
Flex,
|
||||
Input,
|
||||
InputRef,
|
||||
@@ -17,6 +16,7 @@ import {
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import type { FilterDropdownProps } from 'antd/lib/table/interface';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import {
|
||||
@@ -105,9 +105,8 @@ const getColumnSearchProps = (
|
||||
/>
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={(): void => handleSearch(selectedKeys as string[], confirm)}
|
||||
size="sm"
|
||||
>
|
||||
<Flex align="center" gap={4}>
|
||||
<Search size="md" />
|
||||
@@ -116,17 +115,19 @@ const getColumnSearchProps = (
|
||||
</Button>
|
||||
<Button
|
||||
onClick={(): void => clearFilters && handleReset(clearFilters, confirm)}
|
||||
size="small"
|
||||
style={{ width: 90 }}
|
||||
size="sm"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
size="small"
|
||||
onClick={(): void => {
|
||||
close();
|
||||
}}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
close
|
||||
</Button>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useMutation } from 'react-query';
|
||||
import { Check, ChevronsDown, ScrollText, X } from '@signozhq/icons';
|
||||
import { Button, Flex, Modal } from 'antd';
|
||||
import { Flex, Modal } from 'antd';
|
||||
import updateUserPreference from 'api/v1/user/preferences/name/update';
|
||||
import cx from 'classnames';
|
||||
import { USER_PREFERENCES } from 'constants/userPreferences';
|
||||
@@ -14,6 +14,7 @@ import { UserPreference } from 'types/api/preferences/preference';
|
||||
import ChangelogRenderer from './components/ChangelogRenderer';
|
||||
|
||||
import './ChangelogModal.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
interface Props {
|
||||
changelog: ChangelogSchema;
|
||||
@@ -115,13 +116,13 @@ function ChangelogModal({ changelog, onClose }: Props): JSX.Element {
|
||||
>
|
||||
{!isCloudUser && (
|
||||
<div className="changelog-modal-footer-ctas">
|
||||
<Button type="default" onClick={onClose}>
|
||||
<Button onClick={onClose} variant="outlined" color="secondary">
|
||||
<Flex align="center" gap="4px">
|
||||
<X size="md" />
|
||||
Skip for now
|
||||
</Flex>
|
||||
</Button>
|
||||
<Button type="primary" onClick={onClickUpdateWorkspace}>
|
||||
<Button onClick={onClickUpdateWorkspace}>
|
||||
<Flex align="center" gap="4px">
|
||||
<Check size="md" />
|
||||
Update my workspace
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { useMutation } from 'react-query';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Button, Modal } from 'antd';
|
||||
import { Modal } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import updateCreditCardApi from 'api/v1/checkout/create';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
@@ -72,6 +73,8 @@ export default function ChatSupportGateway(): JSX.Element {
|
||||
|
||||
setIsAddCreditCardModalOpen(true);
|
||||
}}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
<MessageSquareText size={24} />
|
||||
</Button>
|
||||
@@ -90,19 +93,19 @@ export default function ChatSupportGateway(): JSX.Element {
|
||||
key="cancel"
|
||||
onClick={(): void => setIsAddCreditCardModalOpen(false)}
|
||||
className="cancel-btn"
|
||||
icon={<X size={16} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<X size={16} />}
|
||||
>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
icon={<CreditCard size={16} />}
|
||||
size="middle"
|
||||
loading={isLoadingBilling}
|
||||
disabled={isLoadingBilling}
|
||||
onClick={handleAddCreditCard}
|
||||
className="add-credit-card-btn"
|
||||
prefix={<CreditCard size={16} />}
|
||||
>
|
||||
Add Credit Card
|
||||
</Button>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Calendar } from '@signozhq/ui/calendar';
|
||||
import { Button } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import dayjs from 'dayjs';
|
||||
import { Calendar as CalendarIcon, Check, X } from '@signozhq/icons';
|
||||
@@ -78,18 +78,20 @@ function CalendarContainer({
|
||||
|
||||
<div className="calendar-actions">
|
||||
<Button
|
||||
type="primary"
|
||||
className="periscope-btn secondary cancel-btn"
|
||||
className="cancel-btn"
|
||||
onClick={onCancel}
|
||||
icon={<X size={12} />}
|
||||
prefix={<X size={12} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
className="periscope-btn primary apply-btn"
|
||||
className="apply-btn"
|
||||
onClick={onApply}
|
||||
icon={<Check size={12} />}
|
||||
prefix={<Check size={12} />}
|
||||
variant="solid"
|
||||
color="primary"
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
}
|
||||
|
||||
.info-text:hover {
|
||||
&.ant-btn-text {
|
||||
& {
|
||||
background-color: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
} from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import cx from 'classnames';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
@@ -32,6 +31,7 @@ import TimezonePicker from './TimezonePicker';
|
||||
import { Timezone } from './timezoneUtils';
|
||||
|
||||
import './CustomTimePicker.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
const TO_MILLISECONDS_FACTOR = 1000_000;
|
||||
|
||||
@@ -177,13 +177,13 @@ function CustomTimePickerPopoverContent({
|
||||
<div className="relative-date-time-section">
|
||||
{options.map((option) => (
|
||||
<Button
|
||||
type="text"
|
||||
className="time-btns"
|
||||
key={option.label + option.value}
|
||||
onClick={(): void => {
|
||||
handleExitLiveLogs();
|
||||
onSelectHandler(option.label, option.value);
|
||||
}}
|
||||
variant="ghost"
|
||||
>
|
||||
{option.label}
|
||||
</Button>
|
||||
@@ -249,15 +249,14 @@ function CustomTimePickerPopoverContent({
|
||||
{isLogsExplorerPage && isLogsListView && (
|
||||
<Button
|
||||
className={cx('data-time-live', isLiveLogsEnabled ? 'active' : '')}
|
||||
type="text"
|
||||
onClick={handleGoLive}
|
||||
variant="ghost"
|
||||
>
|
||||
Live
|
||||
</Button>
|
||||
)}
|
||||
{options.map((option) => (
|
||||
<Button
|
||||
type="text"
|
||||
key={option.label + option.value}
|
||||
onClick={(e: React.MouseEvent<HTMLButtonElement>): void => {
|
||||
e.stopPropagation();
|
||||
@@ -271,6 +270,7 @@ function CustomTimePickerPopoverContent({
|
||||
? option.value === 'custom' && !isLiveLogsEnabled && 'active'
|
||||
: selectedTime === option.value && !isLiveLogsEnabled && 'active',
|
||||
)}
|
||||
variant="ghost"
|
||||
>
|
||||
<span className="time-label">{option.label}</span>
|
||||
|
||||
@@ -370,11 +370,12 @@ function CustomTimePickerPopoverContent({
|
||||
|
||||
<div className="timezone-container__right">
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
className="periscope-btn text timezone-change-button"
|
||||
className="timezone-change-button"
|
||||
onClick={handleTimezoneHintClick}
|
||||
icon={<PenLine size={10} />}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
prefix={<PenLine size={10} />}
|
||||
color="none"
|
||||
>
|
||||
Change Timezone
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { Button, Popover, Radio, Tooltip } from 'antd';
|
||||
import { Popover, Radio, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { useExportRawData } from 'hooks/useDownloadOptionsMenu/useDownloadOptionsMenu';
|
||||
import { Download, LoaderCircle } from '@signozhq/icons';
|
||||
@@ -104,12 +105,11 @@ export default function DownloadOptionsMenu({
|
||||
)}
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<Download size={16} />}
|
||||
onClick={handleExport}
|
||||
className="export-button"
|
||||
disabled={isDownloading}
|
||||
loading={isDownloading}
|
||||
prefix={<Download size={16} />}
|
||||
>
|
||||
Export
|
||||
</Button>
|
||||
@@ -137,16 +137,18 @@ export default function DownloadOptionsMenu({
|
||||
>
|
||||
<Tooltip title="Download" placement="top">
|
||||
<Button
|
||||
className="periscope-btn ghost"
|
||||
icon={
|
||||
data-testid={`periscope-btn-download-${dataSource}`}
|
||||
disabled={isDownloading}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={
|
||||
isDownloading ? (
|
||||
<LoaderCircle size={14} className="animate-spin" />
|
||||
) : (
|
||||
<Download size={14} />
|
||||
)
|
||||
}
|
||||
data-testid={`periscope-btn-download-${dataSource}`}
|
||||
disabled={isDownloading}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState } from 'react';
|
||||
import { Ellipsis } from '@signozhq/icons';
|
||||
import { Button, Dropdown, MenuProps } from 'antd';
|
||||
import { Dropdown, MenuProps } from 'antd';
|
||||
|
||||
import './DropDown.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function DropDown({
|
||||
element,
|
||||
@@ -31,12 +32,12 @@ function DropDown({
|
||||
open={isDdOpen}
|
||||
>
|
||||
<Button
|
||||
type="link"
|
||||
className={`dropdown-button`}
|
||||
onClick={(e): void => {
|
||||
e.preventDefault();
|
||||
setDdOpen(true);
|
||||
}}
|
||||
variant="link"
|
||||
>
|
||||
<Ellipsis className="dropdown-icon" size={16} />
|
||||
</Button>
|
||||
|
||||
@@ -59,7 +59,7 @@ function getDeleteTooltip(
|
||||
|
||||
function getInviteButtonLabel(
|
||||
isLoading: boolean,
|
||||
existingToken: { expiresAt?: string } | undefined,
|
||||
existingToken: { expiresAt?: Date } | undefined,
|
||||
isExpired: boolean,
|
||||
notFound: boolean,
|
||||
): string {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Modal, Tag } from 'antd';
|
||||
import { Modal, Tag } from 'antd';
|
||||
import { CircleAlert, X } from '@signozhq/icons';
|
||||
import KeyValueLabel from 'periscope/components/KeyValueLabel';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
@@ -9,6 +9,7 @@ import APIError from 'types/api/error';
|
||||
import ErrorContent from './components/ErrorContent';
|
||||
|
||||
import './ErrorModal.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
type Props = {
|
||||
error: APIError;
|
||||
@@ -73,10 +74,11 @@ function ErrorModal({
|
||||
<div className="error-modal__version-placeholder" />
|
||||
)}
|
||||
<Button
|
||||
type="default"
|
||||
className="close-button"
|
||||
onClick={handleClose}
|
||||
data-testid="close-button"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
<X size={16} color={Color.BG_VANILLA_400} />
|
||||
</Button>
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import {
|
||||
Button,
|
||||
Col,
|
||||
Dropdown,
|
||||
MenuProps,
|
||||
Popover,
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
} from 'antd';
|
||||
import { Col, Dropdown, MenuProps, Popover, Row, Select, Space } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import axios from 'axios';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
@@ -159,7 +151,6 @@ function ExplorerCard({
|
||||
],
|
||||
};
|
||||
|
||||
const saveButtonType = isQueryUpdated ? 'default' : 'primary';
|
||||
const saveButtonIcon = isQueryUpdated ? null : <Save size="md" />;
|
||||
|
||||
const showSaveView = false;
|
||||
@@ -210,7 +201,7 @@ function ExplorerCard({
|
||||
</Space>
|
||||
)}
|
||||
{isQueryUpdated && (
|
||||
<Button type="primary" icon={<Save />} onClick={onUpdateQueryHandler}>
|
||||
<Button onClick={onUpdateQueryHandler} prefix={<Save />}>
|
||||
Save changes
|
||||
</Button>
|
||||
)}
|
||||
@@ -230,9 +221,10 @@ function ExplorerCard({
|
||||
onOpenChange={handleOpenChange}
|
||||
>
|
||||
<Button
|
||||
type={saveButtonType}
|
||||
icon={saveButtonIcon}
|
||||
data-testid="traces-save-view-action"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={saveButtonIcon ?? undefined}
|
||||
>
|
||||
{isQueryUpdated
|
||||
? SaveButtonText.SAVE_AS_NEW_VIEW
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
import { Check, TableColumnsSplit, X } from '@signozhq/icons';
|
||||
import { FloatingPanel } from 'periscope/components/FloatingPanel';
|
||||
import { TelemetryFieldKey } from 'types/api/v5/queryRange';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
import AddedFields from './AddedFields';
|
||||
import OtherFields from './OtherFields';
|
||||
|
||||
import styles from './FieldsSelector.module.scss';
|
||||
|
||||
const DEFAULT_PANEL_WIDTH = 350;
|
||||
const DEFAULT_PANEL_HEIGHT_OFFSET = 100;
|
||||
const DEFAULT_PANEL_RIGHT_INSET = 100;
|
||||
const DEFAULT_PANEL_TOP_INSET = 50;
|
||||
|
||||
interface FieldsSelectorProps {
|
||||
isOpen: boolean;
|
||||
title: string;
|
||||
fields: TelemetryFieldKey[];
|
||||
onFieldsChange: (fields: TelemetryFieldKey[]) => void;
|
||||
onClose: () => void;
|
||||
signal: DataSource;
|
||||
maxFields?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
defaultPosition?: { x: number; y: number };
|
||||
}
|
||||
|
||||
function FieldsSelector({
|
||||
isOpen,
|
||||
title,
|
||||
fields,
|
||||
onFieldsChange,
|
||||
onClose,
|
||||
signal,
|
||||
maxFields,
|
||||
width = DEFAULT_PANEL_WIDTH,
|
||||
height,
|
||||
defaultPosition,
|
||||
}: FieldsSelectorProps): JSX.Element | null {
|
||||
if (!isOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const resolvedHeight =
|
||||
height ?? window.innerHeight - DEFAULT_PANEL_HEIGHT_OFFSET;
|
||||
const resolvedPosition = defaultPosition ?? {
|
||||
x: window.innerWidth - width - DEFAULT_PANEL_RIGHT_INSET,
|
||||
y: DEFAULT_PANEL_TOP_INSET,
|
||||
};
|
||||
const [draftFields, setDraftFields] = useState<TelemetryFieldKey[]>(fields);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [debouncedInputValue, setDebouncedInputValue] = useState('');
|
||||
|
||||
const debouncedUpdate = useDebouncedFn((value) => {
|
||||
setDebouncedInputValue(value as string);
|
||||
}, 400);
|
||||
|
||||
const handleInputChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const value = e.target.value.trim().toLowerCase();
|
||||
setInputValue(value);
|
||||
debouncedUpdate(value);
|
||||
},
|
||||
[debouncedUpdate],
|
||||
);
|
||||
|
||||
const handleAdd = useCallback(
|
||||
(field: TelemetryFieldKey): void => {
|
||||
if (maxFields !== undefined && draftFields.length >= maxFields) {
|
||||
return;
|
||||
}
|
||||
if (draftFields.some((f) => f.name === field.name)) {
|
||||
return;
|
||||
}
|
||||
setDraftFields((prev) => [...prev, field]);
|
||||
},
|
||||
[draftFields, maxFields],
|
||||
);
|
||||
|
||||
const handleSave = useCallback((): void => {
|
||||
onFieldsChange(draftFields);
|
||||
toast.success('Saved successfully', {
|
||||
position: 'top-right',
|
||||
});
|
||||
onClose();
|
||||
}, [draftFields, onFieldsChange, onClose]);
|
||||
|
||||
const handleDiscard = useCallback((): void => {
|
||||
setDraftFields(fields);
|
||||
}, [fields]);
|
||||
|
||||
const hasUnsavedChanges = useMemo(
|
||||
() =>
|
||||
!(
|
||||
draftFields.length === fields.length &&
|
||||
draftFields.every((f, i) => f.name === fields[i]?.name)
|
||||
),
|
||||
[draftFields, fields],
|
||||
);
|
||||
|
||||
const isAtLimit = maxFields !== undefined && draftFields.length >= maxFields;
|
||||
|
||||
return (
|
||||
<FloatingPanel
|
||||
isOpen
|
||||
width={width}
|
||||
height={resolvedHeight}
|
||||
defaultPosition={resolvedPosition}
|
||||
enableResizing={false}
|
||||
>
|
||||
<div className={styles.root}>
|
||||
<div className={styles.header}>
|
||||
<div className={styles.title}>
|
||||
<TableColumnsSplit size={16} />
|
||||
{title}
|
||||
</div>
|
||||
<X className={styles.closeIcon} size={16} onClick={onClose} />
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<Input
|
||||
className={styles.searchInput}
|
||||
type="text"
|
||||
value={inputValue}
|
||||
placeholder="Search for a field..."
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<AddedFields
|
||||
inputValue={inputValue}
|
||||
fields={draftFields}
|
||||
onFieldsChange={setDraftFields}
|
||||
maxFields={maxFields}
|
||||
/>
|
||||
|
||||
<OtherFields
|
||||
signal={signal}
|
||||
debouncedInputValue={debouncedInputValue}
|
||||
addedFields={draftFields}
|
||||
onAdd={handleAdd}
|
||||
isAtLimit={isAtLimit}
|
||||
/>
|
||||
|
||||
{hasUnsavedChanges && (
|
||||
<div className={styles.footer}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
onClick={handleDiscard}
|
||||
prefix={<X width={14} height={14} />}
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
<Button
|
||||
variant="solid"
|
||||
color="primary"
|
||||
onClick={handleSave}
|
||||
prefix={<Check width={14} height={14} />}
|
||||
>
|
||||
Save changes
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</FloatingPanel>
|
||||
);
|
||||
}
|
||||
|
||||
export default FieldsSelector;
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './FieldsSelector';
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import { Button, Input, Radio, RadioChangeEvent } from 'antd';
|
||||
import { Input, Radio, RadioChangeEvent } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { handleContactSupport } from 'container/Integrations/utils';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
@@ -125,11 +126,11 @@ function FeedbackModal({ onClose }: { onClose: () => void }): JSX.Element {
|
||||
|
||||
<div className="feedback-modal-content-footer">
|
||||
<Button
|
||||
className="periscope-btn primary"
|
||||
type="primary"
|
||||
onClick={handleSubmit}
|
||||
loading={isLoading}
|
||||
disabled={feedback.length === 0}
|
||||
variant="solid"
|
||||
color="primary"
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
|
||||
@@ -5,8 +5,6 @@ import { Button } from '@signozhq/ui/button';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import { Popover } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { AIAssistantEvents } from 'container/AIAssistant/events';
|
||||
import { normalizePage } from 'container/AIAssistant/hooks/useAIAssistantAnalyticsContext';
|
||||
import {
|
||||
openAIAssistant,
|
||||
useAIAssistantStore,
|
||||
@@ -52,14 +50,6 @@ function HeaderRightSection({
|
||||
setOpenAnnouncementsModal(false);
|
||||
}, [location.pathname]);
|
||||
|
||||
const handleOpenAIAssistant = useCallback((): void => {
|
||||
void logEvent(AIAssistantEvents.Opened, {
|
||||
source: 'header',
|
||||
currentPage: normalizePage(location.pathname),
|
||||
});
|
||||
openAIAssistant();
|
||||
}, [location.pathname]);
|
||||
|
||||
const handleOpenShareURLModal = useCallback((): void => {
|
||||
logEvent('Share: Clicked', {
|
||||
page: location.pathname,
|
||||
@@ -111,7 +101,7 @@ function HeaderRightSection({
|
||||
<Button
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
onClick={handleOpenAIAssistant}
|
||||
onClick={openAIAssistant}
|
||||
aria-label={
|
||||
showHeaderPendingBadge
|
||||
? pendingUserInputCount === 1
|
||||
@@ -166,12 +156,12 @@ function HeaderRightSection({
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
aria-label="Announcements"
|
||||
prefix={<Inbox size={14} />}
|
||||
onClick={(): void => {
|
||||
logEvent('Announcements: Clicked', {
|
||||
page: location.pathname,
|
||||
});
|
||||
}}
|
||||
prefix={<Inbox size={14} />}
|
||||
/>
|
||||
</Popover>
|
||||
)}
|
||||
|
||||
@@ -4,8 +4,9 @@ import { useSelector } from 'react-redux';
|
||||
import { matchPath, useLocation } from 'react-router-dom';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Switch } from 'antd';
|
||||
import { Switch } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
@@ -155,9 +156,10 @@ function ShareURLModal(): JSX.Element {
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="periscope-btn secondary"
|
||||
onClick={handleCopyURL}
|
||||
icon={isURLCopied ? <Check size={14} /> : <Link2 size={14} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={isURLCopied ? <Check size={14} /> : <Link2 size={14} />}
|
||||
>
|
||||
Copy page link
|
||||
</Button>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { CircleCheckBig, HandPlatter } from '@signozhq/icons';
|
||||
@@ -57,17 +57,18 @@ export default function WaitlistFragment({
|
||||
</Typography.Text>
|
||||
|
||||
<Button
|
||||
className="periscope-btn join-waitlist-btn"
|
||||
type="default"
|
||||
className="join-waitlist-btn"
|
||||
loading={isSubmitting}
|
||||
icon={
|
||||
onClick={handleJoinWaitlist}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={
|
||||
isSuccess ? (
|
||||
<CircleCheckBig size={16} color={Color.BG_FOREST_500} />
|
||||
) : (
|
||||
<HandPlatter size={16} />
|
||||
)
|
||||
}
|
||||
onClick={handleJoinWaitlist}
|
||||
>
|
||||
Get early access
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Input } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import cx from 'classnames';
|
||||
import { X } from '@signozhq/icons';
|
||||
|
||||
@@ -55,9 +56,12 @@ function InputWithLabel({
|
||||
{labelAfter && <Typography.Text className="label">{label}</Typography.Text>}
|
||||
{onClose && (
|
||||
<Button
|
||||
className="periscope-btn ghost close-btn"
|
||||
icon={closeIcon || <X size={16} />}
|
||||
className="close-btn"
|
||||
onClick={onClose}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={(closeIcon as JSX.Element) || <X size={16} />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
color: var(--bg-amber-500);
|
||||
border-color: var(--bg-amber-500);
|
||||
|
||||
> .ant-btn:hover {
|
||||
> button:hover {
|
||||
color: var(--bg-amber-400) !important;
|
||||
border-color: var(--bg-amber-300) !important;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useMutation } from 'react-query';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Button, Modal, Tooltip } from 'antd';
|
||||
import { Modal, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import updateCreditCardApi from 'api/v1/checkout/create';
|
||||
import cx from 'classnames';
|
||||
@@ -170,7 +171,9 @@ function LaunchChatSupport({
|
||||
<Button
|
||||
className={cx('periscope-btn', 'facing-issue-button', className)}
|
||||
onClick={handleFacingIssuesClick}
|
||||
icon={<CircleHelp size={14} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<CircleHelp size={14} />}
|
||||
>
|
||||
{buttonText || 'Facing issues?'}
|
||||
</Button>
|
||||
@@ -189,19 +192,19 @@ function LaunchChatSupport({
|
||||
key="cancel"
|
||||
onClick={(): void => setIsAddCreditCardModalOpen(false)}
|
||||
className="cancel-btn"
|
||||
icon={<X size={16} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<X size={16} />}
|
||||
>
|
||||
Cancel
|
||||
</Button>,
|
||||
<Button
|
||||
key="submit"
|
||||
type="primary"
|
||||
icon={<CreditCard size={16} />}
|
||||
size="middle"
|
||||
loading={isLoadingBilling}
|
||||
disabled={isLoadingBilling}
|
||||
onClick={handleAddCreditCard}
|
||||
className="add-credit-card-btn"
|
||||
prefix={<CreditCard size={16} />}
|
||||
>
|
||||
Add Credit Card
|
||||
</Button>,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import { ArrowUpRight } from '@signozhq/icons';
|
||||
import { openInNewTab } from 'utils/navigation';
|
||||
|
||||
import './LearnMore.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
type LearnMoreProps = {
|
||||
text?: string;
|
||||
@@ -19,7 +19,7 @@ function LearnMore({ text, url, onClick }: LearnMoreProps): JSX.Element {
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Button type="link" className="learn-more" onClick={handleClick}>
|
||||
<Button className="learn-more" onClick={handleClick} variant="link">
|
||||
<div className="learn-more__text">{text}</div>
|
||||
<ArrowUpRight size={16} color={Color.BG_ROBIN_400} />
|
||||
</Button>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
.log-detail-drawer__title-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
border-left: 1px solid var(--l1-border) !important;
|
||||
}
|
||||
|
||||
.ant-btn-default {
|
||||
button {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l2-background);
|
||||
|
||||
.ant-btn-default {
|
||||
button {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
padding: 9px;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { memo, MouseEventHandler } from 'react';
|
||||
import { Link, TextSelect } from '@signozhq/icons';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
|
||||
import './LogLinesActionButtons.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
export interface LogLinesActionButtonsProps {
|
||||
handleShowContext: MouseEventHandler<HTMLElement>;
|
||||
@@ -19,18 +20,22 @@ function LogLinesActionButtons({
|
||||
<div className={`log-line-action-buttons ${customClassName}`}>
|
||||
<Tooltip title="Show in Context">
|
||||
<Button
|
||||
size="small"
|
||||
icon={<TextSelect size={14} />}
|
||||
className="show-context-btn"
|
||||
onClick={handleShowContext}
|
||||
size="sm"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<TextSelect size={14} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title="Copy Link">
|
||||
<Button
|
||||
size="small"
|
||||
icon={<Link size={14} />}
|
||||
onClick={onLogCopy}
|
||||
className="copy-log-btn"
|
||||
size="sm"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<Link size={14} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Button, Input, InputNumber, Popover, Tooltip } from 'antd';
|
||||
import { Input, InputNumber, Popover, Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import cx from 'classnames';
|
||||
import { LogViewMode } from 'container/LogsTable';
|
||||
@@ -223,7 +224,7 @@ function OptionsMenu({
|
||||
<Button
|
||||
onClick={(): void => setIsFontSizeOptionsOpen(false)}
|
||||
className="back-btn"
|
||||
type="text"
|
||||
variant="ghost"
|
||||
>
|
||||
<ChevronLeft size={14} className="icon" />
|
||||
<Typography.Text className="text">Select font size</Typography.Text>
|
||||
@@ -235,7 +236,7 @@ function OptionsMenu({
|
||||
setFontSizeValue(FontSize.SMALL);
|
||||
}}
|
||||
className="option-btn"
|
||||
type="text"
|
||||
variant="ghost"
|
||||
>
|
||||
<Typography.Text className="text">{FontSize.SMALL}</Typography.Text>
|
||||
{fontSizeValue === FontSize.SMALL && (
|
||||
@@ -247,7 +248,7 @@ function OptionsMenu({
|
||||
setFontSizeValue(FontSize.MEDIUM);
|
||||
}}
|
||||
className="option-btn"
|
||||
type="text"
|
||||
variant="ghost"
|
||||
>
|
||||
<Typography.Text className="text">{FontSize.MEDIUM}</Typography.Text>
|
||||
{fontSizeValue === FontSize.MEDIUM && (
|
||||
@@ -259,7 +260,7 @@ function OptionsMenu({
|
||||
setFontSizeValue(FontSize.LARGE);
|
||||
}}
|
||||
className="option-btn"
|
||||
type="text"
|
||||
variant="ghost"
|
||||
>
|
||||
<Typography.Text className="text">{FontSize.LARGE}</Typography.Text>
|
||||
{fontSizeValue === FontSize.LARGE && (
|
||||
@@ -338,10 +339,10 @@ function OptionsMenu({
|
||||
<div className="title">Font Size</div>
|
||||
<Button
|
||||
className="value"
|
||||
type="text"
|
||||
onClick={(): void => {
|
||||
setIsFontSizeOptionsOpen(true);
|
||||
}}
|
||||
variant="ghost"
|
||||
>
|
||||
<Typography.Text className="font-value">{fontSizeValue}</Typography.Text>
|
||||
<ChevronRight size={14} className="icon" />
|
||||
@@ -472,9 +473,11 @@ function LogsFormatOptionsMenu({
|
||||
>
|
||||
<Tooltip title="Options">
|
||||
<Button
|
||||
className="periscope-btn ghost"
|
||||
icon={<SlidersVertical size="md" />}
|
||||
data-testid="periscope-btn-format-options"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<SlidersVertical size={14} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import { useOnboardingStatus } from 'hooks/messagingQueue/useOnboardingStatus';
|
||||
import { Bolt, FolderTree } from '@signozhq/icons';
|
||||
@@ -8,6 +7,7 @@ import { MessagingQueueHealthCheckService } from 'pages/MessagingQueues/Messagin
|
||||
import AttributeCheckList from './AttributeCheckList';
|
||||
|
||||
import './MessagingQueueHealthCheck.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
interface MessagingQueueHealthCheckProps {
|
||||
serviceToInclude: string[];
|
||||
@@ -94,7 +94,9 @@ function MessagingQueueHealthCheck({
|
||||
'config-btn',
|
||||
missingConfiguration ? 'missing-config-btn' : '',
|
||||
)}
|
||||
icon={<Bolt size={12} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<Bolt size={12} />}
|
||||
>
|
||||
<div className="config-btn-content">
|
||||
{missingConfiguration
|
||||
|
||||
@@ -18,8 +18,9 @@ import {
|
||||
RefreshCw,
|
||||
} from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Checkbox, Select } from 'antd';
|
||||
import { Checkbox, Select } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import cx from 'classnames';
|
||||
import TextToolTip from 'components/TextToolTip/TextToolTip';
|
||||
import { SOMETHING_WENT_WRONG } from 'constants/api';
|
||||
@@ -767,11 +768,11 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
<div className="option-badge">{capitalize(option.type)}</div>
|
||||
)}
|
||||
{option.value && ensureValidOption(option.value) && (
|
||||
<Button type="text" className="only-btn">
|
||||
<Button className="only-btn" variant="ghost">
|
||||
{currentToggleTagValue({ option: option.value })}
|
||||
</Button>
|
||||
)}
|
||||
<Button type="text" className="toggle-btn">
|
||||
<Button className="toggle-btn" variant="ghost">
|
||||
Toggle
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -13,12 +13,12 @@ import { javascript } from '@codemirror/lang-javascript';
|
||||
import { copilot } from '@uiw/codemirror-theme-copilot';
|
||||
import { githubLight } from '@uiw/codemirror-theme-github';
|
||||
import CodeMirror, { EditorView, keymap } from '@uiw/react-codemirror';
|
||||
import { Button } from 'antd';
|
||||
import { Having } from 'api/v5/v5';
|
||||
import { useQueryBuilderV2Context } from 'components/QueryBuilderV2/QueryBuilderV2Context';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { ChevronUp } from '@signozhq/icons';
|
||||
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
const havingOperators = [
|
||||
{
|
||||
@@ -368,9 +368,12 @@ function HavingFilter({
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
className="close-btn periscope-btn ghost"
|
||||
icon={<ChevronUp size={16} />}
|
||||
className="close-btn"
|
||||
onClick={onClose}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<ChevronUp size={16} />}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Button, Radio, RadioChangeEvent, Tooltip } from 'antd';
|
||||
import { Radio, RadioChangeEvent, Tooltip } from 'antd';
|
||||
import InputWithLabel from 'components/InputWithLabel/InputWithLabel';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { GroupByFilter } from 'container/QueryBuilder/filters/GroupByFilter/GroupByFilter';
|
||||
@@ -17,6 +17,7 @@ import HavingFilter from './HavingFilter/HavingFilter';
|
||||
import { buildDefaultLegendFromGroupBy } from './utils';
|
||||
|
||||
import './QueryAddOns.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
interface AddOn {
|
||||
icon: React.ReactNode;
|
||||
@@ -370,9 +371,12 @@ function QueryAddOns({
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
className="close-btn periscope-btn ghost"
|
||||
icon={<ChevronUp size={16} />}
|
||||
className="close-btn"
|
||||
onClick={(): void => handleRemoveView('group_by')}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<ChevronUp size={16} />}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -455,9 +459,12 @@ function QueryAddOns({
|
||||
</div>
|
||||
{!isListViewPanel && (
|
||||
<Button
|
||||
className="close-btn periscope-btn ghost"
|
||||
icon={<ChevronUp size={16} />}
|
||||
className="close-btn"
|
||||
onClick={(): void => handleRemoveView('order_by')}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<ChevronUp size={16} />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -488,9 +495,12 @@ function QueryAddOns({
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className="close-btn periscope-btn ghost"
|
||||
icon={<ChevronUp size={16} />}
|
||||
className="close-btn"
|
||||
onClick={(): void => handleRemoveView('reduce_to')}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<ChevronUp size={16} />}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@ import CodeMirror, {
|
||||
ViewPlugin,
|
||||
ViewUpdate,
|
||||
} from '@uiw/react-codemirror';
|
||||
import { Button, Popover, Tooltip } from 'antd';
|
||||
import { Popover, Tooltip } from 'antd';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import { QUERY_BUILDER_KEY_TYPES } from 'constants/antlrQueryConstants';
|
||||
import { QueryBuilderKeys } from 'constants/queryBuilder';
|
||||
@@ -36,6 +36,7 @@ import { TracesAggregatorOperator } from 'types/common/queryBuilder';
|
||||
import { useQueryBuilderV2Context } from '../../QueryBuilderV2Context';
|
||||
|
||||
import './QueryAggregation.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
const chipDecoration = Decoration.mark({
|
||||
class: 'chip-decorator',
|
||||
@@ -720,9 +721,10 @@ function QueryAggregationSelect({
|
||||
overlayClassName="query-aggregation-error-popover"
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<TriangleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
className="periscope-btn ghost query-aggregation-error-btn"
|
||||
className="query-aggregation-error-btn"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
prefix={<TriangleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import WarningPopover from 'components/WarningPopover/WarningPopover';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
@@ -56,9 +57,11 @@ function TraceOperatorSection({
|
||||
}
|
||||
>
|
||||
<Button
|
||||
className="add-trace-operator-button periscope-btn"
|
||||
icon={<DraftingCompass size={16} />}
|
||||
className="add-trace-operator-button"
|
||||
onClick={(): void => addTraceOperator?.()}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<DraftingCompass size={16} />}
|
||||
>
|
||||
<div className="qb-trace-operator-button-container-text">
|
||||
Add Trace Matching
|
||||
@@ -92,9 +95,12 @@ export default function QueryFooter({
|
||||
<div className="qb-add-new-query">
|
||||
<Tooltip title={<div style={{ textAlign: 'center' }}>Add New Query</div>}>
|
||||
<Button
|
||||
className="add-new-query-button periscope-btn "
|
||||
icon={<Plus size={16} />}
|
||||
className="add-new-query-button"
|
||||
onClick={addNewBuilderQuery}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<Plus size={16} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
@@ -118,9 +124,11 @@ export default function QueryFooter({
|
||||
}
|
||||
>
|
||||
<Button
|
||||
className="add-formula-button periscope-btn "
|
||||
icon={<Sigma size={16} />}
|
||||
className="add-formula-button"
|
||||
onClick={addNewFormula}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<Sigma size={16} />}
|
||||
>
|
||||
Add Formula
|
||||
</Button>
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Color } from '@signozhq/design-tokens';
|
||||
import { copilot } from '@uiw/codemirror-theme-copilot';
|
||||
import { githubLight } from '@uiw/codemirror-theme-github';
|
||||
import CodeMirror, { EditorView, keymap, Prec } from '@uiw/react-codemirror';
|
||||
import { Button, Card, Collapse, Popover, Tag, Tooltip } from 'antd';
|
||||
import { Card, Collapse, Popover, Tag, Tooltip } from 'antd';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion';
|
||||
import cx from 'classnames';
|
||||
@@ -49,6 +49,7 @@ import { queryExamples } from './constants';
|
||||
import { combineInitialAndUserExpression } from './utils';
|
||||
|
||||
import './QuerySearch.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
const { Panel } = Collapse;
|
||||
|
||||
@@ -1484,15 +1485,16 @@ function QuerySearch({
|
||||
>
|
||||
{validation.isValid ? (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<CircleCheck size="md" />}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="periscope-btn ghost"
|
||||
prefix={<CircleCheck size={14} />}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<TriangleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
className="periscope-btn ghost"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
prefix={<TriangleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
@@ -108,7 +109,7 @@ export default function TraceOperator({
|
||||
)}
|
||||
</div>
|
||||
<Tooltip title="Remove Trace Operator" placement="topLeft">
|
||||
<Button className="periscope-btn ghost" onClick={removeTraceOperator}>
|
||||
<Button onClick={removeTraceOperator} variant="outlined" color="secondary">
|
||||
<Trash2 size={14} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
@@ -15,7 +15,7 @@ import { Color } from '@signozhq/design-tokens';
|
||||
import { copilot } from '@uiw/codemirror-theme-copilot';
|
||||
import { githubLight } from '@uiw/codemirror-theme-github';
|
||||
import CodeMirror, { EditorView, keymap, Prec } from '@uiw/react-codemirror';
|
||||
import { Button, Popover } from 'antd';
|
||||
import { Popover } from 'antd';
|
||||
import cx from 'classnames';
|
||||
import {
|
||||
TRACE_OPERATOR_OPERATORS,
|
||||
@@ -34,6 +34,7 @@ import { getInvolvedQueriesInTraceOperator } from './utils/utils';
|
||||
|
||||
import '../QuerySearch/QuerySearch.styles.scss';
|
||||
import { CircleCheck, TriangleAlert } from '@signozhq/icons';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
// Custom extension to stop events
|
||||
const stopEventsExtension = EditorView.domEventHandlers({
|
||||
@@ -465,15 +466,15 @@ function TraceOperatorEditor({
|
||||
>
|
||||
{validation.isValid ? (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<CircleCheck size="md" />}
|
||||
className="periscope-btn ghost"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
prefix={<CircleCheck size={14} />}
|
||||
/>
|
||||
) : (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<TriangleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
className="periscope-btn ghost"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
prefix={<TriangleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import { Fragment, useMemo, useState } from 'react';
|
||||
import { Button, Checkbox, Input, Skeleton } from 'antd';
|
||||
import { Checkbox, Input, Skeleton } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { removeKeysFromExpression } from 'components/QueryBuilderV2/utils';
|
||||
@@ -660,14 +661,14 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
|
||||
{String(value)}
|
||||
</Typography.Text>
|
||||
)}
|
||||
<Button type="text" className="only-btn">
|
||||
<Button className="only-btn" variant="ghost">
|
||||
{isSomeFilterPresentForCurrentAttribute
|
||||
? currentFilterState[value] && !isMultipleValuesTrueForTheKey
|
||||
? 'All'
|
||||
: 'Only'
|
||||
: 'Only'}
|
||||
</Button>
|
||||
<Button type="text" className="toggle-btn">
|
||||
<Button className="toggle-btn" variant="ghost">
|
||||
Toggle
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import EmptyQuickFilterIcon from 'assets/CustomIcons/EmptyQuickFilterIcon';
|
||||
import { ArrowUpRight } from '@signozhq/icons';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
const QUICK_FILTER_DOC_PATHS: Record<string, string> = {
|
||||
severity_text: 'severity-text',
|
||||
@@ -39,9 +39,9 @@ function LogsQuickFilterEmptyState({
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="link"
|
||||
className="go-to-docs__button"
|
||||
onClick={handleLearnMoreClick}
|
||||
variant="link"
|
||||
>
|
||||
<div className="go-to-docs__button-text">Learn more</div>
|
||||
<ArrowUpRight size={14} color={Color.BG_ROBIN_400} />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Button, Collapse } from 'antd';
|
||||
import { Collapse } from 'antd';
|
||||
import {
|
||||
IQuickFiltersConfig,
|
||||
QuickFiltersSource,
|
||||
@@ -21,6 +21,7 @@ import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import './Duration.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
export type FilterType = Record<
|
||||
AllTraceFilterKeys,
|
||||
@@ -299,9 +300,9 @@ function Duration({
|
||||
/>
|
||||
{activeKeys.includes('durationNano') && (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={onClearHandler}
|
||||
data-testid="collapse-duration-clearBtn"
|
||||
variant="link"
|
||||
>
|
||||
Clear All
|
||||
</Button>
|
||||
|
||||
@@ -14,10 +14,10 @@ import {
|
||||
verticalListSortingStrategy,
|
||||
} from '@dnd-kit/sortable';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { Button } from 'antd';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import { GripVertical } from '@signozhq/icons';
|
||||
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function SortableFilter({
|
||||
filter,
|
||||
@@ -50,11 +50,13 @@ function SortableFilter({
|
||||
</div>
|
||||
{allowRemove && (
|
||||
<Button
|
||||
className="remove-filter-btn periscope-btn"
|
||||
size="small"
|
||||
className="remove-filter-btn"
|
||||
onClick={(): void => {
|
||||
onRemove(filter as FilterType);
|
||||
}}
|
||||
size="sm"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Button, Skeleton } from 'antd';
|
||||
import { Skeleton } from 'antd';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import { SIGNAL_DATA_SOURCE_MAP } from 'components/QuickFilters/QuickFiltersSettings/constants';
|
||||
import { SignalType } from 'components/QuickFilters/types';
|
||||
@@ -12,6 +12,7 @@ import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { QueryKeyDataSuggestionsProps } from 'types/api/querySuggestions/types';
|
||||
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function OtherFiltersSkeleton(): JSX.Element {
|
||||
return (
|
||||
@@ -146,9 +147,11 @@ function OtherFilters({
|
||||
<div key={filter.key} className="qf-filter-item other-filters-item">
|
||||
<div className="qf-filter-key">{filter.key}</div>
|
||||
<Button
|
||||
className="add-filter-btn periscope-btn"
|
||||
size="small"
|
||||
className="add-filter-btn"
|
||||
onClick={(): void => handleAddFilter(filter as FilterType)}
|
||||
size="sm"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Button, Input } from 'antd';
|
||||
import { Input } from 'antd';
|
||||
import { Check, TableColumnsSplit, X } from '@signozhq/icons';
|
||||
import { Filter as FilterType } from 'types/api/quickFilters/getCustomFilters';
|
||||
|
||||
@@ -9,6 +9,7 @@ import useQuickFilterSettings from './hooks/useQuickFilterSettings';
|
||||
import OtherFilters from './OtherFilters';
|
||||
|
||||
import './QuickFiltersSettings.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function QuickFiltersSettings({
|
||||
signal,
|
||||
@@ -86,17 +87,17 @@ function QuickFiltersSettings({
|
||||
{hasUnsavedChanges && (
|
||||
<div className="qf-footer">
|
||||
<Button
|
||||
type="default"
|
||||
onClick={handleDiscardChanges}
|
||||
icon={<X size={16} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<X size={16} />}
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSaveChanges}
|
||||
icon={<Check size={16} />}
|
||||
loading={isUpdatingCustomFilters}
|
||||
prefix={<Check size={16} />}
|
||||
>
|
||||
Save changes
|
||||
</Button>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import refreshPaymentStatus from 'api/v3/licenses/put';
|
||||
import cx from 'classnames';
|
||||
import { RefreshCcw } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function RefreshPaymentStatus({
|
||||
btnShape,
|
||||
type,
|
||||
}: {
|
||||
btnShape?: 'default' | 'round' | 'circle';
|
||||
type?: 'button' | 'text' | 'tooltip';
|
||||
}): JSX.Element {
|
||||
const { t } = useTranslation(['failedPayment']);
|
||||
@@ -35,12 +34,12 @@ function RefreshPaymentStatus({
|
||||
<span className="refresh-payment-status-btn-wrapper">
|
||||
<Tooltip title={type === 'tooltip' ? t('refreshPaymentStatus') : ''}>
|
||||
<Button
|
||||
type={type === 'text' ? 'text' : 'default'}
|
||||
shape={btnShape}
|
||||
className={cx('periscope-btn', { text: type === 'text' })}
|
||||
onClick={handleRefreshPaymentStatus}
|
||||
icon={<RefreshCcw size={14} />}
|
||||
loading={isLoading}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<RefreshCcw size={14} />}
|
||||
>
|
||||
{type !== 'tooltip' ? t('refreshPaymentStatus') : ''}
|
||||
</Button>
|
||||
@@ -49,7 +48,6 @@ function RefreshPaymentStatus({
|
||||
);
|
||||
}
|
||||
RefreshPaymentStatus.defaultProps = {
|
||||
btnShape: 'default',
|
||||
type: 'button',
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
TableColumnsType as ColumnsType,
|
||||
TableColumnType as ColumnType,
|
||||
} from 'antd';
|
||||
import { Button, Dropdown, Flex, MenuProps, Switch } from 'antd';
|
||||
import { Dropdown, Flex, MenuProps, Switch } from 'antd';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import LaunchChatSupport from 'components/LaunchChatSupport/LaunchChatSupport';
|
||||
import { useSafeNavigate } from 'hooks/useSafeNavigate';
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
} from './utils';
|
||||
|
||||
import './DynamicColumnTable.syles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function DynamicColumnTable({
|
||||
tablesource,
|
||||
@@ -133,9 +134,11 @@ function DynamicColumnTable({
|
||||
>
|
||||
<Button
|
||||
className="dynamicColumnTable-button filter-btn"
|
||||
size="middle"
|
||||
icon={<SlidersHorizontal size={14} />}
|
||||
data-testid="additional-filters-button"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<SlidersHorizontal size={14} />}
|
||||
/>
|
||||
</Dropdown>
|
||||
)}
|
||||
|
||||
@@ -144,7 +144,6 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
|
||||
loading={loading}
|
||||
notFoundContent={notFoundContent}
|
||||
options={options}
|
||||
optionFilterProp="label"
|
||||
optionRender={(option): JSX.Element => (
|
||||
<Checkbox
|
||||
checked={value.includes(option.value as string)}
|
||||
@@ -163,7 +162,6 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
|
||||
return (
|
||||
<Select
|
||||
id={id}
|
||||
showSearch
|
||||
value={value || undefined}
|
||||
onChange={onChange}
|
||||
placeholder={placeholder}
|
||||
@@ -172,7 +170,6 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
|
||||
loading={loading}
|
||||
notFoundContent={notFoundContent}
|
||||
options={options}
|
||||
optionFilterProp="label"
|
||||
getPopupContainer={getPopupContainer}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
@@ -28,7 +28,7 @@ const mockKey: ServiceaccounttypesGettableFactorAPIKeyDTO = {
|
||||
id: 'key-1',
|
||||
name: 'Original Key Name',
|
||||
expiresAt: 0,
|
||||
lastObservedAt: null as unknown as string,
|
||||
lastObservedAt: null as unknown as Date,
|
||||
serviceAccountId: 'sa-1',
|
||||
};
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ const keys: ServiceaccounttypesGettableFactorAPIKeyDTO[] = [
|
||||
id: 'key-1',
|
||||
name: 'Production Key',
|
||||
expiresAt: 0,
|
||||
lastObservedAt: null as unknown as string,
|
||||
lastObservedAt: null as unknown as Date,
|
||||
serviceAccountId: 'sa-1',
|
||||
},
|
||||
{
|
||||
id: 'key-2',
|
||||
name: 'Staging Key',
|
||||
expiresAt: 1924905600, // 2030-12-31
|
||||
lastObservedAt: '2026-03-10T10:00:00Z',
|
||||
lastObservedAt: new Date('2026-03-10T10:00:00Z'),
|
||||
serviceAccountId: 'sa-1',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
}
|
||||
|
||||
.ant-modal-footer {
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React, { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { Check, Plus, X } from '@signozhq/icons';
|
||||
import { Button, Flex, Tag } from 'antd';
|
||||
import { Flex, Tag } from 'antd';
|
||||
import Input from 'components/Input';
|
||||
|
||||
import './Tags.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function Tags({ tags, setTags }: AddTagsProps): JSX.Element {
|
||||
const [inputValue, setInputValue] = useState<string>('');
|
||||
@@ -71,19 +72,19 @@ function Tags({ tags, setTags }: AddTagsProps): JSX.Element {
|
||||
|
||||
<div className="confirm-cancel-actions">
|
||||
<Button
|
||||
type="primary"
|
||||
className="periscope-btn"
|
||||
size="small"
|
||||
icon={<Check size={14} />}
|
||||
onClick={handleInputConfirm}
|
||||
size="sm"
|
||||
prefix={<Check size={14} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
/>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
className="periscope-btn"
|
||||
size="small"
|
||||
icon={<X size={14} />}
|
||||
onClick={hideInput}
|
||||
size="sm"
|
||||
prefix={<X size={14} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -91,15 +92,14 @@ function Tags({ tags, setTags }: AddTagsProps): JSX.Element {
|
||||
|
||||
{!inputVisible && (
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
}}
|
||||
onClick={showInput}
|
||||
size="sm"
|
||||
prefix={<Plus size={14} />}
|
||||
>
|
||||
<Flex justify="center" align="center" gap={4}>
|
||||
<Plus size="md" />
|
||||
New Tag
|
||||
</Flex>
|
||||
</Button>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Dispatch, SetStateAction, useCallback, useMemo } from 'react';
|
||||
import { ChevronDown, Globe } from '@signozhq/icons';
|
||||
import { Button, Dropdown } from 'antd';
|
||||
import { Dropdown } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import TimeItems, {
|
||||
timePreferance,
|
||||
@@ -40,7 +41,7 @@ function TimePreference({
|
||||
className="time-selection-target"
|
||||
trigger={['click']}
|
||||
>
|
||||
<Button>
|
||||
<Button variant="outlined" color="secondary">
|
||||
<div className="button-selected-text">
|
||||
<Globe size={14} />
|
||||
<Typography.Text className="selected-value">
|
||||
|
||||
@@ -10,5 +10,4 @@ export enum FeatureKeys {
|
||||
ONBOARDING_V3 = 'onboarding_v3',
|
||||
DOT_METRICS_ENABLED = 'dot_metrics_enabled',
|
||||
USE_JSON_BODY = 'use_json_body',
|
||||
USE_FINE_GRAINED_AUTHZ = 'use_fine_grained_authz',
|
||||
}
|
||||
|
||||
@@ -108,7 +108,4 @@ export const REACT_QUERY_KEY = {
|
||||
|
||||
// Dashboard Grid Card Query Keys
|
||||
DASHBOARD_GRID_CARD_QUERY_RANGE: 'DASHBOARD_GRID_CARD_QUERY_RANGE',
|
||||
|
||||
// Fields Selector Query Keys
|
||||
GET_FIELDS_SELECTOR_SUGGESTIONS: 'GET_FIELDS_SELECTOR_SUGGESTIONS',
|
||||
} as const;
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { History, Maximize2, Minus, Plus, Sparkles, X } from '@signozhq/icons';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import HistorySidebar from '../components/ConversationsList';
|
||||
import ConversationView from '../ConversationView';
|
||||
import { AIAssistantEvents } from '../events';
|
||||
import {
|
||||
normalizePage,
|
||||
useAIAssistantAnalyticsContext,
|
||||
} from '../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../store/useAIAssistantStore';
|
||||
import { VariantContext } from '../VariantContext';
|
||||
|
||||
@@ -31,7 +24,6 @@ import styles from './AIAssistantModal.module.scss';
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
export default function AIAssistantModal(): JSX.Element | null {
|
||||
const history = useHistory();
|
||||
const { pathname } = useLocation();
|
||||
const [showHistory, setShowHistory] = useState(false);
|
||||
|
||||
const isOpen = useAIAssistantStore((s) => s.isModalOpen);
|
||||
@@ -44,7 +36,6 @@ export default function AIAssistantModal(): JSX.Element | null {
|
||||
const startNewConversation = useAIAssistantStore(
|
||||
(s) => s.startNewConversation,
|
||||
);
|
||||
const analyticsCtx = useAIAssistantAnalyticsContext();
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent): void => {
|
||||
@@ -64,10 +55,6 @@ export default function AIAssistantModal(): JSX.Element | null {
|
||||
} else {
|
||||
startNewConversation();
|
||||
setShowHistory(false);
|
||||
void logEvent(AIAssistantEvents.Opened, {
|
||||
source: 'shortcut',
|
||||
currentPage: normalizePage(pathname),
|
||||
});
|
||||
openModal();
|
||||
}
|
||||
return;
|
||||
@@ -81,7 +68,7 @@ export default function AIAssistantModal(): JSX.Element | null {
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return (): void => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, [isOpen, openModal, closeModal, startNewConversation, pathname]);
|
||||
}, [isOpen, openModal, closeModal, startNewConversation]);
|
||||
|
||||
// ── Handlers ────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -90,28 +77,15 @@ export default function AIAssistantModal(): JSX.Element | null {
|
||||
return;
|
||||
}
|
||||
closeModal();
|
||||
// Router state tells AIAssistantPage to skip its mount-time Opened fire:
|
||||
// the assistant was already open in the modal, so this is a surface
|
||||
// switch, not a new open.
|
||||
history.push(
|
||||
ROUTES.AI_ASSISTANT.replace(':conversationId', activeConversationId),
|
||||
{ fromInApp: true },
|
||||
);
|
||||
}, [activeConversationId, closeModal, history]);
|
||||
|
||||
const handleNew = useCallback(() => {
|
||||
void logEvent(AIAssistantEvents.NewChatClicked, {
|
||||
...analyticsCtx,
|
||||
// useAIAssistantAnalyticsContext() runs above this component's
|
||||
// VariantContext.Provider, so the hook reports the default 'page'
|
||||
// mode. Override here: the modal collapses to 'sidepane' in our
|
||||
// taxonomy alongside the drawer.
|
||||
mode: 'sidepane',
|
||||
source: 'header',
|
||||
});
|
||||
startNewConversation();
|
||||
setShowHistory(false);
|
||||
}, [startNewConversation, analyticsCtx]);
|
||||
}, [startNewConversation]);
|
||||
|
||||
const handleHistorySelect = useCallback(() => {
|
||||
setShowHistory(false);
|
||||
|
||||
@@ -5,12 +5,8 @@ import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { History, Maximize2, Plus, Sparkles, X } from '@signozhq/icons';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import ConversationsList from '../components/ConversationsList';
|
||||
import ConversationView from '../ConversationView';
|
||||
import { AIAssistantEvents } from '../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../store/useAIAssistantStore';
|
||||
import { VariantContext } from '../VariantContext';
|
||||
|
||||
@@ -36,35 +32,21 @@ export default function AIAssistantPanel(): JSX.Element | null {
|
||||
const startNewConversation = useAIAssistantStore(
|
||||
(s) => s.startNewConversation,
|
||||
);
|
||||
const analyticsCtx = useAIAssistantAnalyticsContext();
|
||||
|
||||
const handleExpand = useCallback(() => {
|
||||
if (!activeConversationId) {
|
||||
return;
|
||||
}
|
||||
closeDrawer();
|
||||
// Router state tells AIAssistantPage to skip its mount-time Opened fire:
|
||||
// the assistant was already open in the drawer, so this is a surface
|
||||
// switch, not a new open.
|
||||
history.push(
|
||||
ROUTES.AI_ASSISTANT.replace(':conversationId', activeConversationId),
|
||||
{ fromInApp: true },
|
||||
);
|
||||
}, [activeConversationId, closeDrawer, history]);
|
||||
|
||||
const handleNew = useCallback(() => {
|
||||
void logEvent(AIAssistantEvents.NewChatClicked, {
|
||||
...analyticsCtx,
|
||||
// useAIAssistantAnalyticsContext() runs above this component's
|
||||
// VariantContext.Provider, so the hook reports the default 'page'
|
||||
// mode. Override here: this handler only runs when the drawer
|
||||
// itself is mounted, which is unambiguously the sidepane surface.
|
||||
mode: 'sidepane',
|
||||
source: 'header',
|
||||
});
|
||||
startNewConversation();
|
||||
setShowHistory(false);
|
||||
}, [startNewConversation, analyticsCtx]);
|
||||
}, [startNewConversation]);
|
||||
|
||||
// When user picks a conversation from the list, close the sidebar
|
||||
const handleHistorySelect = useCallback(() => {
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { useCallback } from 'react';
|
||||
import { matchPath, useLocation } from 'react-router-dom';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { Bot } from '@signozhq/icons';
|
||||
|
||||
import { AIAssistantEvents } from '../events';
|
||||
import { normalizePage } from '../hooks/useAIAssistantAnalyticsContext';
|
||||
import {
|
||||
openAIAssistant,
|
||||
useAIAssistantStore,
|
||||
@@ -29,14 +25,6 @@ export default function AIAssistantTrigger(): JSX.Element | null {
|
||||
exact: true,
|
||||
});
|
||||
|
||||
const handleOpen = useCallback((): void => {
|
||||
void logEvent(AIAssistantEvents.Opened, {
|
||||
source: 'icon',
|
||||
currentPage: normalizePage(pathname),
|
||||
});
|
||||
openAIAssistant();
|
||||
}, [pathname]);
|
||||
|
||||
if (isDrawerOpen || isModalOpen || isFullScreenPage) {
|
||||
return null;
|
||||
}
|
||||
@@ -47,7 +35,7 @@ export default function AIAssistantTrigger(): JSX.Element | null {
|
||||
variant="solid"
|
||||
color="primary"
|
||||
className={styles.trigger}
|
||||
onClick={handleOpen}
|
||||
onClick={openAIAssistant}
|
||||
aria-label="Open AI Assistant"
|
||||
>
|
||||
<Bot size={20} />
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import cx from 'classnames';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import ChatInput, { autoContextKey } from '../components/ChatInput';
|
||||
import ConversationSkeleton from '../components/ConversationSkeleton';
|
||||
import VirtualizedMessages from '../components/VirtualizedMessages';
|
||||
import { AIAssistantEvents } from '../events';
|
||||
import { getAutoContexts } from '../getAutoContexts';
|
||||
import { useAIAssistantAnalyticsContext } from '../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../store/useAIAssistantStore';
|
||||
import { MessageAttachment } from '../types';
|
||||
import { MessageContext } from '../../../api/ai-assistant/chat';
|
||||
@@ -43,7 +39,6 @@ export default function ConversationView({
|
||||
);
|
||||
const sendMessage = useAIAssistantStore((s) => s.sendMessage);
|
||||
const cancelStream = useAIAssistantStore((s) => s.cancelStream);
|
||||
const analyticsCtx = useAIAssistantAnalyticsContext(conversationId);
|
||||
|
||||
// Auto-derived contexts come from the route the user is currently looking
|
||||
// at (dashboard detail, service metrics, an explorer, …). Skip when the
|
||||
@@ -87,50 +82,14 @@ export default function ConversationView({
|
||||
attachments?: MessageAttachment[],
|
||||
contexts?: MessageContext[],
|
||||
) => {
|
||||
const hasAuto = contexts?.some((c) => c.source === 'auto') ?? false;
|
||||
const hasManual = contexts?.some((c) => c.source === 'mention') ?? false;
|
||||
let contextType: 'manual' | 'auto' | 'both' | undefined;
|
||||
if (hasAuto && hasManual) {
|
||||
contextType = 'both';
|
||||
} else if (hasAuto) {
|
||||
contextType = 'auto';
|
||||
} else if (hasManual) {
|
||||
contextType = 'manual';
|
||||
}
|
||||
void logEvent(AIAssistantEvents.MessageSent, {
|
||||
...analyticsCtx,
|
||||
queryLength: text.length,
|
||||
hasContext: hasAuto || hasManual,
|
||||
contextType,
|
||||
respondingToClarification: Boolean(pendingClarificationHere),
|
||||
});
|
||||
void sendMessage(text, attachments, contexts);
|
||||
},
|
||||
[sendMessage, analyticsCtx, pendingClarificationHere],
|
||||
[sendMessage],
|
||||
);
|
||||
|
||||
// Wall-clock timestamp of the current streaming start, used to compute
|
||||
// `secondsSinceStart` on Cancel clicked. Cleared whenever streaming ends.
|
||||
const streamStartedAtRef = useRef<number | null>(null);
|
||||
useEffect(() => {
|
||||
if (!isStreamingHere) {
|
||||
streamStartedAtRef.current = null;
|
||||
return;
|
||||
}
|
||||
if (streamStartedAtRef.current === null) {
|
||||
streamStartedAtRef.current = Date.now();
|
||||
}
|
||||
}, [isStreamingHere]);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
const startedAt = streamStartedAtRef.current;
|
||||
void logEvent(AIAssistantEvents.CancelClicked, {
|
||||
threadId: analyticsCtx.threadId,
|
||||
secondsSinceStart:
|
||||
startedAt !== null ? Math.round((Date.now() - startedAt) / 1000) : null,
|
||||
});
|
||||
cancelStream(conversationId);
|
||||
}, [cancelStream, conversationId, analyticsCtx.threadId]);
|
||||
}, [cancelStream, conversationId]);
|
||||
|
||||
const messages = conversation?.messages ?? [];
|
||||
const showDisclaimer = messages.length > 0;
|
||||
@@ -175,7 +134,6 @@ export default function ConversationView({
|
||||
conversationId={conversationId}
|
||||
messages={messages}
|
||||
isStreaming={isStreamingHere}
|
||||
onSendSuggestedPrompt={(text): void => handleSend(text)}
|
||||
/>
|
||||
{showDisclaimer && (
|
||||
<div className={disclaimerClass} role="note" aria-live="polite">
|
||||
|
||||
@@ -41,68 +41,12 @@ import {
|
||||
Undo,
|
||||
} from '@signozhq/icons';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import { AIAssistantEvents, SuggestedPromptCategory } from '../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../../store/useAIAssistantStore';
|
||||
|
||||
import styles from './ActionsSection.module.scss';
|
||||
|
||||
interface ActionsSectionProps {
|
||||
actions: MessageActionDTO[];
|
||||
/** ID of the assistant message these actions belong to — used in analytics. */
|
||||
messageId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resource-type strings the backend uses for `open_resource` and rollback
|
||||
* actions. Centralized here so the route/module lookups below stay in sync.
|
||||
*/
|
||||
const ResourceType = {
|
||||
dashboard: 'dashboard',
|
||||
alert: 'alert',
|
||||
service: 'service',
|
||||
saved_view: 'saved_view',
|
||||
logs_explorer: 'logs_explorer',
|
||||
traces_explorer: 'traces_explorer',
|
||||
metrics_explorer: 'metrics_explorer',
|
||||
} as const;
|
||||
|
||||
/** Maps an open_resource action's resourceType to its product module name. */
|
||||
function targetModuleForResource(resourceType: string): string | null {
|
||||
switch (resourceType) {
|
||||
case ResourceType.dashboard:
|
||||
return 'dashboards';
|
||||
case ResourceType.alert:
|
||||
return 'alerts';
|
||||
case ResourceType.service:
|
||||
return 'apm';
|
||||
case ResourceType.saved_view:
|
||||
return 'savedViews';
|
||||
case ResourceType.logs_explorer:
|
||||
return 'logs';
|
||||
case ResourceType.traces_explorer:
|
||||
return 'traces';
|
||||
case ResourceType.metrics_explorer:
|
||||
return 'metrics';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Maps an apply_filter signal to its product module name. */
|
||||
function targetModuleForSignal(signal: ApplyFilterSignalDTO): string | null {
|
||||
switch (signal) {
|
||||
case ApplyFilterSignalDTO.logs:
|
||||
return 'logs';
|
||||
case ApplyFilterSignalDTO.traces:
|
||||
return 'traces';
|
||||
case ApplyFilterSignalDTO.metrics:
|
||||
return 'metrics';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
type ChipState = 'idle' | 'loading' | 'success' | 'error';
|
||||
@@ -150,23 +94,23 @@ function resourceRoute(
|
||||
resourceId: string,
|
||||
): string | null {
|
||||
switch (resourceType) {
|
||||
case ResourceType.dashboard:
|
||||
case 'dashboard':
|
||||
return ROUTES.DASHBOARD.replace(':dashboardId', resourceId);
|
||||
case ResourceType.alert: {
|
||||
case 'alert': {
|
||||
const params = new URLSearchParams({ [QueryParams.ruleId]: resourceId });
|
||||
return `${ROUTES.EDIT_ALERTS}?${params.toString()}`;
|
||||
}
|
||||
case ResourceType.service:
|
||||
case 'service':
|
||||
return ROUTES.SERVICE_METRICS.replace(':servicename', resourceId);
|
||||
case ResourceType.saved_view:
|
||||
case 'saved_view':
|
||||
// No detail route — saved views land on the list page.
|
||||
// Caller may provide signal-aware metadata in future; default to logs.
|
||||
return ROUTES.LOGS_SAVE_VIEWS;
|
||||
case ResourceType.logs_explorer:
|
||||
case 'logs_explorer':
|
||||
return ROUTES.LOGS_EXPLORER;
|
||||
case ResourceType.traces_explorer:
|
||||
case 'traces_explorer':
|
||||
return ROUTES.TRACES_EXPLORER;
|
||||
case ResourceType.metrics_explorer:
|
||||
case 'metrics_explorer':
|
||||
return ROUTES.METRICS_EXPLORER_EXPLORER;
|
||||
default:
|
||||
return null;
|
||||
@@ -280,24 +224,6 @@ function actionKey(action: MessageActionDTO, index: number): string {
|
||||
: `${action.kind}:${action.label}:${index}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the prompt to send for a follow_up action. The chip's `label` is
|
||||
* the short display text (e.g. "Python setup"); the real prompt lives in
|
||||
* `input.intent` per the schema doc. Falls back to label defensively so a
|
||||
* malformed server payload doesn't drop the click silently. Both branches
|
||||
* are trimmed so whitespace-only payloads don't become whitespace messages.
|
||||
*/
|
||||
function followUpIntent(action: MessageActionDTO): string {
|
||||
const intent = action.input?.intent;
|
||||
if (typeof intent === 'string') {
|
||||
const trimmed = intent.trim();
|
||||
if (trimmed.length > 0) {
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
return action.label.trim();
|
||||
}
|
||||
|
||||
/** Maps a signal to its target explorer route. */
|
||||
function explorerRouteForSignal(signal: ApplyFilterSignalDTO): string | null {
|
||||
switch (signal) {
|
||||
@@ -427,12 +353,10 @@ function rollbackCall(
|
||||
*/
|
||||
export default function ActionsSection({
|
||||
actions,
|
||||
messageId,
|
||||
}: ActionsSectionProps): JSX.Element | null {
|
||||
const history = useHistory();
|
||||
const { pathname } = useLocation();
|
||||
const sendMessage = useAIAssistantStore((s) => s.sendMessage);
|
||||
const { threadId, page, mode } = useAIAssistantAnalyticsContext();
|
||||
const { redirectWithQueryBuilderData, handleSetQueryData } = useQueryBuilder();
|
||||
|
||||
// Per-chip click state, keyed by chip key (see `key` below). Persists
|
||||
@@ -506,39 +430,13 @@ export default function ActionsSection({
|
||||
switch (action.kind) {
|
||||
case MessageActionKindDTO.open_docs: {
|
||||
if (action.url) {
|
||||
void logEvent(AIAssistantEvents.DocOpened, {
|
||||
threadId,
|
||||
messageId,
|
||||
docPath: action.url,
|
||||
});
|
||||
openInNewTab(action.url);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MessageActionKindDTO.follow_up: {
|
||||
const intent = followUpIntent(action);
|
||||
if (intent) {
|
||||
// Fire SuggestedPromptClicked + MessageSent so analytics can compute
|
||||
// both the click-through rate against follow-ups offered *and* keep
|
||||
// the unified send funnel intact. `category` distinguishes server-
|
||||
// emitted follow-ups from the empty-state grid. `promptId` stays the
|
||||
// label so dashboards group identical chip texts together regardless
|
||||
// of the dynamic intent payload.
|
||||
void logEvent(AIAssistantEvents.SuggestedPromptClicked, {
|
||||
threadId,
|
||||
messageId,
|
||||
promptId: action.label,
|
||||
category: SuggestedPromptCategory.FollowUp,
|
||||
});
|
||||
void logEvent(AIAssistantEvents.MessageSent, {
|
||||
threadId,
|
||||
page,
|
||||
mode,
|
||||
queryLength: intent.length,
|
||||
hasContext: false,
|
||||
respondingToClarification: false,
|
||||
});
|
||||
void sendMessage(intent);
|
||||
if (action.label) {
|
||||
void sendMessage(action.label);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -546,12 +444,6 @@ export default function ActionsSection({
|
||||
if (action.resourceType && action.resourceId) {
|
||||
const path = resourceRoute(action.resourceType, action.resourceId);
|
||||
if (path) {
|
||||
void logEvent(AIAssistantEvents.ResourceOpened, {
|
||||
threadId,
|
||||
messageId,
|
||||
targetModule: targetModuleForResource(action.resourceType),
|
||||
resourceId: action.resourceId,
|
||||
});
|
||||
history.push(path);
|
||||
}
|
||||
}
|
||||
@@ -564,13 +456,6 @@ export default function ActionsSection({
|
||||
break;
|
||||
}
|
||||
case MessageActionKindDTO.apply_filter: {
|
||||
if (action.signal) {
|
||||
void logEvent(AIAssistantEvents.ApplyFilterClicked, {
|
||||
threadId,
|
||||
messageId,
|
||||
targetModule: targetModuleForSignal(action.signal),
|
||||
});
|
||||
}
|
||||
applyFilter(action, {
|
||||
history,
|
||||
pathname,
|
||||
|
||||
@@ -5,17 +5,13 @@ import { Badge } from '@signozhq/ui/badge';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Input } from '@signozhq/ui/input';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@signozhq/ui/popover';
|
||||
import { toast } from '@signozhq/ui/sonner';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import type { UploadFile } from 'antd';
|
||||
import getSessionStorage from 'api/browser/sessionstorage/get';
|
||||
import setSessionStorage from 'api/browser/sessionstorage/set';
|
||||
import {
|
||||
getListRulesQueryKey,
|
||||
useListRules,
|
||||
} from 'api/generated/services/rules';
|
||||
import type { ListRules200 } from 'api/generated/services/sigNoz.schemas';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
||||
import { useQueryService } from 'hooks/useQueryService';
|
||||
@@ -26,8 +22,6 @@ import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
|
||||
import { AIAssistantEvents, getBrowserInfo } from '../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useSpeechRecognition } from '../../hooks/useSpeechRecognition';
|
||||
import { MessageAttachment } from '../../types';
|
||||
import { MessageContext } from '../../../../api/ai-assistant/chat';
|
||||
@@ -143,8 +137,6 @@ function autoContextCategory(ctx: MessageContext): string {
|
||||
const MAX_INPUT_LENGTH = 20000;
|
||||
const WARNING_THRESHOLD = 15000;
|
||||
const HOME_SERVICES_INTERVAL = 30 * 60 * 1000;
|
||||
/** sessionStorage key for the "voice input failed this tab" flag. */
|
||||
const VOICE_UNAVAILABLE_KEY = 'ai-assistant-voice-unavailable';
|
||||
|
||||
const CONTEXT_CATEGORIES = ['Dashboards', 'Alerts', 'Services'] as const;
|
||||
|
||||
@@ -376,28 +368,6 @@ export default function ChatInput({
|
||||
|
||||
// ── Voice input ────────────────────────────────────────────────────────────
|
||||
|
||||
const analyticsCtx = useAIAssistantAnalyticsContext();
|
||||
// Captured at the start of a voice session, consumed when it ends.
|
||||
// Tracks both the trigger (button vs. PTT shortcut) and the wall-clock
|
||||
// start time so we can attribute `durationMs` on the Voice input used
|
||||
// event regardless of which control ended the session.
|
||||
const voiceStartedAtRef = useRef<number | null>(null);
|
||||
const voiceSourceRef = useRef<'button' | 'shortcut' | null>(null);
|
||||
// Set to true after a `network`, `not-allowed`, or `not-supported` failure
|
||||
// so we hide the mic button for the rest of the tab session — silent
|
||||
// retries don't help, and Chromium derivatives without the Google Speech
|
||||
// API key always fail with `network` no matter how many times the user
|
||||
// clicks. Persisted to sessionStorage so a page reload doesn't surface the
|
||||
// button again (closing the tab still resets, in case the user fixed
|
||||
// permissions or switched browsers).
|
||||
const [voiceUnavailable, setVoiceUnavailable] = useState(
|
||||
() => getSessionStorage(VOICE_UNAVAILABLE_KEY) === 'true',
|
||||
);
|
||||
const markVoiceUnavailable = useCallback((): void => {
|
||||
setVoiceUnavailable(true);
|
||||
setSessionStorage(VOICE_UNAVAILABLE_KEY, 'true');
|
||||
}, []);
|
||||
|
||||
const {
|
||||
isListening,
|
||||
isSupported,
|
||||
@@ -418,81 +388,9 @@ export default function ChatInput({
|
||||
setText(capText(committedTextRef.current + separator + transcriptText));
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
// Guard against double-fire: Chrome can fire `onerror` more than
|
||||
// once per session when `continuous = true` (it retries internally
|
||||
// before giving up). Only fire the analytics event for the first
|
||||
// error in a given session — voiceSourceRef being null means we've
|
||||
// already handled it.
|
||||
const source = voiceSourceRef.current;
|
||||
if (source === null) {
|
||||
return;
|
||||
}
|
||||
voiceStartedAtRef.current = null;
|
||||
voiceSourceRef.current = null;
|
||||
void logEvent(AIAssistantEvents.VoiceInputFailed, {
|
||||
...analyticsCtx,
|
||||
...getBrowserInfo(),
|
||||
source,
|
||||
errorType: error,
|
||||
});
|
||||
if (error === 'network') {
|
||||
markVoiceUnavailable();
|
||||
toast.error('Voice input unavailable in this browser', {
|
||||
description:
|
||||
'This browser cannot reach the speech recognition service. Try Google Chrome or Microsoft Edge.',
|
||||
});
|
||||
} else if (error === 'not-allowed') {
|
||||
markVoiceUnavailable();
|
||||
toast.error('Microphone access denied', {
|
||||
description:
|
||||
'Grant microphone permission in your browser settings to use voice input.',
|
||||
});
|
||||
} else if (error === 'not-supported') {
|
||||
markVoiceUnavailable();
|
||||
toast.error('Voice input is not supported in this browser.');
|
||||
}
|
||||
// `no-speech` is benign (just silence) — don't toast or hide.
|
||||
},
|
||||
});
|
||||
|
||||
const showMic = isSupported && micPermission !== 'denied' && !voiceUnavailable;
|
||||
|
||||
const startVoiceInput = useCallback(
|
||||
(source: 'button' | 'shortcut') => {
|
||||
// Defense in depth: the button is hidden when `voiceUnavailable` is
|
||||
// true, but the PTT shortcut listener can still call us. Bailing here
|
||||
// keeps a single source of truth and prevents repeat `Voice input
|
||||
// failed` events in the same session.
|
||||
if (voiceUnavailable) {
|
||||
return;
|
||||
}
|
||||
voiceStartedAtRef.current = Date.now();
|
||||
voiceSourceRef.current = source;
|
||||
start();
|
||||
},
|
||||
[start, voiceUnavailable],
|
||||
);
|
||||
|
||||
const fireVoiceInputEvent = useCallback(
|
||||
(outcome: 'sent' | 'discarded') => {
|
||||
const startedAt = voiceStartedAtRef.current;
|
||||
const source = voiceSourceRef.current;
|
||||
voiceStartedAtRef.current = null;
|
||||
voiceSourceRef.current = null;
|
||||
if (startedAt === null || source === null) {
|
||||
return;
|
||||
}
|
||||
void logEvent(AIAssistantEvents.VoiceInputUsed, {
|
||||
...analyticsCtx,
|
||||
...getBrowserInfo(),
|
||||
source,
|
||||
outcome,
|
||||
durationMs: Date.now() - startedAt,
|
||||
});
|
||||
},
|
||||
[analyticsCtx],
|
||||
);
|
||||
const showMic = isSupported && micPermission !== 'denied';
|
||||
|
||||
// Stop recording and immediately send whatever is in the textarea.
|
||||
const handleStopAndSend = useCallback(async () => {
|
||||
@@ -500,17 +398,15 @@ export default function ChatInput({
|
||||
committedTextRef.current = capText(text);
|
||||
// Stop recognition without triggering onTranscript again (would double-append).
|
||||
discard();
|
||||
fireVoiceInputEvent('sent');
|
||||
await handleSend();
|
||||
}, [text, discard, handleSend, capText, fireVoiceInputEvent]);
|
||||
}, [text, discard, handleSend, capText]);
|
||||
|
||||
// Stop recording and revert the textarea to what it was before voice started.
|
||||
const handleDiscard = useCallback(() => {
|
||||
discard();
|
||||
fireVoiceInputEvent('discarded');
|
||||
setText(committedTextRef.current);
|
||||
textareaRef.current?.focus();
|
||||
}, [discard, fireVoiceInputEvent]);
|
||||
}, [discard]);
|
||||
|
||||
// ── Push-to-talk (Cmd/Ctrl + Shift + Space) ────────────────────────────────
|
||||
// Hold the combo to record; release Space to submit. We track which key
|
||||
@@ -519,7 +415,7 @@ export default function ChatInput({
|
||||
// "session active" ref so a held key only calls `start()` once.
|
||||
const pttActiveRef = useRef(false);
|
||||
useEffect(() => {
|
||||
if (!isSupported || micPermission === 'denied' || voiceUnavailable) {
|
||||
if (!isSupported || micPermission === 'denied') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -536,7 +432,7 @@ export default function ChatInput({
|
||||
return; // ignore auto-repeat
|
||||
}
|
||||
pttActiveRef.current = true;
|
||||
startVoiceInput('shortcut');
|
||||
start();
|
||||
};
|
||||
|
||||
const handleKeyUp = (e: KeyboardEvent): void => {
|
||||
@@ -570,10 +466,9 @@ export default function ChatInput({
|
||||
}, [
|
||||
isSupported,
|
||||
micPermission,
|
||||
voiceUnavailable,
|
||||
disabled,
|
||||
isStreaming,
|
||||
startVoiceInput,
|
||||
start,
|
||||
handleStopAndSend,
|
||||
]);
|
||||
|
||||
@@ -1008,7 +903,7 @@ export default function ChatInput({
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(): void => startVoiceInput('button')}
|
||||
onClick={start}
|
||||
disabled={disabled}
|
||||
aria-label="Start voice input"
|
||||
className={styles.micBtn}
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from '@signozhq/ui/select';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { ClarificationFieldTypeDTO } from 'api/ai-assistant/sigNozAIAssistantAPI.schemas';
|
||||
import type {
|
||||
ClarificationEventDTO,
|
||||
@@ -17,8 +16,6 @@ import type {
|
||||
} from 'api/ai-assistant/sigNozAIAssistantAPI.schemas';
|
||||
import { CircleHelp, Send, X } from '@signozhq/icons';
|
||||
|
||||
import { AIAssistantEvents } from '../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../../store/useAIAssistantStore';
|
||||
|
||||
import styles from './ClarificationForm.module.scss';
|
||||
@@ -47,8 +44,6 @@ export default function ClarificationForm({
|
||||
const isStreaming = useAIAssistantStore(
|
||||
(s) => s.streams[conversationId]?.isStreaming ?? false,
|
||||
);
|
||||
const { threadId, page, mode } =
|
||||
useAIAssistantAnalyticsContext(conversationId);
|
||||
|
||||
const fields = clarification.fields ?? [];
|
||||
const initialAnswers = Object.fromEntries(
|
||||
@@ -65,18 +60,6 @@ export default function ClarificationForm({
|
||||
|
||||
const handleSubmit = async (): Promise<void> => {
|
||||
setSubmitted(true);
|
||||
// Approximate queryLength as the JSON encoding of the form answers — the
|
||||
// clarification API doesn't render a single user-visible string, but the
|
||||
// JSON size is a reasonable stand-in for "how much did the user provide".
|
||||
const queryLength = JSON.stringify(answers).length;
|
||||
void logEvent(AIAssistantEvents.MessageSent, {
|
||||
threadId,
|
||||
page,
|
||||
mode,
|
||||
queryLength,
|
||||
hasContext: false,
|
||||
respondingToClarification: true,
|
||||
});
|
||||
await submitClarification(
|
||||
conversationId,
|
||||
clarification.clarificationId,
|
||||
@@ -86,10 +69,6 @@ export default function ClarificationForm({
|
||||
|
||||
const handleCancel = (): void => {
|
||||
setCancelled(true);
|
||||
void logEvent(AIAssistantEvents.CancelClicked, {
|
||||
threadId,
|
||||
secondsSinceStart: null,
|
||||
});
|
||||
cancelStream(conversationId);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@ import { Input } from '@signozhq/ui/input';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import { Plus, Search } from '@signozhq/icons';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import { AIAssistantEvents } from '../../events';
|
||||
import { useAIAssistantStore } from '../../store/useAIAssistantStore';
|
||||
import { Conversation } from '../../types';
|
||||
import { useVariant } from '../../VariantContext';
|
||||
@@ -139,17 +136,6 @@ export default function ConversationsList({
|
||||
|
||||
const handleSelect = (id: string): void => {
|
||||
const conv = conversations[id];
|
||||
// Skip re-selecting the currently active thread — Notion-style click on
|
||||
// the highlighted row in the history list shouldn't inflate the funnel.
|
||||
const isReselectingActive = id === activeConversationId;
|
||||
if (conv?.threadId && !isReselectingActive) {
|
||||
void logEvent(AIAssistantEvents.ThreadOpenedFromHistory, {
|
||||
threadId: conv.threadId,
|
||||
threadAgeDays: Math.floor(
|
||||
(Date.now() - conv.createdAt) / (24 * 60 * 60 * 1000),
|
||||
),
|
||||
});
|
||||
}
|
||||
if (conv?.threadId) {
|
||||
// Always load from backend — refreshes messages and reconnects
|
||||
// to active execution if the thread is still busy.
|
||||
|
||||
@@ -144,7 +144,7 @@ export default function MessageBubble({
|
||||
)}
|
||||
|
||||
{!isUser && message.actions && message.actions.length > 0 && (
|
||||
<ActionsSection actions={message.actions} messageId={message.id} />
|
||||
<ActionsSection actions={message.actions} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,10 +8,6 @@ import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { Check, Copy, RefreshCw, ThumbsDown, ThumbsUp } from '@signozhq/icons';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import { AIAssistantEvents } from '../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../../store/useAIAssistantStore';
|
||||
import { FeedbackRating, Message } from '../../types';
|
||||
|
||||
@@ -58,7 +54,6 @@ export default function MessageFeedback({
|
||||
const submitMessageFeedback = useAIAssistantStore(
|
||||
(s) => s.submitMessageFeedback,
|
||||
);
|
||||
const { threadId } = useAIAssistantAnalyticsContext();
|
||||
|
||||
const { formatTimezoneAdjustedTimestamp } = useTimezone();
|
||||
|
||||
@@ -96,21 +91,10 @@ export default function MessageFeedback({
|
||||
}, [message.createdAt]);
|
||||
|
||||
const handleCopy = useCallback((): void => {
|
||||
void logEvent(AIAssistantEvents.MessageCopied, {
|
||||
role: message.role,
|
||||
messageId: message.id,
|
||||
hadToolCalls: Boolean(message.blocks?.some((b) => b.type === 'tool_call')),
|
||||
});
|
||||
copyToClipboard(message.content);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1500);
|
||||
}, [
|
||||
copyToClipboard,
|
||||
message.content,
|
||||
message.id,
|
||||
message.role,
|
||||
message.blocks,
|
||||
]);
|
||||
}, [copyToClipboard, message.content]);
|
||||
|
||||
const handleVote = useCallback(
|
||||
(rating: FeedbackRating): void => {
|
||||
@@ -123,31 +107,20 @@ export default function MessageFeedback({
|
||||
return;
|
||||
}
|
||||
setVote(rating);
|
||||
void logEvent(AIAssistantEvents.FeedbackSubmitted, {
|
||||
messageId: message.id,
|
||||
threadId,
|
||||
rating: 'up',
|
||||
hasComment: false,
|
||||
commentLength: 0,
|
||||
});
|
||||
submitMessageFeedback(message.id, rating);
|
||||
},
|
||||
[vote, message.id, submitMessageFeedback, threadId],
|
||||
[vote, message.id, submitMessageFeedback],
|
||||
);
|
||||
|
||||
const handleSubmitNegative = useCallback((): void => {
|
||||
setVote('negative');
|
||||
setIsNegativeDialogOpen(false);
|
||||
const trimmed = negativeComment.trim();
|
||||
void logEvent(AIAssistantEvents.FeedbackSubmitted, {
|
||||
messageId: message.id,
|
||||
threadId,
|
||||
rating: 'down',
|
||||
hasComment: trimmed.length > 0,
|
||||
commentLength: trimmed.length,
|
||||
});
|
||||
submitMessageFeedback(message.id, 'negative', trimmed || undefined);
|
||||
}, [message.id, negativeComment, submitMessageFeedback, threadId]);
|
||||
submitMessageFeedback(
|
||||
message.id,
|
||||
'negative',
|
||||
negativeComment.trim() || undefined,
|
||||
);
|
||||
}, [message.id, negativeComment, submitMessageFeedback]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -4,9 +4,6 @@ import { Button } from '@signozhq/ui/button';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import { Check, Copy } from '@signozhq/icons';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import { AIAssistantEvents } from '../../events';
|
||||
import { Message } from '../../types';
|
||||
|
||||
import styles from './UserMessageActions.module.scss';
|
||||
@@ -28,15 +25,10 @@ export default function UserMessageActions({
|
||||
const [, copyToClipboard] = useCopyToClipboard();
|
||||
|
||||
const handleCopy = useCallback((): void => {
|
||||
void logEvent(AIAssistantEvents.MessageCopied, {
|
||||
role: message.role,
|
||||
messageId: message.id,
|
||||
hadToolCalls: false,
|
||||
});
|
||||
copyToClipboard(message.content);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 1500);
|
||||
}, [copyToClipboard, message.content, message.id, message.role]);
|
||||
}, [copyToClipboard, message.content]);
|
||||
|
||||
return (
|
||||
<div className={styles.actions}>
|
||||
|
||||
@@ -10,10 +10,6 @@ import {
|
||||
Sparkles,
|
||||
} from '@signozhq/icons';
|
||||
|
||||
import logEvent from 'api/common/logEvent';
|
||||
|
||||
import { AIAssistantEvents, SuggestedPromptCategory } from '../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../../store/useAIAssistantStore';
|
||||
import { Message, StreamingEventItem } from '../../types';
|
||||
import MessageBubble from '../MessageBubble';
|
||||
@@ -50,24 +46,17 @@ interface VirtualizedMessagesProps {
|
||||
conversationId: string;
|
||||
messages: Message[];
|
||||
isStreaming: boolean;
|
||||
/**
|
||||
* Called when a user clicks an empty-state suggested prompt. Routed
|
||||
* through the parent so analytics (Message sent) fire with the same
|
||||
* page/mode/context attribution as a normal send.
|
||||
*/
|
||||
onSendSuggestedPrompt: (text: string) => void;
|
||||
}
|
||||
|
||||
export default function VirtualizedMessages({
|
||||
conversationId,
|
||||
messages,
|
||||
isStreaming,
|
||||
onSendSuggestedPrompt,
|
||||
}: VirtualizedMessagesProps): JSX.Element {
|
||||
const sendMessage = useAIAssistantStore((s) => s.sendMessage);
|
||||
const regenerateAssistantMessage = useAIAssistantStore(
|
||||
(s) => s.regenerateAssistantMessage,
|
||||
);
|
||||
const { threadId } = useAIAssistantAnalyticsContext(conversationId);
|
||||
const streamingStatus = useAIAssistantStore(
|
||||
(s) => s.streams[conversationId]?.streamingStatus ?? '',
|
||||
);
|
||||
@@ -96,13 +85,9 @@ export default function VirtualizedMessages({
|
||||
if (isStreaming) {
|
||||
return;
|
||||
}
|
||||
void logEvent(AIAssistantEvents.RegenerateClicked, {
|
||||
messageId,
|
||||
threadId,
|
||||
});
|
||||
void regenerateAssistantMessage(conversationId, messageId);
|
||||
},
|
||||
[conversationId, isStreaming, regenerateAssistantMessage, threadId],
|
||||
[conversationId, isStreaming, regenerateAssistantMessage],
|
||||
);
|
||||
|
||||
// Scroll all the way to the actual bottom — including the 64px of bottom
|
||||
@@ -161,11 +146,7 @@ export default function VirtualizedMessages({
|
||||
color="secondary"
|
||||
className={styles.emptyChip}
|
||||
onClick={(): void => {
|
||||
void logEvent(AIAssistantEvents.SuggestedPromptClicked, {
|
||||
promptId: s.text,
|
||||
category: SuggestedPromptCategory.EmptyState,
|
||||
});
|
||||
onSendSuggestedPrompt(s.text);
|
||||
sendMessage(s.text);
|
||||
}}
|
||||
prefix={<s.icon size={14} />}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import cx from 'classnames';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { Check, X } from '@signozhq/icons';
|
||||
|
||||
import { AIAssistantEvents } from '../../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../../../store/useAIAssistantStore';
|
||||
import { useMessageContext } from '../../MessageContext';
|
||||
|
||||
@@ -40,7 +37,6 @@ export default function ConfirmBlock({
|
||||
const answeredBlocks = useAIAssistantStore((s) => s.answeredBlocks);
|
||||
const markBlockAnswered = useAIAssistantStore((s) => s.markBlockAnswered);
|
||||
const sendMessage = useAIAssistantStore((s) => s.sendMessage);
|
||||
const { threadId, page, mode } = useAIAssistantAnalyticsContext();
|
||||
|
||||
// Durable answered state — survives re-renders/remounts
|
||||
const answeredChoice = messageId ? answeredBlocks[messageId] : undefined;
|
||||
@@ -51,14 +47,6 @@ export default function ConfirmBlock({
|
||||
if (messageId) {
|
||||
markBlockAnswered(messageId, choice);
|
||||
}
|
||||
void logEvent(AIAssistantEvents.MessageSent, {
|
||||
threadId,
|
||||
page,
|
||||
mode,
|
||||
queryLength: responseText.length,
|
||||
hasContext: false,
|
||||
respondingToClarification: false,
|
||||
});
|
||||
sendMessage(responseText);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { useState } from 'react';
|
||||
import cx from 'classnames';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { Checkbox, Radio } from 'antd';
|
||||
|
||||
import { AIAssistantEvents } from '../../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../../hooks/useAIAssistantAnalyticsContext';
|
||||
import { useAIAssistantStore } from '../../../store/useAIAssistantStore';
|
||||
import { useMessageContext } from '../../MessageContext';
|
||||
|
||||
@@ -39,7 +36,6 @@ export default function InteractiveQuestion({
|
||||
const answeredBlocks = useAIAssistantStore((s) => s.answeredBlocks);
|
||||
const markBlockAnswered = useAIAssistantStore((s) => s.markBlockAnswered);
|
||||
const sendMessage = useAIAssistantStore((s) => s.sendMessage);
|
||||
const { threadId, page, mode } = useAIAssistantAnalyticsContext();
|
||||
|
||||
// Persist selected state locally only for the pending (not-yet-submitted) case
|
||||
const [selected, setSelected] = useState<string[]>([]);
|
||||
@@ -56,14 +52,6 @@ export default function InteractiveQuestion({
|
||||
if (messageId) {
|
||||
markBlockAnswered(messageId, answer);
|
||||
}
|
||||
void logEvent(AIAssistantEvents.MessageSent, {
|
||||
threadId,
|
||||
page,
|
||||
mode,
|
||||
queryLength: answer.length,
|
||||
hasContext: false,
|
||||
respondingToClarification: false,
|
||||
});
|
||||
sendMessage(answer);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Analytics event names for the AI Assistant feature. Backend-emitted events
|
||||
* (Execution finished, Approval resolved, Resource mutated, Clarification
|
||||
* requested, Limit hit) are not declared here — they fire from the AI service.
|
||||
*/
|
||||
|
||||
export interface BrowserInfo {
|
||||
browserName: string;
|
||||
browserVersion: string;
|
||||
}
|
||||
|
||||
type NavigatorWithBrandHints = Navigator & {
|
||||
userAgentData?: { brands: { brand: string; version: string }[] };
|
||||
brave?: { isBrave: () => Promise<boolean> };
|
||||
};
|
||||
|
||||
/**
|
||||
* We mainly need to distinguish Chrome / Edge (Speech API works) from Chromium
|
||||
* derivatives (no Google API key → voice fails with `network`). UA sniffing is
|
||||
* the source of truth for derivative identification; `userAgentData` is used
|
||||
* only as a fast happy path for Chrome / Edge. Brave needs its own probe — it
|
||||
* advertises Chrome in both UA and brand hints.
|
||||
*/
|
||||
export function getBrowserInfo(): BrowserInfo {
|
||||
if (typeof navigator === 'undefined') {
|
||||
return { browserName: 'unknown', browserVersion: 'unknown' };
|
||||
}
|
||||
const nav = navigator as NavigatorWithBrandHints;
|
||||
const ua = nav.userAgent;
|
||||
|
||||
// Order matters: derivatives put "Chrome" in their UA; Chrome puts "Safari".
|
||||
const matchers: { name: string; re: RegExp }[] = [
|
||||
{ name: 'Edge', re: /Edg(?:e|A|iOS)?\/([\d.]+)/ },
|
||||
{ name: 'Opera', re: /OPR\/([\d.]+)/ },
|
||||
{ name: 'Vivaldi', re: /Vivaldi\/([\d.]+)/ },
|
||||
{ name: 'Chrome', re: /Chrome\/([\d.]+)/ },
|
||||
{ name: 'Firefox', re: /Firefox\/([\d.]+)/ },
|
||||
{ name: 'Safari', re: /Version\/([\d.]+).*Safari/ },
|
||||
];
|
||||
let browserName = 'unknown';
|
||||
let browserVersion = 'unknown';
|
||||
for (const { name, re } of matchers) {
|
||||
const m = ua.match(re);
|
||||
if (m) {
|
||||
browserName = name;
|
||||
browserVersion = m[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Brave hides as Chrome in UA + brand hints; its probe is the only tell.
|
||||
if (nav.brave?.isBrave) {
|
||||
browserName = 'Brave';
|
||||
}
|
||||
|
||||
return { browserName, browserVersion };
|
||||
}
|
||||
|
||||
export const SuggestedPromptCategory = {
|
||||
FollowUp: 'follow_up',
|
||||
EmptyState: 'empty_state',
|
||||
} as const;
|
||||
export type SuggestedPromptCategory =
|
||||
(typeof SuggestedPromptCategory)[keyof typeof SuggestedPromptCategory];
|
||||
|
||||
export enum AIAssistantEvents {
|
||||
Opened = 'AI Assistant: Opened',
|
||||
MessageSent = 'AI Assistant: Message sent',
|
||||
SuggestedPromptClicked = 'AI Assistant: Suggested prompt clicked',
|
||||
CancelClicked = 'AI Assistant: Cancel clicked',
|
||||
RegenerateClicked = 'AI Assistant: Regenerate clicked',
|
||||
MessageCopied = 'AI Assistant: Message copied',
|
||||
FeedbackSubmitted = 'AI Assistant: Feedback submitted',
|
||||
ResourceOpened = 'AI Assistant: Resource opened',
|
||||
DocOpened = 'AI Assistant: Doc opened',
|
||||
ApplyFilterClicked = 'AI Assistant: Apply filter clicked',
|
||||
ThreadOpenedFromHistory = 'AI Assistant: Thread opened from history',
|
||||
VoiceInputUsed = 'AI Assistant: Voice input used',
|
||||
VoiceInputFailed = 'AI Assistant: Voice input failed',
|
||||
NewChatClicked = 'AI Assistant: New chat clicked',
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import { matchPath, useLocation } from 'react-router-dom';
|
||||
|
||||
import ROUTES from 'constants/routes';
|
||||
|
||||
import { useAIAssistantStore } from '../store/useAIAssistantStore';
|
||||
import { useVariant } from '../VariantContext';
|
||||
|
||||
export interface AIAssistantAnalyticsContext {
|
||||
/** Backend thread ID for the resolved conversation; undefined before the first send. */
|
||||
threadId: string | undefined;
|
||||
/**
|
||||
* Normalised route template for the current page (e.g. `/dashboard/:dashboardId`).
|
||||
* Falls back to the raw pathname for routes not in ROUTES. We normalise to keep
|
||||
* analytics cardinality bounded and avoid leaking customer identifiers
|
||||
* (dashboard IDs, service names, trace IDs, conversation IDs) into the event.
|
||||
*/
|
||||
page: string;
|
||||
/** Surface the assistant is rendered on. `panel` / `modal` collapse to `sidepane`. */
|
||||
mode: 'sidepane' | 'full_screen';
|
||||
}
|
||||
|
||||
// Pre-sorted longest-first so more specific templates match before their
|
||||
// less specific siblings (e.g. `/services/:s/top-level-operations` wins
|
||||
// over `/services/:s`). Module-level — ROUTES is static.
|
||||
const ROUTE_TEMPLATES = Object.values(ROUTES).sort(
|
||||
(a, b) => b.length - a.length,
|
||||
);
|
||||
|
||||
export function normalizePage(pathname: string): string {
|
||||
for (const template of ROUTE_TEMPLATES) {
|
||||
if (matchPath(pathname, { path: template, exact: true })) {
|
||||
return template;
|
||||
}
|
||||
}
|
||||
return pathname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared base attributes for AI Assistant analytics events (Message sent,
|
||||
* Cancel clicked, Feedback submitted, Resource/Doc/Apply filter, …).
|
||||
*
|
||||
* Pass `conversationId` when the caller is scoped to a specific
|
||||
* conversation (e.g. `ClarificationForm`, `VirtualizedMessages`); omit
|
||||
* to fall back to the store's active conversation.
|
||||
*/
|
||||
export function useAIAssistantAnalyticsContext(
|
||||
conversationId?: string,
|
||||
): AIAssistantAnalyticsContext {
|
||||
const { pathname } = useLocation();
|
||||
const variant = useVariant();
|
||||
const threadId = useAIAssistantStore((s) => {
|
||||
const id = conversationId ?? s.activeConversationId;
|
||||
return id ? s.conversations[id]?.threadId : undefined;
|
||||
});
|
||||
return {
|
||||
threadId,
|
||||
page: normalizePage(pathname),
|
||||
mode: variant === 'page' ? 'full_screen' : 'sidepane',
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import history from 'lib/history';
|
||||
import { ArrowRight } from '@signozhq/icons';
|
||||
@@ -11,6 +10,7 @@ import { TopContributorsCardProps } from './types';
|
||||
import ViewAllDrawer from './ViewAllDrawer';
|
||||
|
||||
import './TopContributorsCard.styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function TopContributorsCard({
|
||||
topContributorsData,
|
||||
@@ -52,7 +52,11 @@ function TopContributorsCard({
|
||||
<div className="top-contributors-card__header">
|
||||
<div className="title">top contributors</div>
|
||||
{topContributorsData.length > 3 && (
|
||||
<Button type="text" className="view-all" onClick={toggleViewAllDrawer}>
|
||||
<Button
|
||||
className="view-all"
|
||||
onClick={toggleViewAllDrawer}
|
||||
variant="ghost"
|
||||
>
|
||||
<div className="label">View all</div>
|
||||
<div className="icon">
|
||||
<ArrowRight
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { Button } from 'antd';
|
||||
import type { ColumnsType } from 'antd/lib/table';
|
||||
import { ResizeTable } from 'components/ResizeTable';
|
||||
import ROUTES from 'constants/routes';
|
||||
@@ -12,6 +11,7 @@ import { useAppContext } from 'providers/App/App';
|
||||
import { Channels } from 'types/api/channels/getAll';
|
||||
|
||||
import Delete from './Delete';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element {
|
||||
const { t } = useTranslation(['channels']);
|
||||
@@ -51,7 +51,7 @@ function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element {
|
||||
width: 80,
|
||||
render: (id: string): JSX.Element => (
|
||||
<>
|
||||
<Button onClick={(): void => onClickEditHandler(id)} type="link">
|
||||
<Button onClick={(): void => onClickEditHandler(id)} variant="link">
|
||||
{t('column_channel_edit')}
|
||||
</Button>
|
||||
<Delete id={id} notifications={notifications} />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import { Button } from 'antd';
|
||||
import type { NotificationInstance } from 'antd/es/notification/interface';
|
||||
import deleteChannel from 'api/channels/delete';
|
||||
import APIError from 'types/api/error';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function Delete({ notifications, id }: DeleteProps): JSX.Element {
|
||||
const { t } = useTranslation(['channels']);
|
||||
@@ -38,8 +38,8 @@ function Delete({ notifications, id }: DeleteProps): JSX.Element {
|
||||
<Button
|
||||
loading={loading}
|
||||
disabled={loading}
|
||||
type="link"
|
||||
onClick={onClickHandler}
|
||||
variant="link"
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -5,7 +6,7 @@ import { useQueries } from 'react-query';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { Button, Card, Input, Space, TableProps, Tooltip, Flex } from 'antd';
|
||||
import { Card, Input, Space, TableProps, Tooltip, Flex } from 'antd';
|
||||
import { Search } from '@signozhq/icons';
|
||||
import type { ColumnType, TablePaginationConfig } from 'antd/es/table';
|
||||
import type { FilterValue, SorterResult } from 'antd/es/table/interface';
|
||||
@@ -266,9 +267,8 @@ function AllErrors(): JSX.Element {
|
||||
onPressEnter={handleSearch(confirm, String(selectedKeys[0]), filterKey)}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSearch(confirm, String(selectedKeys[0]), filterKey)}
|
||||
size="small"
|
||||
size="sm"
|
||||
>
|
||||
<Flex align="center" justify="center" gap={4}>
|
||||
<Search size="md" />
|
||||
|
||||
@@ -706,7 +706,7 @@
|
||||
.views-tabs {
|
||||
color: var(--l2-foreground);
|
||||
|
||||
.ant-btn {
|
||||
button {
|
||||
box-shadow: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Spacing } from '@signozhq/design-tokens';
|
||||
import { Button, Divider, Drawer, Radio } from 'antd';
|
||||
import { Divider, Drawer, Radio } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { RadioChangeEvent } from 'antd/lib';
|
||||
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
|
||||
@@ -24,6 +25,7 @@ import EndPointDetails from './EndPointDetails';
|
||||
import TopErrors from './TopErrors';
|
||||
|
||||
import './DomainDetails.styles.scss';
|
||||
import ButtonGroup from 'periscope/components/ButtonGroup/ButtonGroup';
|
||||
|
||||
const TimeRangeOffset = 1000000000;
|
||||
|
||||
@@ -176,7 +178,7 @@ function DomainDetails({
|
||||
modalInitialStartTime={modalTimeRange.startTime * 1000}
|
||||
modalInitialEndTime={modalTimeRange.endTime * 1000}
|
||||
/>
|
||||
<Button.Group className="domain-details-drawer-header-ctas">
|
||||
<ButtonGroup className="domain-details-drawer-header-ctas">
|
||||
<Button
|
||||
className="domain-navigate-cta"
|
||||
onClick={(): void => {
|
||||
@@ -185,9 +187,12 @@ function DomainDetails({
|
||||
setEndPointsGroupBy([]);
|
||||
setSelectedView(VIEW_TYPES.ALL_ENDPOINTS);
|
||||
}}
|
||||
icon={<ArrowUp size={16} />}
|
||||
disabled={selectedDomainIndex === 0}
|
||||
title="Previous domain"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<ArrowUp size={16} />}
|
||||
/>
|
||||
<Button
|
||||
className="domain-navigate-cta"
|
||||
@@ -197,11 +202,14 @@ function DomainDetails({
|
||||
setEndPointsGroupBy([]);
|
||||
setSelectedView(VIEW_TYPES.ALL_ENDPOINTS);
|
||||
}}
|
||||
icon={<ArrowDown size={16} />}
|
||||
disabled={selectedDomainIndex === domainListLength - 1}
|
||||
title="Next domain"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<ArrowDown size={16} />}
|
||||
/>
|
||||
</Button.Group>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { RotateCw } from '@signozhq/icons';
|
||||
|
||||
@@ -22,7 +22,9 @@ function ErrorState({ refetch }: { refetch: () => void }): JSX.Element {
|
||||
<Button
|
||||
className="refresh-cta"
|
||||
onClick={(): void => refetch()}
|
||||
icon={<RotateCw size={16} />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
prefix={<RotateCw size={16} />}
|
||||
>
|
||||
Refresh this panel
|
||||
</Button>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Card, Skeleton } from 'antd';
|
||||
import { Card, Skeleton } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { useNavigateToExplorer } from 'components/CeleryTask/useNavigateToExplorer';
|
||||
@@ -29,6 +30,7 @@ import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
|
||||
import ErrorState from './ErrorState';
|
||||
import { prepareStatusCodeBarChartsConfig } from './utils';
|
||||
import ButtonGroup from 'periscope/components/ButtonGroup/ButtonGroup';
|
||||
|
||||
function StatusCodeBarCharts({
|
||||
endPointStatusCodeBarChartsDataQuery,
|
||||
@@ -247,23 +249,25 @@ function StatusCodeBarCharts({
|
||||
<Card bordered className="endpoint-details-card">
|
||||
<div className="header">
|
||||
<Typography.Text>Call response status</Typography.Text>
|
||||
<Button.Group className="views-tabs">
|
||||
<ButtonGroup className="views-tabs">
|
||||
<Button
|
||||
value={0}
|
||||
className={currentWidgetInfoIndex === 0 ? 'selected_view tab' : 'tab'}
|
||||
disabled={false}
|
||||
onClick={(): void => setCurrentWidgetInfoIndex(0)}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Number of calls
|
||||
</Button>
|
||||
<Button
|
||||
value={1}
|
||||
className={currentWidgetInfoIndex === 1 ? 'selected_view tab' : 'tab'}
|
||||
onClick={(): void => setCurrentWidgetInfoIndex(1)}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
Latency
|
||||
</Button>
|
||||
</Button.Group>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<div className="graph-container" ref={graphRef}>
|
||||
{renderCardContent(endPointStatusCodeBarChartsDataQuery)}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -6,7 +7,6 @@ import { CircleCheck, CloudDownload } from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Flex,
|
||||
@@ -445,12 +445,11 @@ export default function BillingContainer(): JSX.Element {
|
||||
</Flex>
|
||||
<Flex gap={8}>
|
||||
<Button
|
||||
type="default"
|
||||
size="middle"
|
||||
loading={isLoadingBilling || isLoadingManageBilling}
|
||||
disabled={isLoading || isFetchingBillingData}
|
||||
onClick={handleCsvDownload}
|
||||
className="periscope-btn"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
<Flex align="center" justify="center" gap={4}>
|
||||
<CloudDownload size="md" />
|
||||
@@ -459,8 +458,6 @@ export default function BillingContainer(): JSX.Element {
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="header-billing-button"
|
||||
type="primary"
|
||||
size="middle"
|
||||
loading={isLoadingBilling || isLoadingManageBilling}
|
||||
disabled={isLoading}
|
||||
onClick={handleBilling}
|
||||
@@ -584,8 +581,6 @@ export default function BillingContainer(): JSX.Element {
|
||||
<Col span={4} style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button
|
||||
data-testid="upgrade-plan-button"
|
||||
type="primary"
|
||||
size="middle"
|
||||
loading={isLoadingBilling || isLoadingManageBilling}
|
||||
onClick={handleBilling}
|
||||
>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { memo, useMemo } from 'react';
|
||||
import { ChevronLeft, ChevronRight } from '@signozhq/icons';
|
||||
import { Button, Flex, Select } from 'antd';
|
||||
import { Flex, Select } from 'antd';
|
||||
import { DEFAULT_PER_PAGE_OPTIONS, Pagination } from 'hooks/queryPagination';
|
||||
import { popupContainer } from 'utils/selectPopupContainer';
|
||||
|
||||
import { defaultSelectStyle } from './config';
|
||||
import { Container } from './styles';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function Controls({
|
||||
offset = 0,
|
||||
@@ -37,10 +38,10 @@ function Controls({
|
||||
<Container>
|
||||
<Button
|
||||
loading={isLoading}
|
||||
size="small"
|
||||
type="link"
|
||||
disabled={isPreviousDisabled}
|
||||
onClick={handleNavigatePrevious}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<Flex align="center" gap="4px">
|
||||
<ChevronLeft size={16} /> Previous
|
||||
@@ -48,10 +49,10 @@ function Controls({
|
||||
</Button>
|
||||
<Button
|
||||
loading={isLoading}
|
||||
size="small"
|
||||
type="link"
|
||||
disabled={isNextDisabled}
|
||||
onClick={handleNavigateNext}
|
||||
size="sm"
|
||||
variant="link"
|
||||
>
|
||||
<Flex align="center" gap="4px">
|
||||
Next <ChevronRight size={16} />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useQuery } from 'react-query';
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import getAllChannels from 'api/channels/getAll';
|
||||
import classNames from 'classnames';
|
||||
import { ChartLine } from '@signozhq/icons';
|
||||
@@ -16,6 +16,7 @@ import AnomalyThreshold from './AnomalyThreshold';
|
||||
import { ANOMALY_TAB_TOOLTIP, THRESHOLD_TAB_TOOLTIP } from './constants';
|
||||
|
||||
import './styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function AlertCondition(): JSX.Element {
|
||||
const { alertType, setAlertType } = useCreateAlertState();
|
||||
@@ -82,6 +83,8 @@ function AlertCondition(): JSX.Element {
|
||||
handleAlertTypeChange(tab.value as AlertTypes);
|
||||
}
|
||||
}}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
{tab.icon}
|
||||
{tab.label}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Button, Select, Tooltip } from 'antd';
|
||||
import { Select, Tooltip } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import classNames from 'classnames';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
@@ -294,11 +295,11 @@ function AlertThreshold({
|
||||
/>
|
||||
))}
|
||||
<Button
|
||||
type="dashed"
|
||||
icon={<Plus size={16} />}
|
||||
onClick={addThreshold}
|
||||
className="add-threshold-btn"
|
||||
data-testid="add-threshold-button"
|
||||
variant="dashed"
|
||||
prefix={<Plus size={16} />}
|
||||
>
|
||||
Add Threshold
|
||||
</Button>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Button, Input, Select, Tooltip } from 'antd';
|
||||
import { Input, Select, Tooltip } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { CircleX, Trash } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
@@ -9,6 +10,7 @@ import { AlertThresholdOperator } from '../context/types';
|
||||
import { normalizeOperator } from '../utils';
|
||||
import { ThresholdItemProps } from './types';
|
||||
import { NotificationChannelsNotFoundContent } from './utils';
|
||||
import ButtonGroup from 'periscope/components/ButtonGroup/ButtonGroup';
|
||||
|
||||
function ThresholdItem({
|
||||
threshold,
|
||||
@@ -166,16 +168,18 @@ function ThresholdItem({
|
||||
/>
|
||||
<Tooltip title="Remove recovery threshold">
|
||||
<Button
|
||||
type="default"
|
||||
icon={<Trash size={16} />}
|
||||
onClick={removeRecoveryThreshold}
|
||||
className="icon-btn"
|
||||
data-testid="remove-recovery-threshold-button"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<Trash size={16} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
<Button.Group>
|
||||
<ButtonGroup>
|
||||
{/* TODO: Add recovery threshold back once the functionality is implemented */}
|
||||
{/* {!showRecoveryThreshold && (
|
||||
<Tooltip title="Add recovery threshold">
|
||||
@@ -190,15 +194,17 @@ function ThresholdItem({
|
||||
{showRemoveButton && (
|
||||
<Tooltip title="Remove threshold">
|
||||
<Button
|
||||
type="default"
|
||||
icon={<CircleX size={16} />}
|
||||
onClick={(): void => removeThreshold(threshold.id)}
|
||||
className="icon-btn"
|
||||
data-testid="remove-threshold-button"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
size="icon"
|
||||
prefix={<CircleX size={16} />}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Button.Group>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -333,7 +333,7 @@
|
||||
}
|
||||
|
||||
.condensed-evaluation-settings-container {
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 240px;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Button, Flex, SelectProps, Switch } from 'antd';
|
||||
import { Flex, SelectProps, Switch } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { BaseOptionType, DefaultOptionType } from 'antd/es/select';
|
||||
import { getInvolvedQueriesInTraceOperator } from 'components/QueryBuilderV2/QueryV2/TraceOperator/utils/utils';
|
||||
@@ -388,10 +389,10 @@ export function NotificationChannelsNotFoundContent({
|
||||
Create one
|
||||
<Button
|
||||
style={{ padding: '0 4px' }}
|
||||
type="link"
|
||||
onClick={(): void => {
|
||||
openInNewTab(ROUTES.CHANNELS_NEW);
|
||||
}}
|
||||
variant="link"
|
||||
>
|
||||
here.
|
||||
</Button>
|
||||
@@ -400,7 +401,7 @@ export function NotificationChannelsNotFoundContent({
|
||||
<Typography.Text>Please ask your admin to create one.</Typography.Text>
|
||||
)}
|
||||
</Flex>
|
||||
<Button type="text" onClick={refreshChannels}>
|
||||
<Button onClick={refreshChannels} variant="ghost">
|
||||
Refresh
|
||||
</Button>
|
||||
</Flex>
|
||||
@@ -429,10 +430,10 @@ export function RoutingPolicyBanner({
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="link"
|
||||
className="view-routing-policies-button"
|
||||
data-testid="view-routing-policies-button"
|
||||
onClick={(): void => safeNavigate(ROUTING_POLICIES_ROUTE)}
|
||||
variant="link"
|
||||
>
|
||||
View Routing Policies
|
||||
<ArrowRight size={14} />
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
color: var(--l2-foreground);
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useCreateAlertState } from 'container/CreateAlertV2/context';
|
||||
import { INITIAL_ADVANCED_OPTIONS_STATE } from 'container/CreateAlertV2/context/constants';
|
||||
import { IEditCustomScheduleProps } from 'container/CreateAlertV2/EvaluationSettings/types';
|
||||
import { Calendar1, Pencil, Trash } from '@signozhq/icons';
|
||||
import ButtonGroup from 'periscope/components/ButtonGroup/ButtonGroup';
|
||||
|
||||
function EditCustomSchedule({
|
||||
setIsEvaluationCadenceDetailsVisible,
|
||||
@@ -80,23 +81,24 @@ function EditCustomSchedule({
|
||||
<div className="edit-custom-schedule">
|
||||
{displayText}
|
||||
<div className="button-row">
|
||||
<Button.Group>
|
||||
<Button type="default" onClick={handleEdit}>
|
||||
<ButtonGroup>
|
||||
<Button onClick={handleEdit} variant="outlined" color="secondary">
|
||||
<Pencil size={12} />
|
||||
<Typography.Text>Edit custom schedule</Typography.Text>
|
||||
</Button>
|
||||
<Button type="default" onClick={handlePreview}>
|
||||
<Button onClick={handlePreview} variant="outlined" color="secondary">
|
||||
<Calendar1 size={12} />
|
||||
<Typography.Text>Preview</Typography.Text>
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="discard-button"
|
||||
type="default"
|
||||
onClick={handleDiscard}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
<Trash size={12} />
|
||||
</Button>
|
||||
</Button.Group>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Button, DatePicker, Input, Select } from 'antd';
|
||||
import { DatePicker, Input, Select } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import classNames from 'classnames';
|
||||
import { useCreateAlertState } from 'container/CreateAlertV2/context';
|
||||
@@ -311,6 +312,8 @@ function EvaluationCadenceDetails({
|
||||
onClick={(): void => {
|
||||
handleChangeTab(tab.value as 'editor' | 'rrule');
|
||||
}}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
{tab.icon}
|
||||
{tab.label}
|
||||
@@ -321,14 +324,10 @@ function EvaluationCadenceDetails({
|
||||
{activeTab === 'editor' && EditorView}
|
||||
{activeTab === 'rrule' && RRuleView}
|
||||
<div className="buttons-row">
|
||||
<Button type="default" onClick={handleDiscard}>
|
||||
<Button onClick={handleDiscard} variant="outlined" color="secondary">
|
||||
Discard
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleSaveCustomSchedule}
|
||||
disabled={disableSaveButton}
|
||||
>
|
||||
<Button onClick={handleSaveCustomSchedule} disabled={disableSaveButton}>
|
||||
Save Custom Schedule
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ant-btn-group {
|
||||
.ant-btn {
|
||||
.periscope-btn-group {
|
||||
button {
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l2-foreground);
|
||||
font-size: 13px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Popover } from 'antd';
|
||||
import { Popover } from 'antd';
|
||||
import { ChevronDown, ChevronUp } from '@signozhq/icons';
|
||||
|
||||
import { useCreateAlertState } from '../context';
|
||||
@@ -7,6 +7,7 @@ import EvaluationWindowPopover from './EvaluationWindowPopover';
|
||||
import { getEvaluationWindowTypeText, getTimeframeText } from './utils';
|
||||
|
||||
import './styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function EvaluationSettings(): JSX.Element {
|
||||
const { evaluationWindow, setEvaluationWindow } = useCreateAlertState();
|
||||
@@ -29,7 +30,11 @@ function EvaluationSettings(): JSX.Element {
|
||||
trigger="click"
|
||||
showArrow={false}
|
||||
>
|
||||
<Button data-testid="evaluation-settings-button">
|
||||
<Button
|
||||
data-testid="evaluation-settings-button"
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
<div className="evaluate-alert-conditions-button-left">
|
||||
{getTimeframeText(evaluationWindow)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from 'antd';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import classNames from 'classnames';
|
||||
import { Check } from '@signozhq/icons';
|
||||
@@ -98,7 +98,7 @@ function EvaluationWindowPopover({
|
||||
<Typography.Text>
|
||||
{getRollingWindowDescription(evaluationWindow.timeframe)}
|
||||
</Typography.Text>
|
||||
<Button type="link">Read the docs</Button>
|
||||
<Button variant="link">Read the docs</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -112,7 +112,7 @@ function EvaluationWindowPopover({
|
||||
<Typography.Text>
|
||||
{getCumulativeWindowDescription(evaluationWindow.timeframe)}
|
||||
</Typography.Text>
|
||||
<Button type="link">Read the docs</Button>
|
||||
<Button variant="link">Read the docs</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
border-top: 1px dashed var(--l1-border);
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -156,7 +156,7 @@
|
||||
color: var(--muted-foreground);
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
button {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
button {
|
||||
background-color: var(--l3-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l2-foreground);
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ant-btn-default {
|
||||
button {
|
||||
background-color: var(--l1-background);
|
||||
border: 1px solid var(--l1-border);
|
||||
color: var(--l2-foreground);
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
}
|
||||
|
||||
.notification-message-header-actions {
|
||||
.ant-btn {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useQueryClient } from 'react-query';
|
||||
import { Button } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { YAxisSource } from 'components/YAxisUnitSelector/types';
|
||||
import { QueryParams } from 'constants/query';
|
||||
@@ -26,6 +25,7 @@ import ChartPreview from './ChartPreview';
|
||||
import { buildAlertDefForChartPreview } from './utils';
|
||||
|
||||
import './styles.scss';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
|
||||
function QuerySection(): JSX.Element {
|
||||
const {
|
||||
@@ -149,6 +149,8 @@ function QuerySection(): JSX.Element {
|
||||
onClick={(): void => {
|
||||
setAlertType(tab.value as AlertTypes);
|
||||
}}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
>
|
||||
{tab.icon}
|
||||
{tab.label}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user