-
+
diff --git a/frontend/src/pages/AlertDetails/AlertHeader/AlertLabels/AlertLabels.tsx b/frontend/src/pages/AlertDetails/AlertHeader/AlertLabels/AlertLabels.tsx
index bdc5eaa019..4386417219 100644
--- a/frontend/src/pages/AlertDetails/AlertHeader/AlertLabels/AlertLabels.tsx
+++ b/frontend/src/pages/AlertDetails/AlertHeader/AlertLabels/AlertLabels.tsx
@@ -4,7 +4,7 @@ import KeyValueLabel from 'periscope/components/KeyValueLabel';
import SeeMore from 'periscope/components/SeeMore';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
-type AlertLabelsProps = {
+export type AlertLabelsProps = {
labels: Record
;
initialCount?: number;
};
diff --git a/frontend/src/pages/AlertDetails/hooks.tsx b/frontend/src/pages/AlertDetails/hooks.tsx
index c6f7b64d64..8a630a6374 100644
--- a/frontend/src/pages/AlertDetails/hooks.tsx
+++ b/frontend/src/pages/AlertDetails/hooks.tsx
@@ -17,6 +17,7 @@ import AlertHistory from 'container/AlertHistory';
import { TIMELINE_TABLE_PAGE_SIZE } from 'container/AlertHistory/constants';
import { AlertDetailsTab, TimelineFilter } from 'container/AlertHistory/types';
import { urlKey } from 'container/AllError/utils';
+import { RelativeTimeMap } from 'container/TopNav/DateTimeSelection/config';
import useAxiosError from 'hooks/useAxiosError';
import { useNotifications } from 'hooks/useNotifications';
import useUrlQuery from 'hooks/useUrlQuery';
@@ -31,9 +32,7 @@ import PaginationInfoText from 'periscope/components/PaginationInfoText/Paginati
import { useAlertRule } from 'providers/Alert';
import { useCallback, useMemo } from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
-import { useSelector } from 'react-redux';
import { generatePath, useLocation } from 'react-router-dom';
-import { AppState } from 'store/reducers';
import { ErrorResponse, SuccessResponse } from 'types/api';
import {
AlertDef,
@@ -44,7 +43,7 @@ import {
AlertRuleTopContributorsPayload,
} from 'types/api/alerts/def';
import { PayloadProps } from 'types/api/alerts/get';
-import { GlobalReducer } from 'types/reducer/globalTime';
+import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { nanoToMilli } from 'utils/timeUtils';
export const useAlertHistoryQueryParams = (): {
@@ -56,11 +55,10 @@ export const useAlertHistoryQueryParams = (): {
} => {
const params = useUrlQuery();
- const globalTime = useSelector(
- (state) => state.globalTime,
- );
const startTime = params.get(QueryParams.startTime);
const endTime = params.get(QueryParams.endTime);
+ const relativeTime =
+ params.get(QueryParams.relativeTime) ?? RelativeTimeMap['6hr'];
const intStartTime = parseInt(startTime || '0', 10);
const intEndTime = parseInt(endTime || '0', 10);
@@ -69,8 +67,8 @@ export const useAlertHistoryQueryParams = (): {
const { maxTime, minTime } = useMemo(() => {
if (hasStartAndEndParams)
return GetMinMax('custom', [intStartTime, intEndTime]);
- return GetMinMax(globalTime.selectedTime);
- }, [hasStartAndEndParams, intStartTime, intEndTime, globalTime.selectedTime]);
+ return GetMinMax(relativeTime);
+ }, [hasStartAndEndParams, intStartTime, intEndTime, relativeTime]);
const ruleId = params.get(QueryParams.ruleId);
@@ -164,7 +162,6 @@ export const useGetAlertRuleDetails = (): Props => {
id: parseInt(ruleId || '', 10),
}),
enabled: isValidRuleId,
- refetchOnMount: false,
refetchOnWindowFocus: false,
});
@@ -253,7 +250,11 @@ type GetAlertRuleDetailsTimelineTableProps = GetAlertRuleDetailsApiProps & {
| undefined;
};
-export const useGetAlertRuleDetailsTimelineTable = (): GetAlertRuleDetailsTimelineTableProps => {
+export const useGetAlertRuleDetailsTimelineTable = ({
+ filters,
+}: {
+ filters: TagFilter;
+}): GetAlertRuleDetailsTimelineTableProps => {
const { ruleId, startTime, endTime, params } = useAlertHistoryQueryParams();
const { updatedOrder, offset } = useMemo(
() => ({
@@ -277,6 +278,7 @@ export const useGetAlertRuleDetailsTimelineTable = (): GetAlertRuleDetailsTimeli
timelineFilter,
updatedOrder,
offset,
+ JSON.stringify(filters.items),
],
{
queryFn: () =>
@@ -287,7 +289,7 @@ export const useGetAlertRuleDetailsTimelineTable = (): GetAlertRuleDetailsTimeli
limit: TIMELINE_TABLE_PAGE_SIZE,
order: updatedOrder,
offset,
-
+ filters,
...(timelineFilter && timelineFilter !== TimelineFilter.ALL
? {
state: timelineFilter === TimelineFilter.FIRED ? 'firing' : 'normal',
@@ -372,9 +374,9 @@ export const useAlertRuleStatusToggle = ({
}: {
ruleId: string;
}): {
- handleAlertStateToggle: (state: boolean) => void;
+ handleAlertStateToggle: () => void;
} => {
- const { isAlertRuleDisabled, setIsAlertRuleDisabled } = useAlertRule();
+ const { alertRuleState, setAlertRuleState } = useAlertRule();
const { notifications } = useNotifications();
const queryClient = useQueryClient();
@@ -384,16 +386,17 @@ export const useAlertRuleStatusToggle = ({
[REACT_QUERY_KEY.TOGGLE_ALERT_STATE, ruleId],
patchAlert,
{
- onMutate: () => {
- setIsAlertRuleDisabled((prev) => !prev);
- },
- onSuccess: () => {
+ onSuccess: (data) => {
+ setAlertRuleState(data?.payload?.state);
+
notifications.success({
- message: `Alert has been ${isAlertRuleDisabled ? 'enabled' : 'disabled'}.`,
+ message: `Alert has been ${
+ data?.payload?.state === 'disabled' ? 'disabled' : 'enabled'
+ }.`,
});
},
onError: (error) => {
- queryClient.refetchQueries([REACT_QUERY_KEY.ALERT_RULE_DETAILS]);
+ queryClient.refetchQueries([REACT_QUERY_KEY.ALERT_RULE_DETAILS, ruleId]);
handleError(error);
},
},
@@ -402,7 +405,7 @@ export const useAlertRuleStatusToggle = ({
const handleAlertStateToggle = (): void => {
const args = {
id: parseInt(ruleId, 10),
- data: { disabled: !isAlertRuleDisabled },
+ data: { disabled: alertRuleState !== 'disabled' },
};
toggleAlertState(args);
};
diff --git a/frontend/src/pages/Support/Support.tsx b/frontend/src/pages/Support/Support.tsx
index 9d3d8fff8f..668ac34143 100644
--- a/frontend/src/pages/Support/Support.tsx
+++ b/frontend/src/pages/Support/Support.tsx
@@ -10,8 +10,6 @@ import useLicense from 'hooks/useLicense';
import { useNotifications } from 'hooks/useNotifications';
import {
Book,
- Cable,
- Calendar,
CreditCard,
Github,
MessageSquare,
@@ -78,22 +76,6 @@ const supportChannels = [
url: '',
btnText: 'Launch chat',
},
- {
- key: 'schedule_call',
- name: 'Schedule a call',
- icon: ,
- title: 'Schedule a call with the founders.',
- url: 'https://calendly.com/vishal-signoz/30min',
- btnText: 'Schedule call',
- },
- {
- key: 'slack_connect',
- name: 'Slack Connect',
- icon: ,
- title: 'Get a dedicated support channel for your team.',
- url: '',
- btnText: 'Request Slack connect',
- },
];
export default function Support(): JSX.Element {
@@ -122,20 +104,6 @@ export default function Support(): JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
- const handleSlackConnectRequest = (): void => {
- const recipient = 'support@signoz.io';
- const subject = 'Slack Connect Request';
- const body = `I'd like to request a dedicated Slack Connect channel for me and my team. Users (emails) to include besides mine:`;
-
- // Create the mailto link
- const mailtoLink = `mailto:${recipient}?subject=${encodeURIComponent(
- subject,
- )}&body=${encodeURIComponent(body)}`;
-
- // Open the default email client
- window.location.href = mailtoLink;
- };
-
const isPremiumChatSupportEnabled =
useFeatureFlags(FeatureKeys.PREMIUM_SUPPORT)?.active || false;
@@ -214,15 +182,11 @@ export default function Support(): JSX.Element {
case channelsMap.documentation:
case channelsMap.github:
case channelsMap.slack_community:
- case channelsMap.schedule_call:
handleChannelWithRedirects(channel.url);
break;
case channelsMap.chat:
handleChat();
break;
- case channelsMap.slack_connect:
- handleSlackConnectRequest();
- break;
default:
handleChannelWithRedirects('https://signoz.io/slack');
break;
diff --git a/frontend/src/pages/TraceDetail/__test__/TraceDetail.test.tsx b/frontend/src/pages/TraceDetail/__test__/TraceDetail.test.tsx
index b16bb6c735..3f2d419f72 100644
--- a/frontend/src/pages/TraceDetail/__test__/TraceDetail.test.tsx
+++ b/frontend/src/pages/TraceDetail/__test__/TraceDetail.test.tsx
@@ -139,9 +139,7 @@ describe('TraceDetail', () => {
const slider = await findByTestId('span-details-sider');
expect(slider).toBeInTheDocument();
- fireEvent.click(
- slider.querySelector('.ant-layout-sider-trigger') as HTMLElement,
- );
+ fireEvent.click(slider.querySelector('.expand-collapse-btn') as HTMLElement);
expect(queryByText('Details for selected Span')).not.toBeInTheDocument();
});
diff --git a/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss b/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss
index cf6eb52b10..4323f901d5 100644
--- a/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss
+++ b/frontend/src/pages/TracesExplorer/TracesExplorer.styles.scss
@@ -1,6 +1,7 @@
.trace-explorer-header {
display: flex;
justify-content: space-between;
+ align-items: center;
.trace-explorer-run-query {
display: flex;
diff --git a/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx b/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx
index c22401f7c4..68df0f5d7c 100644
--- a/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx
+++ b/frontend/src/pages/WorkspaceLocked/CustomerStoryCard.tsx
@@ -32,4 +32,5 @@ function CustomerStoryCard({
);
}
+
export default CustomerStoryCard;
diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss
index 131601bfb0..d2317c8c68 100644
--- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss
+++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.styles.scss
@@ -1,4 +1,5 @@
$light-theme: 'lightMode';
+$dark-theme: 'darkMode';
@keyframes gradientFlow {
0% {
@@ -147,6 +148,34 @@ $light-theme: 'lightMode';
animation: gradientFlow 24s ease infinite;
margin-bottom: 18px;
}
+
+ &__faq-container {
+ width: 100%;
+
+ .ant-collapse,
+ .ant-collapse-item,
+ .ant-collapse-content-active {
+ .#{$dark-theme} & {
+ border-color: var(--bg-slate-400);
+ }
+ }
+ }
+
+ &__customer-stories {
+ &__left-container,
+ &__right-container {
+ display: flex;
+ flex-direction: column;
+ }
+
+ &__left-container {
+ align-items: flex-end;
+ }
+
+ &__right-container {
+ align-items: flex-start;
+ }
+ }
}
.contact-us {
diff --git a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx
index 84d977ae81..602e666137 100644
--- a/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx
+++ b/frontend/src/pages/WorkspaceLocked/WorkspaceLocked.tsx
@@ -54,6 +54,25 @@ export default function WorkspaceBlocked(): JSX.Element {
data: licensesData,
} = useLicense();
+ useEffect((): void => {
+ logEvent('Workspace Blocked: Screen Viewed', {});
+ }, []);
+
+ const handleContactUsClick = (): void => {
+ logEvent('Workspace Blocked: Contact Us Clicked', {});
+ };
+
+ const handleTabClick = (key: string): void => {
+ logEvent('Workspace Blocked: Screen Tabs Clicked', { tabKey: key });
+ };
+
+ const handleCollapseChange = (key: string | string[]): void => {
+ const lastKey = Array.isArray(key) ? key.slice(-1)[0] : key;
+ logEvent('Workspace Blocked: Screen Tab FAQ Item Clicked', {
+ panelKey: lastKey,
+ });
+ };
+
useEffect(() => {
if (!isFetchingLicenseData) {
const shouldBlockWorkspace = licensesData?.payload?.workSpaceBlock;
@@ -135,7 +154,7 @@ export default function WorkspaceBlocked(): JSX.Element {
const tabItems: TabsProps['items'] = [
{
- key: '1',
+ key: 'whyChooseSignoz',
label: t('whyChooseSignoz'),
children: (
@@ -182,13 +201,23 @@ export default function WorkspaceBlocked(): JSX.Element {
),
},
{
- key: '2',
+ key: 'youAreInGoodCompany',
label: t('youAreInGoodCompany'),
children: (
{/* #FIXME: please suggest if there is any better way to loop in different columns to get the masonry layout */}
- {renderCustomerStories((index) => index % 2 === 0)}
- {renderCustomerStories((index) => index % 2 !== 0)}
+
+ {renderCustomerStories((index) => index % 2 === 0)}
+
+
+ {renderCustomerStories((index) => index % 2 !== 0)}
+
{isAdmin && (
@@ -214,13 +243,21 @@ export default function WorkspaceBlocked(): JSX.Element {
// children: 'Our Pricing',
// },
{
- key: '4',
+ key: 'faqs',
label: t('faqs'),
children: (
-
-
-
+
+
+
{isAdmin && (
@@ -324,7 +362,7 @@ export default function WorkspaceBlocked(): JSX.Element {
loading={isLoading}
onClick={handleUpdateCreditCard}
>
- continue my journey
+ Continue my Journey
@@ -340,9 +378,13 @@ export default function WorkspaceBlocked(): JSX.Element {
)}
-
-
-
+
+
+
>
)}
diff --git a/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts b/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts
index 0f4d07b96e..bebcdaf64a 100644
--- a/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts
+++ b/frontend/src/pages/WorkspaceLocked/workspaceLocked.data.ts
@@ -42,7 +42,7 @@ export const enterpriseGradeValuesData = [
export const customerStoriesData = [
{
- key: 'c-story-1',
+ key: 'story-subomi-oluwalana',
avatar: 'https://signoz.io/img/users/subomi-oluwalana.webp',
personName: 'Subomi Oluwalana',
role: 'Founder & CEO at Convoy',
@@ -53,7 +53,7 @@ export const customerStoriesData = [
'https://www.linkedin.com/feed/update/urn:li:activity:7212117589068591105/',
},
{
- key: 'c-story-2',
+ key: 'story-dhruv-garg',
avatar: 'https://signoz.io/img/users/dhruv-garg.webp',
personName: 'Dhruv Garg',
role: 'Tech Lead at Nudge',
@@ -64,7 +64,7 @@ export const customerStoriesData = [
'https://www.linkedin.com/posts/dhruv-garg79_signoz-docker-kubernetes-activity-7205163679028240384-Otlb/',
},
{
- key: 'c-story-3',
+ key: 'story-vivek-bhakta',
avatar: 'https://signoz.io/img/users/vivek-bhakta.webp',
personName: 'Vivek Bhakta',
role: 'CTO at Wombo AI',
@@ -74,7 +74,7 @@ export const customerStoriesData = [
link: 'https://x.com/notorious_VB/status/1701773119696904242',
},
{
- key: 'c-story-4',
+ key: 'story-pranay-narang',
avatar: 'https://signoz.io/img/users/pranay-narang.webp',
personName: 'Pranay Narang',
role: 'Engineering at Azodha',
@@ -84,7 +84,7 @@ export const customerStoriesData = [
link: 'https://x.com/PranayNarang/status/1676247073396752387',
},
{
- key: 'c-story-4',
+ key: 'story-Sheheryar-Sewani',
avatar: 'https://signoz.io/img/users/shey.webp',
personName: 'Sheheryar Sewani',
role: 'Seasoned Rails Dev & Founder',
@@ -95,7 +95,7 @@ export const customerStoriesData = [
'https://www.linkedin.com/feed/update/urn:li:activity:7181011853915926528/',
},
{
- key: 'c-story-5',
+ key: 'story-daniel-schell',
avatar: 'https://signoz.io/img/users/daniel.webp',
personName: 'Daniel Schell',
role: 'Founder & CTO at Airlockdigital',
@@ -115,7 +115,7 @@ export const customerStoriesData = [
link: 'https://x.com/gofrendiasgard/status/1680139003658641408',
},
{
- key: 'c-story-7',
+ key: 'story-anselm-eickhoff',
avatar: 'https://signoz.io/img/users/anselm.jpg',
personName: 'Anselm Eickhoff',
role: 'Software Architect',
@@ -129,26 +129,26 @@ export const customerStoriesData = [
export const faqData = [
{
- key: '1',
+ key: 'signoz-cloud-vs-community',
label:
'What is the difference between SigNoz Cloud(Teams) and Community Edition?',
children:
'You can self-host and manage the community edition yourself. You should choose SigNoz Cloud if you don’t want to worry about managing the SigNoz cluster. There are some exclusive features like SSO & SAML support, which come with SigNoz cloud offering. Our team also offers support on the initial configuration of dashboards & alerts and advises on best practices for setting up your observability stack in the SigNoz cloud offering.',
},
{
- key: '2',
+ key: 'calc-for-metrics',
label: 'How are number of samples calculated for metrics pricing?',
children:
"If a timeseries sends data every 30s, then it will generate 2 samples per min. So, if you have 10,000 time series sending data every 30s then you will be sending 20,000 samples per min to SigNoz. This will be around 864 mn samples per month and would cost 86.4 USD/month. Here's an explainer video on how metrics pricing is calculated - Link: https://vimeo.com/973012522",
},
{
- key: '3',
+ key: 'enterprise-support-plans',
label: 'Do you offer enterprise support plans?',
children:
'Yes, feel free to reach out to us on hello@signoz.io if you need a dedicated support plan or paid support for setting up your initial SigNoz setup.',
},
{
- key: '4',
+ key: 'who-should-use-enterprise-plans',
label: 'Who should use Enterprise plans?',
children:
'Teams which need enterprise support or features like SSO, Audit logs, etc. may find our enterprise plans valuable.',
diff --git a/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx b/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx
index 6b90704b0c..9c77d514e0 100644
--- a/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx
+++ b/frontend/src/periscope/components/LineClampedText/LineClampedText.tsx
@@ -1,14 +1,16 @@
import './LineClampedText.styles.scss';
-import { Tooltip } from 'antd';
+import { Tooltip, TooltipProps } from 'antd';
import { useEffect, useRef, useState } from 'react';
function LineClampedText({
text,
lines,
+ tooltipProps,
}: {
text: string;
lines?: number;
+ tooltipProps?: TooltipProps;
}): JSX.Element {
const [isOverflowing, setIsOverflowing] = useState(false);
const textRef = useRef
(null);
@@ -42,11 +44,22 @@ function LineClampedText({
+ ) : (
+ content
+ );
}
LineClampedText.defaultProps = {
lines: 1,
+ tooltipProps: {},
};
export default LineClampedText;
diff --git a/frontend/src/providers/Alert.tsx b/frontend/src/providers/Alert.tsx
index 337eec9ba5..50b6584491 100644
--- a/frontend/src/providers/Alert.tsx
+++ b/frontend/src/providers/Alert.tsx
@@ -1,10 +1,8 @@
import React, { createContext, useContext, useState } from 'react';
interface AlertRuleContextType {
- isAlertRuleDisabled: boolean | undefined;
- setIsAlertRuleDisabled: React.Dispatch<
- React.SetStateAction