feat(apps): add databuddy analytics (#24689)

* feat(apps): add databuddy analytics

* Update packages/app-store/databuddy/DESCRIPTION.md

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
Vachmara
2025-12-02 02:18:25 +00:00
committed by GitHub
co-authored by cubic-dev-ai[bot] Alex van Andel
parent b98bb8b852
commit f359d37799
17 changed files with 189 additions and 0 deletions
@@ -24,6 +24,7 @@ export const EventTypeAddonMap = {
basecamp3: dynamic(() => import("./basecamp3/components/EventTypeAppCardInterface")),
btcpayserver: dynamic(() => import("./btcpayserver/components/EventTypeAppCardInterface")),
closecom: dynamic(() => import("./closecom/components/EventTypeAppCardInterface")),
databuddy: dynamic(() => import("./databuddy/components/EventTypeAppCardInterface")),
fathom: dynamic(() => import("./fathom/components/EventTypeAppCardInterface")),
ga4: dynamic(() => import("./ga4/components/EventTypeAppCardInterface")),
giphy: dynamic(() => import("./giphy/components/EventTypeAppCardInterface")),
@@ -56,6 +57,7 @@ export const EventTypeSettingsMap = {
alby: dynamic(() => import("./alby/components/EventTypeAppSettingsInterface")),
basecamp3: dynamic(() => import("./basecamp3/components/EventTypeAppSettingsInterface")),
btcpayserver: dynamic(() => import("./btcpayserver/components/EventTypeAppSettingsInterface")),
databuddy: dynamic(() => import("./databuddy/components/EventTypeAppSettingsInterface")),
fathom: dynamic(() => import("./fathom/components/EventTypeAppSettingsInterface")),
ga4: dynamic(() => import("./ga4/components/EventTypeAppSettingsInterface")),
giphy: dynamic(() => import("./giphy/components/EventTypeAppSettingsInterface")),
@@ -7,6 +7,7 @@ import { appKeysSchema as basecamp3_zod_ts } from "./basecamp3/zod";
import { appKeysSchema as btcpayserver_zod_ts } from "./btcpayserver/zod";
import { appKeysSchema as closecom_zod_ts } from "./closecom/zod";
import { appKeysSchema as dailyvideo_zod_ts } from "./dailyvideo/zod";
import { appKeysSchema as databuddy_zod_ts } from "./databuddy/zod";
import { appKeysSchema as dub_zod_ts } from "./dub/zod";
import { appKeysSchema as fathom_zod_ts } from "./fathom/zod";
import { appKeysSchema as feishucalendar_zod_ts } from "./feishucalendar/zod";
@@ -58,6 +59,7 @@ export const appKeysSchemas = {
btcpayserver: btcpayserver_zod_ts,
closecom: closecom_zod_ts,
dailyvideo: dailyvideo_zod_ts,
databuddy: databuddy_zod_ts,
dub: dub_zod_ts,
fathom: fathom_zod_ts,
feishucalendar: feishucalendar_zod_ts,
@@ -18,6 +18,7 @@ import clic_config_json from "./clic/config.json";
import closecom_config_json from "./closecom/config.json";
import cron_config_json from "./cron/config.json";
import { metadata as dailyvideo__metadata_ts } from "./dailyvideo/_metadata";
import databuddy_config_json from "./databuddy/config.json";
import deel_config_json from "./deel/config.json";
import demodesk_config_json from "./demodesk/config.json";
import dialpad_config_json from "./dialpad/config.json";
@@ -128,6 +129,7 @@ export const appStoreMetadata = {
closecom: closecom_config_json,
cron: cron_config_json,
dailyvideo: dailyvideo__metadata_ts,
databuddy: databuddy_config_json,
deel: deel_config_json,
demodesk: demodesk_config_json,
dialpad: dialpad_config_json,
@@ -7,6 +7,7 @@ import { appDataSchema as basecamp3_zod_ts } from "./basecamp3/zod";
import { appDataSchema as btcpayserver_zod_ts } from "./btcpayserver/zod";
import { appDataSchema as closecom_zod_ts } from "./closecom/zod";
import { appDataSchema as dailyvideo_zod_ts } from "./dailyvideo/zod";
import { appDataSchema as databuddy_zod_ts } from "./databuddy/zod";
import { appDataSchema as dub_zod_ts } from "./dub/zod";
import { appDataSchema as fathom_zod_ts } from "./fathom/zod";
import { appDataSchema as feishucalendar_zod_ts } from "./feishucalendar/zod";
@@ -58,6 +59,7 @@ export const appDataSchemas = {
btcpayserver: btcpayserver_zod_ts,
closecom: closecom_zod_ts,
dailyvideo: dailyvideo_zod_ts,
databuddy: databuddy_zod_ts,
dub: dub_zod_ts,
fathom: fathom_zod_ts,
feishucalendar: feishucalendar_zod_ts,
@@ -18,6 +18,7 @@ export const apiHandlers = {
clic: import("./clic/api"),
closecom: import("./closecom/api"),
cron: import("./cron/api"),
databuddy: import("./databuddy/api"),
deel: import("./deel/api"),
demodesk: import("./demodesk/api"),
dialpad: import("./dialpad/api"),
@@ -4,6 +4,7 @@
**/
import campfire_config_json from "./campfire/config.json";
import { metadata as dailyvideo__metadata_ts } from "./dailyvideo/_metadata";
import databuddy_config_json from "./databuddy/config.json";
import demodesk_config_json from "./demodesk/config.json";
import dialpad_config_json from "./dialpad/config.json";
import discord_config_json from "./discord/config.json";
@@ -49,6 +50,7 @@ import { metadata as zoomvideo__metadata_ts } from "./zoomvideo/_metadata";
export const appStoreMetadata = {
campfire: campfire_config_json,
dailyvideo: dailyvideo__metadata_ts,
databuddy: databuddy_config_json,
demodesk: demodesk_config_json,
dialpad: dialpad_config_json,
discord: discord_config_json,
@@ -0,0 +1,8 @@
---
items:
- 1.png
---
Privacy-first web analytics for devs (Google Analytics alternative)
Track users, not identities. Get fast, accurate insights with zero cookies and 100% GDPR compliance.
+16
View File
@@ -0,0 +1,16 @@
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import { createDefaultInstallation } from "../../_utils/installation";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
@@ -0,0 +1 @@
export { default as add } from "./add";
@@ -0,0 +1,39 @@
import { useAppContextWithSchema } from "@calcom/app-store/EventTypeAppContext";
import AppCard from "@calcom/app-store/_components/AppCard";
import useIsAppEnabled from "@calcom/app-store/_utils/useIsAppEnabled";
import type { EventTypeAppCardComponent } from "@calcom/app-store/types";
import type { appDataSchema } from "../zod";
import EventTypeAppSettingsInterface from "./EventTypeAppSettingsInterface";
const EventTypeAppCard: EventTypeAppCardComponent = function EventTypeAppCard({
app,
eventType,
onAppInstallSuccess,
}) {
const { getAppData, setAppData, disabled } = useAppContextWithSchema<typeof appDataSchema>();
const { enabled, updateEnabled } = useIsAppEnabled(app);
return (
<AppCard
onAppInstallSuccess={onAppInstallSuccess}
hideSettingsIcon
app={app}
switchOnClick={(e) => {
updateEnabled(e);
}}
switchChecked={enabled}
teamId={eventType.team?.id || undefined}>
<EventTypeAppSettingsInterface
eventType={eventType}
slug={app.slug}
disabled={disabled}
getAppData={getAppData}
setAppData={setAppData}
/>
</AppCard>
);
};
export default EventTypeAppCard;
@@ -0,0 +1,52 @@
import type { EventTypeAppSettingsComponent } from "@calcom/app-store/types";
import { TextField } from "@calcom/ui/components/form";
const EventTypeAppSettingsInterface: EventTypeAppSettingsComponent = ({
getAppData,
setAppData,
disabled,
slug,
}) => {
const databuddy_script = getAppData("DATABUDDY_SCRIPT_URL");
const databuddy_api = getAppData("DATABUDDY_API_URL");
const client_id = getAppData("CLIENT_ID");
return (
<div className="flex flex-col gap-2">
<TextField
dataTestid={`${slug}-url`}
name="DataBuddy Script URL"
defaultValue="https://cdn.databuddy.cc/databuddy.js"
placeholder="https://cdn.databuddy.cc/databuddy.js"
value={databuddy_script}
disabled={disabled}
onChange={(e) => {
setAppData("DATABUDDY_SCRIPT_URL", e.target.value);
}}
/>
<TextField
dataTestid={`${slug}-api-url`}
name="DataBuddy API URL"
defaultValue="https://basket.databuddy.cc"
placeholder="https://basket.databuddy.cc"
value={databuddy_api}
disabled={disabled}
onChange={(e) => {
setAppData("DATABUDDY_API_URL", e.target.value);
}}
/>
<TextField
dataTestid={`${slug}-client-id`}
disabled={disabled}
name="Client ID"
placeholder="databuddy-client-id"
value={client_id}
onChange={(e) => {
setAppData("CLIENT_ID", e.target.value);
}}
/>
</div>
);
};
export default EventTypeAppSettingsInterface;
+29
View File
@@ -0,0 +1,29 @@
{
"/*": "Don't modify slug - If required, do it using cli edit command",
"name": "Databuddy",
"slug": "databuddy",
"type": "databuddy_analytics",
"logo": "icon.svg",
"url": "https://github.com/vachmara",
"variant": "analytics",
"categories": ["analytics"],
"publisher": "Valentin Chmara",
"email": "valentinchmara@gmail.com",
"extendsFeature": "EventType",
"appData": {
"tag": {
"scripts": [
{
"src": "{DATABUDDY_SCRIPT_URL}",
"attrs": {
"data-client-id": "{CLIENT_ID}",
"data-api-url": "{DATABUDDY_API_URL}"
}
}
]
}
},
"description": "Privacy-first web analytics for devs (Google Analytics alternative) — 3 KB, GDPR-compliant",
"__createdUsingCli": true,
"isOAuth": false
}
+1
View File
@@ -0,0 +1 @@
export * as api from "./api";
+14
View File
@@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/databuddy",
"version": "0.0.0",
"main": "./index.ts",
"description": "Privacy-first web analytics for devs (Google Analytics alternative) — 3 KB, GDPR-compliant",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

@@ -0,0 +1 @@
<svg width="512" height="512" viewBox="0 0 8 8" shape-rendering="crispEdges" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h8v8H0z"/><path fill="#fff" d="M1 1h1v6H1zm1 0h4v1H2zm4 1h1v1H6zm0 1h1v1H6zm0 1h1v1H6zm0 1h1v1H6zM2 6h4v1H2zm1-3h1v1H3zm1 1h1v1H4z"/></svg>

After

Width:  |  Height:  |  Size: 264 B

+17
View File
@@ -0,0 +1,17 @@
import { z } from "zod";
import { eventTypeAppCardZod } from "../eventTypeAppCardZod";
export const appDataSchema = eventTypeAppCardZod.merge(
z.object({
DATABUDDY_SCRIPT_URL: z
.string()
.optional()
.default("https://cdn.databuddy.cc/databuddy.js")
.or(z.undefined()),
DATABUDDY_API_URL: z.string().optional().default("https://basket.databuddy.cc").or(z.undefined()),
CLIENT_ID: z.string().default("").optional(),
})
);
export const appKeysSchema = z.object({});