mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-29 13:20:28 +01:00
Compare commits
12 Commits
refactor/c
...
feat/overv
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2535f0ccf | ||
|
|
745222867b | ||
|
|
b0ddcbe9f1 | ||
|
|
785c6233c7 | ||
|
|
97912f6c50 | ||
|
|
849cae1a9c | ||
|
|
92d40bf335 | ||
|
|
78723f63bc | ||
|
|
f8d73af495 | ||
|
|
6ba2049cfe | ||
|
|
bd1fc43376 | ||
|
|
da1b09c479 |
@@ -7965,80 +7965,6 @@ paths:
|
||||
tags:
|
||||
- cloudintegration
|
||||
/api/v1/cloud_integrations/{cloud_provider}/accounts/{id}/services/{service_id}:
|
||||
get:
|
||||
deprecated: false
|
||||
description: This endpoint gets a service and its configuration for the specified
|
||||
cloud integration account
|
||||
operationId: GetAccountService
|
||||
parameters:
|
||||
- in: path
|
||||
name: cloud_provider
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: service_id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/CloudintegrationtypesService'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"400":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Bad Request
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"404":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Not Found
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- ADMIN
|
||||
- tokenizer:
|
||||
- ADMIN
|
||||
summary: Get service for account
|
||||
tags:
|
||||
- cloudintegration
|
||||
put:
|
||||
deprecated: false
|
||||
description: This endpoint updates a service for the specified cloud provider
|
||||
|
||||
@@ -237,6 +237,10 @@ func (module *module) Update(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return module.pkgDashboardModule.Update(ctx, orgID, id, updatedBy, data, diff)
|
||||
}
|
||||
|
||||
func (module *module) ResetSystemDashboard(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string) (*dashboardtypes.Dashboard, error) {
|
||||
return module.pkgDashboardModule.ResetSystemDashboard(ctx, orgID, id, updatedBy)
|
||||
}
|
||||
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, isAdmin bool, lock bool) error {
|
||||
return module.pkgDashboardModule.LockUnlock(ctx, orgID, id, updatedBy, isAdmin, lock)
|
||||
}
|
||||
|
||||
@@ -31,8 +31,6 @@ import type {
|
||||
DisconnectAccountPathParameters,
|
||||
GetAccount200,
|
||||
GetAccountPathParameters,
|
||||
GetAccountService200,
|
||||
GetAccountServicePathParameters,
|
||||
GetConnectionCredentials200,
|
||||
GetConnectionCredentialsPathParameters,
|
||||
GetService200,
|
||||
@@ -633,117 +631,6 @@ export const useUpdateAccount = <
|
||||
> => {
|
||||
return useMutation(getUpdateAccountMutationOptions(options));
|
||||
};
|
||||
/**
|
||||
* This endpoint gets a service and its configuration for the specified cloud integration account
|
||||
* @summary Get service for account
|
||||
*/
|
||||
export const getAccountService = (
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetAccountService200>({
|
||||
url: `/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services/${serviceId}`,
|
||||
method: 'GET',
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetAccountServiceQueryKey = ({
|
||||
cloudProvider,
|
||||
id,
|
||||
serviceId,
|
||||
}: GetAccountServicePathParameters) => {
|
||||
return [
|
||||
`/api/v1/cloud_integrations/${cloudProvider}/accounts/${id}/services/${serviceId}`,
|
||||
] as const;
|
||||
};
|
||||
|
||||
export const getGetAccountServiceQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ??
|
||||
getGetAccountServiceQueryKey({ cloudProvider, id, serviceId });
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getAccountService>>
|
||||
> = ({ signal }) =>
|
||||
getAccountService({ cloudProvider, id, serviceId }, signal);
|
||||
|
||||
return {
|
||||
queryKey,
|
||||
queryFn,
|
||||
enabled: !!(cloudProvider && id && serviceId),
|
||||
...queryOptions,
|
||||
} as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetAccountServiceQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getAccountService>>
|
||||
>;
|
||||
export type GetAccountServiceQueryError = ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get service for account
|
||||
*/
|
||||
|
||||
export function useGetAccountService<
|
||||
TData = Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getAccountService>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetAccountServiceQueryOptions(
|
||||
{ cloudProvider, id, serviceId },
|
||||
options,
|
||||
);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get service for account
|
||||
*/
|
||||
export const invalidateGetAccountService = async (
|
||||
queryClient: QueryClient,
|
||||
{ cloudProvider, id, serviceId }: GetAccountServicePathParameters,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetAccountServiceQueryKey({ cloudProvider, id, serviceId }) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint updates a service for the specified cloud provider
|
||||
* @summary Update service
|
||||
|
||||
@@ -8566,19 +8566,6 @@ export type UpdateAccountPathParameters = {
|
||||
cloudProvider: string;
|
||||
id: string;
|
||||
};
|
||||
export type GetAccountServicePathParameters = {
|
||||
cloudProvider: string;
|
||||
id: string;
|
||||
serviceId: string;
|
||||
};
|
||||
export type GetAccountService200 = {
|
||||
data: CloudintegrationtypesServiceDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type UpdateServicePathParameters = {
|
||||
cloudProvider: string;
|
||||
id: string;
|
||||
|
||||
12
frontend/src/components/RouteTab/RouteTab.styles.scss
Normal file
12
frontend/src/components/RouteTab/RouteTab.styles.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
.route-tab-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.route-tab-extra {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ describe('RouteTab component', () => {
|
||||
</Router>,
|
||||
);
|
||||
expect(history.location.pathname).toBe('/');
|
||||
fireEvent.click(screen.getByRole('tab', { name: 'Tab2' }));
|
||||
fireEvent.mouseDown(screen.getByRole('tab', { name: 'Tab2' }));
|
||||
expect(history.location.pathname).toBe('/tab2');
|
||||
});
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('RouteTab component', () => {
|
||||
/>
|
||||
</Router>,
|
||||
);
|
||||
fireEvent.click(screen.getByRole('tab', { name: 'Tab2' }));
|
||||
fireEvent.mouseDown(screen.getByRole('tab', { name: 'Tab2' }));
|
||||
expect(onChangeHandler).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import './RouteTab.styles.scss';
|
||||
|
||||
import {
|
||||
generatePath,
|
||||
matchPath,
|
||||
useLocation,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
import { Tabs, TabsProps } from 'antd';
|
||||
import {
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsRoot,
|
||||
TabsTrigger,
|
||||
} from '@signozhq/ui/tabs';
|
||||
import HeaderRightSection from 'components/HeaderRightSection/HeaderRightSection';
|
||||
|
||||
import { RouteTabProps } from './types';
|
||||
@@ -16,11 +23,13 @@ interface Params {
|
||||
function RouteTab({
|
||||
routes,
|
||||
activeKey,
|
||||
defaultActiveKey,
|
||||
onChangeHandler,
|
||||
history,
|
||||
showRightSection,
|
||||
...rest
|
||||
}: RouteTabProps & TabsProps): JSX.Element {
|
||||
showRightSection = true,
|
||||
tabBarExtraContent,
|
||||
hideTabBar = false,
|
||||
}: RouteTabProps): JSX.Element {
|
||||
const params = useParams<Params>();
|
||||
const location = useLocation();
|
||||
|
||||
@@ -46,38 +55,38 @@ function RouteTab({
|
||||
}
|
||||
};
|
||||
|
||||
const items = routes.map(({ Component, name, route, key }) => ({
|
||||
label: name,
|
||||
key,
|
||||
tabKey: route,
|
||||
children: <Component />,
|
||||
}));
|
||||
const resolvedActiveKey = currentRoute?.key || activeKey;
|
||||
const extraContent =
|
||||
tabBarExtraContent ??
|
||||
(showRightSection && (
|
||||
<HeaderRightSection enableAnnouncements={false} enableShare enableFeedback />
|
||||
));
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
onChange={onChange}
|
||||
destroyInactiveTabPane
|
||||
activeKey={currentRoute?.key || activeKey}
|
||||
defaultActiveKey={currentRoute?.key || activeKey}
|
||||
animated
|
||||
items={items}
|
||||
tabBarExtraContent={
|
||||
showRightSection && (
|
||||
<HeaderRightSection
|
||||
enableAnnouncements={false}
|
||||
enableShare
|
||||
enableFeedback
|
||||
/>
|
||||
)
|
||||
}
|
||||
{...rest}
|
||||
/>
|
||||
<TabsRoot
|
||||
value={resolvedActiveKey}
|
||||
defaultValue={defaultActiveKey ?? resolvedActiveKey}
|
||||
onValueChange={onChange}
|
||||
>
|
||||
{!hideTabBar && (
|
||||
<div className="route-tab-header">
|
||||
<TabsList>
|
||||
{routes.map(({ name, key }) => (
|
||||
<TabsTrigger key={key} value={key}>
|
||||
{name}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
{extraContent && <div className="route-tab-extra">{extraContent}</div>}
|
||||
</div>
|
||||
)}
|
||||
{routes.map(({ key, Component }) => (
|
||||
<TabsContent key={key} value={key}>
|
||||
<Component />
|
||||
</TabsContent>
|
||||
))}
|
||||
</TabsRoot>
|
||||
);
|
||||
}
|
||||
|
||||
RouteTab.defaultProps = {
|
||||
onChangeHandler: undefined,
|
||||
showRightSection: true,
|
||||
};
|
||||
|
||||
export default RouteTab;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { TabsProps } from 'antd';
|
||||
import { History } from 'history';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export type TabRoutes = {
|
||||
name: React.ReactNode;
|
||||
@@ -10,8 +10,11 @@ export type TabRoutes = {
|
||||
|
||||
export interface RouteTabProps {
|
||||
routes: TabRoutes[];
|
||||
activeKey: TabsProps['activeKey'];
|
||||
activeKey: string | undefined;
|
||||
defaultActiveKey?: string;
|
||||
onChangeHandler?: (key: string) => void;
|
||||
history: History<unknown>;
|
||||
showRightSection: boolean;
|
||||
showRightSection?: boolean;
|
||||
tabBarExtraContent?: ReactNode;
|
||||
hideTabBar?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
.settings-tabs {
|
||||
.ant-tabs-nav-list {
|
||||
height: 32px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 2px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l2-background);
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
transition: opacity 0.1s !important;
|
||||
|
||||
.ant-tabs-tab + .ant-tabs-tab {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.ant-tabs-tab:not(:last-child) {
|
||||
border-right: 1px solid var(--l1-border) !important;
|
||||
}
|
||||
|
||||
.overview-btn {
|
||||
width: 114px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.variables-btn {
|
||||
width: 114px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.public-dashboard-btn {
|
||||
width: 150px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.disabled-btn {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-ink-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ant-tabs-tab-active {
|
||||
.overview-btn {
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
background: var(--l1-border);
|
||||
}
|
||||
|
||||
.variables-btn {
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
background: var(--l1-border);
|
||||
}
|
||||
|
||||
.public-dashboard-btn {
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
background: var(--l1-border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-nav::before {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Tabs, Tooltip } from 'antd';
|
||||
import { Tabs, TabItemProps } from '@signozhq/ui/tabs';
|
||||
import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
|
||||
import { Braces, Globe, Table } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
@@ -9,8 +9,6 @@ import DashboardVariableSettings from './DashboardVariableSettings';
|
||||
import GeneralDashboardSettings from './General';
|
||||
import PublicDashboardSetting from './PublicDashboard';
|
||||
|
||||
import './DashboardSettingsContent.styles.scss';
|
||||
|
||||
function DashboardSettings({
|
||||
variablesSettingsTabHandle,
|
||||
}: {
|
||||
@@ -21,49 +19,26 @@ function DashboardSettings({
|
||||
|
||||
const enablePublicDashboard = isCloudUser || isEnterpriseSelfHostedUser;
|
||||
|
||||
const publicDashboardItem = {
|
||||
label: (
|
||||
<Tooltip
|
||||
title={
|
||||
user?.role !== USER_ROLES.ADMIN
|
||||
? 'Only admins can publish / manage public dashboards'
|
||||
: ''
|
||||
}
|
||||
placement="right"
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<Globe size={14} />}
|
||||
className={`public-dashboard-btn ${
|
||||
user?.role !== USER_ROLES.ADMIN ? 'disabled-btn' : ''
|
||||
}`}
|
||||
>
|
||||
Publish
|
||||
</Button>
|
||||
</Tooltip>
|
||||
),
|
||||
const publicDashboardItem: TabItemProps = {
|
||||
key: 'public-dashboard',
|
||||
label: 'Publish',
|
||||
prefixIcon: <Globe size={14} />,
|
||||
children: <PublicDashboardSetting />,
|
||||
disabled: user?.role !== USER_ROLES.ADMIN,
|
||||
disabledReason: 'Only admins can publish / manage public dashboards',
|
||||
};
|
||||
|
||||
const items = [
|
||||
const items: TabItemProps[] = [
|
||||
{
|
||||
label: (
|
||||
<Button type="text" icon={<Table size={14} />} className="overview-btn">
|
||||
Overview
|
||||
</Button>
|
||||
),
|
||||
key: 'general',
|
||||
label: 'Overview',
|
||||
prefixIcon: <Table size={14} />,
|
||||
children: <GeneralDashboardSettings />,
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<Button type="text" icon={<Braces size={14} />} className="variables-btn">
|
||||
Variables
|
||||
</Button>
|
||||
),
|
||||
key: 'variables',
|
||||
label: 'Variables',
|
||||
prefixIcon: <Braces size={14} />,
|
||||
children: (
|
||||
<DashboardVariableSettings
|
||||
variablesSettingsTabHandle={variablesSettingsTabHandle}
|
||||
@@ -73,7 +48,7 @@ function DashboardSettings({
|
||||
...(enablePublicDashboard ? [publicDashboardItem] : []),
|
||||
];
|
||||
|
||||
return <Tabs items={items} animated className="settings-tabs" />;
|
||||
return <Tabs items={items} />;
|
||||
}
|
||||
|
||||
export default DashboardSettings;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Button, Tabs, TabsProps } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { Tabs, TabItemProps } from '@signozhq/ui/tabs';
|
||||
import ConfigureIcon from 'assets/Integrations/ConfigureIcon';
|
||||
import { CableCar, Group } from '@signozhq/icons';
|
||||
import { IntegrationDetailedProps } from 'types/api/integrations/types';
|
||||
@@ -22,18 +21,11 @@ function IntegrationDetailContent(
|
||||
): JSX.Element {
|
||||
const { activeDetailTab, integrationData, integrationId, setActiveDetailTab } =
|
||||
props;
|
||||
const items: TabsProps['items'] = [
|
||||
const items: TabItemProps[] = [
|
||||
{
|
||||
key: 'overview',
|
||||
label: (
|
||||
<Button
|
||||
type="text"
|
||||
className="integration-tab-btns"
|
||||
icon={<CableCar size={14} />}
|
||||
>
|
||||
<Typography.Text className="typography">Overview</Typography.Text>
|
||||
</Button>
|
||||
),
|
||||
label: 'Overview',
|
||||
prefixIcon: <CableCar size={14} />,
|
||||
children: (
|
||||
<Overview
|
||||
categories={integrationData.categories}
|
||||
@@ -44,15 +36,8 @@ function IntegrationDetailContent(
|
||||
},
|
||||
{
|
||||
key: 'configuration',
|
||||
label: (
|
||||
<Button
|
||||
type="text"
|
||||
className="integration-tab-btns"
|
||||
icon={<ConfigureIcon />}
|
||||
>
|
||||
<Typography.Text className="typography">Configure</Typography.Text>
|
||||
</Button>
|
||||
),
|
||||
label: 'Configure',
|
||||
prefixIcon: <ConfigureIcon />,
|
||||
children: (
|
||||
<Configure
|
||||
configuration={integrationData.configuration}
|
||||
@@ -62,15 +47,8 @@ function IntegrationDetailContent(
|
||||
},
|
||||
{
|
||||
key: 'dataCollected',
|
||||
label: (
|
||||
<Button
|
||||
type="text"
|
||||
className="integration-tab-btns"
|
||||
icon={<Group size={14} />}
|
||||
>
|
||||
<Typography.Text className="typography">Data Collected</Typography.Text>
|
||||
</Button>
|
||||
),
|
||||
label: 'Data Collected',
|
||||
prefixIcon: <Group size={14} />,
|
||||
children: (
|
||||
<DataCollected
|
||||
logsData={integrationData.data_collected.logs}
|
||||
@@ -81,11 +59,7 @@ function IntegrationDetailContent(
|
||||
];
|
||||
return (
|
||||
<div className="integration-detail-container">
|
||||
<Tabs
|
||||
activeKey={activeDetailTab}
|
||||
items={items}
|
||||
onChange={setActiveDetailTab}
|
||||
/>
|
||||
<Tabs value={activeDetailTab} items={items} onChange={setActiveDetailTab} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,45 +168,6 @@
|
||||
padding: 10px 16px;
|
||||
border: 1px solid var(--l1-border);
|
||||
background: var(--l1-background);
|
||||
|
||||
.integration-tab-btns {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 8px 18px 8px !important;
|
||||
|
||||
.typography {
|
||||
color: var(--l1-foreground);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
}
|
||||
|
||||
.integration-tab-btns:hover {
|
||||
&.ant-btn-text {
|
||||
background-color: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-nav-list {
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.ant-tabs-nav {
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.ant-tabs-tab {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.ant-tabs-tab + .ant-tabs-tab {
|
||||
margin: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.uninstall-integration-bar {
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
.service-route-tab {
|
||||
margin-bottom: 64px;
|
||||
.ant-tabs-nav {
|
||||
&::before {
|
||||
border-bottom: 1px solid var(--l1-border);
|
||||
}
|
||||
.ant-tabs-nav-wrap {
|
||||
.ant-tabs-nav-list {
|
||||
.ant-tabs-ink-bar {
|
||||
background-color: var(--primary-background) !important;
|
||||
}
|
||||
.ant-tabs-tab {
|
||||
font-size: 13px;
|
||||
font-family: 'Inter';
|
||||
color: var(--l1-foreground);
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.07px;
|
||||
gap: 10px;
|
||||
}
|
||||
.ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Tabs, TabsProps } from 'antd';
|
||||
import { Tabs, TabItemProps } from '@signozhq/ui/tabs';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import DBCall from 'container/MetricsApplication/Tabs/DBCall';
|
||||
import External from 'container/MetricsApplication/Tabs/External';
|
||||
@@ -24,7 +24,7 @@ function MetricsApplication(): JSX.Element {
|
||||
const urlQuery = useUrlQuery();
|
||||
const { safeNavigate } = useSafeNavigate();
|
||||
|
||||
const items: TabsProps['items'] = [
|
||||
const items: TabItemProps[] = [
|
||||
{
|
||||
label: TAB_KEY_VS_LABEL[MetricsApplicationTab.OVER_METRICS],
|
||||
key: MetricsApplicationTab.OVER_METRICS,
|
||||
@@ -53,9 +53,8 @@ function MetricsApplication(): JSX.Element {
|
||||
<ApDexApplication />
|
||||
<Tabs
|
||||
items={items}
|
||||
activeKey={activeKey}
|
||||
value={activeKey}
|
||||
className="service-route-tab"
|
||||
destroyInactiveTabPane
|
||||
onChange={onTabChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
.pipeline-tabs {
|
||||
.ant-tabs-content {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.ant-tabs-tabpane-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,7 @@ import { useEffect, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useQuery } from 'react-query';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import type { TabsProps } from 'antd';
|
||||
import { Tabs } from 'antd';
|
||||
import { Tabs, TabItemProps } from '@signozhq/ui/tabs';
|
||||
import getPipeline from 'api/pipeline/get';
|
||||
import Spinner from 'components/Spinner';
|
||||
import ChangeHistory from 'container/PipelinePage/Layouts/ChangeHistory';
|
||||
@@ -13,8 +12,6 @@ import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFall
|
||||
import { SuccessResponse } from 'types/api';
|
||||
import { Pipeline } from 'types/api/pipeline/def';
|
||||
|
||||
import './Pipelines.styles.scss';
|
||||
|
||||
const pipelineRefetchInterval = (
|
||||
pipelineResponse: SuccessResponse<Pipeline> | undefined,
|
||||
): number | false => {
|
||||
@@ -46,7 +43,7 @@ function Pipelines(): JSX.Element {
|
||||
refetchInterval: pipelineRefetchInterval,
|
||||
});
|
||||
|
||||
const tabItems: TabsProps['items'] = useMemo(
|
||||
const tabItems: TabItemProps[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
key: 'pipelines',
|
||||
@@ -83,11 +80,7 @@ function Pipelines(): JSX.Element {
|
||||
|
||||
return (
|
||||
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
|
||||
<Tabs
|
||||
className="pipeline-tabs"
|
||||
defaultActiveKey="pipelines"
|
||||
items={tabItems}
|
||||
/>
|
||||
<Tabs defaultValue="pipelines" items={tabItems} />
|
||||
</Sentry.ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -340,7 +340,7 @@ function SettingsPage(): JSX.Element {
|
||||
routes={routes}
|
||||
activeKey={pathname}
|
||||
history={history}
|
||||
tabBarStyle={{ display: 'none' }}
|
||||
hideTabBar
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -71,88 +71,6 @@
|
||||
flex-direction: column;
|
||||
gap: 25px;
|
||||
padding-top: 16px;
|
||||
|
||||
.flamegraph-waterfall-toggle {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 31px;
|
||||
color: var(--l2-foreground);
|
||||
padding: 5px 20px;
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
|
||||
.ant-btn-icon {
|
||||
margin-inline-end: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.span-list-toggle {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 31px;
|
||||
padding: 5px 20px;
|
||||
color: var(--l2-foreground);
|
||||
font-family: Inter;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
|
||||
.ant-btn-icon {
|
||||
margin-inline-end: 0px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.trace-visualisation-tabs {
|
||||
.ant-tabs-tab {
|
||||
border-radius: 2px 0px 0px 0px;
|
||||
background: var(--l2-background);
|
||||
border-radius: 2px 2px 0px 0px;
|
||||
border: 1px solid var(--l1-border);
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
height: 31px;
|
||||
}
|
||||
|
||||
.ant-tabs-tab-active {
|
||||
background-color: var(--l1-background);
|
||||
|
||||
.ant-btn {
|
||||
color: var(--l1-foreground) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tabs-tab + .ant-tabs-tab {
|
||||
margin: 0px;
|
||||
border-left: 0px;
|
||||
}
|
||||
|
||||
.ant-tabs-ink-bar {
|
||||
height: 1px !important;
|
||||
background: var(--l1-background) !important;
|
||||
}
|
||||
|
||||
.ant-tabs-nav-list {
|
||||
transform: translate(15px, 0px) !important;
|
||||
}
|
||||
|
||||
.ant-tabs-nav::before {
|
||||
border-bottom: 1px solid var(--l1-border);
|
||||
}
|
||||
|
||||
.ant-tabs-nav {
|
||||
margin: 0px;
|
||||
padding: 0px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
ResizablePanel,
|
||||
ResizablePanelGroup,
|
||||
} from '@signozhq/resizable';
|
||||
import { Button, Tabs } from 'antd';
|
||||
import { Tabs, TabItemProps } from '@signozhq/ui/tabs';
|
||||
import FlamegraphImg from 'assets/TraceDetail/Flamegraph';
|
||||
import cx from 'classnames';
|
||||
import TraceFlamegraph from 'container/PaginatedTraceFlamegraph/PaginatedTraceFlamegraph';
|
||||
@@ -86,18 +86,11 @@ function TraceDetailsV2(): JSX.Element {
|
||||
}
|
||||
}, [noData]);
|
||||
|
||||
const items = [
|
||||
const items: TabItemProps[] = [
|
||||
{
|
||||
label: (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<FlamegraphImg />}
|
||||
className="flamegraph-waterfall-toggle"
|
||||
>
|
||||
Flamegraph
|
||||
</Button>
|
||||
),
|
||||
key: 'flamegraph',
|
||||
label: 'Flamegraph',
|
||||
prefixIcon: <FlamegraphImg />,
|
||||
children: (
|
||||
<>
|
||||
<TraceFlamegraph
|
||||
@@ -145,11 +138,7 @@ function TraceDetailsV2(): JSX.Element {
|
||||
totalSpans={traceData?.payload?.totalSpansCount || 0}
|
||||
notFound={noData}
|
||||
/>
|
||||
{!noData ? (
|
||||
<Tabs items={items} animated className="trace-visualisation-tabs" />
|
||||
) : (
|
||||
<NoData />
|
||||
)}
|
||||
{!noData ? <Tabs items={items} /> : <NoData />}
|
||||
</ResizablePanel>
|
||||
|
||||
<ResizableHandle withHandle className="resizable-handle" />
|
||||
|
||||
@@ -22,21 +22,6 @@ $dark-theme: 'darkMode';
|
||||
|
||||
&__tabs {
|
||||
margin-top: 148px;
|
||||
|
||||
.ant-tabs {
|
||||
&-nav {
|
||||
&::before {
|
||||
border-color: var(--l1-border);
|
||||
|
||||
.#{$light-theme} & {
|
||||
border-color: var(--l1-border);
|
||||
}
|
||||
}
|
||||
}
|
||||
&-nav-wrap {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__modal {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useMutation } from 'react-query';
|
||||
import type { TabsProps } from 'antd';
|
||||
import type { TabItemProps } from '@signozhq/ui/tabs';
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
Row,
|
||||
Skeleton,
|
||||
Space,
|
||||
Tabs,
|
||||
} from 'antd';
|
||||
import { Tabs } from '@signozhq/ui/tabs';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import updateCreditCardApi from 'api/v1/checkout/create';
|
||||
@@ -154,7 +154,7 @@ export default function WorkspaceBlocked(): JSX.Element {
|
||||
/>
|
||||
));
|
||||
|
||||
const tabItems: TabsProps['items'] = [
|
||||
const tabItems: TabItemProps[] = [
|
||||
{
|
||||
key: 'whyChooseSignoz',
|
||||
label: t('whyChooseSignoz'),
|
||||
@@ -398,8 +398,8 @@ export default function WorkspaceBlocked(): JSX.Element {
|
||||
<div className="workspace-locked__tabs">
|
||||
<Tabs
|
||||
items={tabItems}
|
||||
defaultActiveKey="youAreInGoodCompany"
|
||||
onTabClick={handleTabClick}
|
||||
defaultValue="youAreInGoodCompany"
|
||||
onChange={handleTabClick}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -825,5 +825,6 @@ body.ai-assistant-panel-open {
|
||||
// overrides
|
||||
:root {
|
||||
--input-focus-outline-width: 0;
|
||||
--tab-list-primary-gap: 12px;
|
||||
--radius-2: 4px;
|
||||
}
|
||||
|
||||
@@ -192,26 +192,6 @@ func (provider *provider) addCloudIntegrationRoutes(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/cloud_integrations/{cloud_provider}/accounts/{id}/services/{service_id}", handler.New(
|
||||
provider.authzMiddleware.AdminAccess(provider.cloudIntegrationHandler.GetAccountService),
|
||||
handler.OpenAPIDef{
|
||||
ID: "GetAccountService",
|
||||
Tags: []string{"cloudintegration"},
|
||||
Summary: "Get service for account",
|
||||
Description: "This endpoint gets a service and its configuration for the specified cloud integration account",
|
||||
Request: nil,
|
||||
RequestContentType: "",
|
||||
Response: new(citypes.Service),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{http.StatusBadRequest, http.StatusNotFound},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleAdmin),
|
||||
},
|
||||
)).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Agent check-in endpoint is kept same as older one to maintain backward compatibility with already deployed agents.
|
||||
// In the future, this endpoint will be deprecated and a new endpoint will be introduced for consistency with above endpoints.
|
||||
if err := router.Handle("/api/v1/cloud-integrations/{cloud_provider}/agent-check-in", handler.New(
|
||||
|
||||
@@ -76,7 +76,6 @@ type Handler interface {
|
||||
DisconnectAccount(http.ResponseWriter, *http.Request)
|
||||
ListServicesMetadata(http.ResponseWriter, *http.Request)
|
||||
GetService(http.ResponseWriter, *http.Request)
|
||||
GetAccountService(http.ResponseWriter, *http.Request)
|
||||
UpdateService(http.ResponseWriter, *http.Request)
|
||||
AgentCheckIn(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
@@ -322,51 +322,6 @@ func (handler *handler) GetService(rw http.ResponseWriter, r *http.Request) {
|
||||
render.Success(rw, http.StatusOK, svc)
|
||||
}
|
||||
|
||||
func (handler *handler) GetAccountService(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
provider, err := cloudintegrationtypes.NewCloudProvider(mux.Vars(r)["cloud_provider"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
serviceID, err := cloudintegrationtypes.NewServiceID(provider, mux.Vars(r)["service_id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
cloudIntegrationID, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID := valuer.MustNewUUID(claims.OrgID)
|
||||
|
||||
_, err = handler.module.GetConnectedAccount(ctx, orgID, cloudIntegrationID, provider)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
svc, err := handler.module.GetService(ctx, orgID, serviceID, provider, cloudIntegrationID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, svc)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateService(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -42,6 +42,8 @@ type Module interface {
|
||||
|
||||
Update(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, data dashboardtypes.UpdatableDashboard, diff int) (*dashboardtypes.Dashboard, error)
|
||||
|
||||
ResetSystemDashboard(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string) (*dashboardtypes.Dashboard, error)
|
||||
|
||||
LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, isAdmin bool, lock bool) error
|
||||
|
||||
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||
@@ -89,4 +91,6 @@ type Handler interface {
|
||||
CreateV2(http.ResponseWriter, *http.Request)
|
||||
|
||||
GetV2(http.ResponseWriter, *http.Request)
|
||||
|
||||
ResetSystemDashboard(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
@@ -185,6 +185,38 @@ func (handler *handler) LockUnlock(rw http.ResponseWriter, r *http.Request) {
|
||||
|
||||
}
|
||||
|
||||
// ResetSystemDashboard resets the dashboard identified by {id} to its default.
|
||||
func (handler *handler) ResetSystemDashboard(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
orgID, err := valuer.NewUUID(claims.OrgID)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := valuer.NewUUID(mux.Vars(r)["id"])
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
dashboard, err := handler.module.ResetSystemDashboard(ctx, orgID, id, claims.Email)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, dashboard)
|
||||
}
|
||||
|
||||
func (handler *handler) Delete(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -97,8 +97,7 @@ func (module *module) Update(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = dashboard.Update(ctx, updatableDashboard, updatedBy, diff)
|
||||
if err != nil {
|
||||
if err := dashboard.Update(ctx, updatableDashboard, updatedBy, diff); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -107,14 +106,31 @@ func (module *module) Update(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = module.store.Update(ctx, orgID, storableDashboard)
|
||||
if err != nil {
|
||||
if err := module.store.Update(ctx, orgID, storableDashboard); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dashboard, nil
|
||||
}
|
||||
|
||||
func (module *module) ResetSystemDashboard(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string) (*dashboardtypes.Dashboard, error) {
|
||||
dashboard, err := module.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dashboard.Source != dashboardtypes.SourceSystem {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "only system dashboards can be reset")
|
||||
}
|
||||
|
||||
defaults, err := dashboardtypes.NewDefaultSystemDashboard(orgID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return module.Update(ctx, orgID, id, updatedBy, defaults.Data, 0)
|
||||
}
|
||||
|
||||
func (module *module) LockUnlock(ctx context.Context, orgID valuer.UUID, id valuer.UUID, updatedBy string, isAdmin bool, lock bool) error {
|
||||
dashboard, err := module.Get(ctx, orgID, id)
|
||||
if err != nil {
|
||||
@@ -156,8 +172,7 @@ func (module *module) Delete(ctx context.Context, orgID valuer.UUID, id valuer.U
|
||||
return errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "dashboard is locked, please unlock the dashboard to be delete it")
|
||||
}
|
||||
|
||||
err = module.store.Delete(ctx, orgID, id)
|
||||
if err != nil {
|
||||
if err := module.store.Delete(ctx, orgID, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ func (store *store) ListPublic(ctx context.Context, orgID valuer.UUID) ([]*dashb
|
||||
func (store *store) Update(ctx context.Context, orgID valuer.UUID, storableDashboard *dashboardtypes.StorableDashboard) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDB().
|
||||
BunDBCtx(ctx).
|
||||
NewUpdate().
|
||||
Model(storableDashboard).
|
||||
WherePK().
|
||||
|
||||
@@ -502,6 +502,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router, am *middleware.AuthZ) {
|
||||
router.HandleFunc("/api/v1/dashboards/{id}", am.EditAccess(aH.Signoz.Handlers.Dashboard.Update)).Methods(http.MethodPut)
|
||||
router.HandleFunc("/api/v1/dashboards/{id}", am.EditAccess(aH.Signoz.Handlers.Dashboard.Delete)).Methods(http.MethodDelete)
|
||||
router.HandleFunc("/api/v1/dashboards/{id}/lock", am.EditAccess(aH.Signoz.Handlers.Dashboard.LockUnlock)).Methods(http.MethodPut)
|
||||
router.HandleFunc("/api/v1/dashboards/{id}/reset", am.AdminAccess(aH.Signoz.Handlers.Dashboard.ResetSystemDashboard)).Methods(http.MethodPut)
|
||||
router.HandleFunc("/api/v2/variables/query", am.ViewAccess(aH.queryDashboardVarsV2)).Methods(http.MethodPost)
|
||||
|
||||
router.HandleFunc("/api/v1/explorer/views", am.ViewAccess(aH.Signoz.Handlers.SavedView.List)).Methods(http.MethodGet)
|
||||
|
||||
10
pkg/types/dashboardtypes/defaults.go
Normal file
10
pkg/types/dashboardtypes/defaults.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package dashboardtypes
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
func NewDefaultSystemDashboard(orgID valuer.UUID) (*Dashboard, error) {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "no defaults registered for system dashboard")
|
||||
}
|
||||
Reference in New Issue
Block a user