Add webhook response graph from the last 5 days (#7487)
#7346 #7343 #7342 #7344 Before: <img width="799" alt="Screenshot 2024-10-08 at 11 59 37" src="https://github.com/user-attachments/assets/a1cd1714-41ed-4f96-85eb-2861e7a8b2c2"> Now:  In order to test: 1. Set ANALYTICS_ENABLED to true 2. Set TINYBIRD_TOKEN to your token from the workspace _twenty_analytics_playground_ 3. Write your client tinybird token in SettingsDeveloppersWebhookDetail.tsx in line 93 4. Create a Webhook in twenty and set wich events it needs to track 5. Run twenty-worker in order to make the webhooks work. 6. Do your tasks in order to populate the data 7. Enter to settings> webhook>your webhook and the statistics section should be displayed.
This commit is contained in:
committed by
GitHub
parent
798722179e
commit
f901512a4f
@ -0,0 +1,59 @@
|
||||
import { webhookGraphDataState } from '@/settings/developers/webhook/states/webhookGraphDataState';
|
||||
import styled from '@emotion/styled';
|
||||
import { ResponsiveLine } from '@nivo/line';
|
||||
import { Section } from '@react-email/components';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { H2Title } from 'twenty-ui';
|
||||
|
||||
export type NivoLineInput = {
|
||||
id: string | number;
|
||||
color?: string;
|
||||
data: Array<{
|
||||
x: number | string | Date;
|
||||
y: number | string | Date;
|
||||
}>;
|
||||
};
|
||||
const StyledGraphContainer = styled.div`
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
`;
|
||||
export const SettingsDeveloppersWebhookUsageGraph = () => {
|
||||
const webhookGraphData = useRecoilValue(webhookGraphDataState);
|
||||
|
||||
return (
|
||||
<>
|
||||
{webhookGraphData.length ? (
|
||||
<Section>
|
||||
<H2Title title="Statistics" />
|
||||
<StyledGraphContainer>
|
||||
<ResponsiveLine
|
||||
data={webhookGraphData}
|
||||
colors={(d) => d.color}
|
||||
margin={{ top: 0, right: 0, bottom: 50, left: 60 }}
|
||||
xFormat="time:%Y-%m-%d %H:%M%"
|
||||
xScale={{
|
||||
type: 'time',
|
||||
useUTC: false,
|
||||
format: '%Y-%m-%d %H:%M:%S',
|
||||
precision: 'hour',
|
||||
}}
|
||||
yScale={{
|
||||
type: 'linear',
|
||||
}}
|
||||
axisBottom={{
|
||||
tickValues: 'every day',
|
||||
format: '%b %d',
|
||||
}}
|
||||
enableTouchCrosshair={true}
|
||||
enableGridY={false}
|
||||
enableGridX={false}
|
||||
enablePoints={false}
|
||||
/>
|
||||
</StyledGraphContainer>
|
||||
</Section>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,101 @@
|
||||
import { NivoLineInput } from '@/settings/developers/webhook/components/SettingsDevelopersWebhookUsageGraph';
|
||||
import { webhookGraphDataState } from '@/settings/developers/webhook/states/webhookGraphDataState';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
type SettingsDevelopersWebhookUsageGraphEffectProps = {
|
||||
webhookId: string;
|
||||
};
|
||||
|
||||
export const SettingsDevelopersWebhookUsageGraphEffect = ({
|
||||
webhookId,
|
||||
}: SettingsDevelopersWebhookUsageGraphEffectProps) => {
|
||||
const setWebhookGraphData = useSetRecoilState(webhookGraphDataState);
|
||||
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const queryString = new URLSearchParams({
|
||||
webhookIdRequest: webhookId,
|
||||
}).toString();
|
||||
const token = 'REPLACE_ME';
|
||||
const response = await fetch(
|
||||
`https://api.eu-central-1.aws.tinybird.co/v0/pipes/getWebhooksAnalytics.json?${queryString}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: 'Bearer ' + token,
|
||||
},
|
||||
},
|
||||
);
|
||||
const result = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
enqueueSnackBar('Something went wrong while fetching webhook usage', {
|
||||
variant: SnackBarVariant.Error,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const graphInput = result.data
|
||||
.flatMap(
|
||||
(dataRow: {
|
||||
start_interval: string;
|
||||
failure_count: number;
|
||||
success_count: number;
|
||||
}) => [
|
||||
{
|
||||
x: dataRow.start_interval,
|
||||
y: dataRow.failure_count,
|
||||
id: 'failure_count',
|
||||
color: 'red',
|
||||
},
|
||||
{
|
||||
x: dataRow.start_interval,
|
||||
y: dataRow.success_count,
|
||||
id: 'success_count',
|
||||
color: 'green',
|
||||
},
|
||||
],
|
||||
)
|
||||
.reduce(
|
||||
(
|
||||
acc: NivoLineInput[],
|
||||
{
|
||||
id,
|
||||
x,
|
||||
y,
|
||||
color,
|
||||
}: { id: string; x: string; y: number; color: string },
|
||||
) => {
|
||||
const existingGroupIndex = acc.findIndex(
|
||||
(group) => group.id === id,
|
||||
);
|
||||
const isExistingGroup = existingGroupIndex !== -1;
|
||||
|
||||
if (isExistingGroup) {
|
||||
return acc.map((group, index) =>
|
||||
index === existingGroupIndex
|
||||
? { ...group, data: [...group.data, { x, y }] }
|
||||
: group,
|
||||
);
|
||||
} else {
|
||||
return [...acc, { id, color, data: [{ x, y }] }];
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
setWebhookGraphData(graphInput);
|
||||
} catch (error) {
|
||||
enqueueSnackBar('Something went wrong while fetching webhook usage', {
|
||||
variant: SnackBarVariant.Error,
|
||||
});
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, [enqueueSnackBar, setWebhookGraphData, webhookId]);
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
import { NivoLineInput } from '@/settings/developers/webhook/components/SettingsDevelopersWebhookUsageGraph';
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const webhookGraphDataState = createState<NivoLineInput[]>({
|
||||
key: 'webhookGraphData',
|
||||
defaultValue: [],
|
||||
});
|
||||
Reference in New Issue
Block a user