Skip to content
Draft
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/tinybird-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Tinybird CD

on:
workflow_dispatch:
push:
branches:
- main
- master
paths:
- 'tinybird/**'

concurrency: ${{ github.workflow }}-${{ github.event.ref }}

jobs:
cd:
name: Deploy
runs-on: ubuntu-latest
defaults:
run:
working-directory: 'tinybird'
steps:
- uses: actions/checkout@v3

- name: Install Tinybird CLI
run: curl https://tinybird.co | sh

- name: Deploy project
with:
TINYBIRD_HOST: ${{ secrets.TINYBIRD_HOST }}
TINYBIRD_TOKEN: ${{ secrets.TINYBIRD_TOKEN }}
run: tb --cloud --host "${{ env.TINYBIRD_HOST }}" --token "${{ env.TINYBIRD_TOKEN }}" deploy
43 changes: 43 additions & 0 deletions .github/workflows/tinybird-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Tinybird CI

on:
workflow_dispatch:
pull_request:
branches:
- main
- master
paths:
- 'tinybird/**'
types: [opened, reopened, labeled, unlabeled, synchronize]

concurrency: ${{ github.workflow }}-${{ github.event.pull_request.number }}

jobs:
ci:
name: Validate
runs-on: ubuntu-latest
defaults:
run:
working-directory: 'tinybird'
services:
tinybird:
image: tinybirdco/tinybird-local:latest
ports:
- 7181:7181
steps:
- uses: actions/checkout@v3

- name: Install Tinybird CLI
run: curl https://tinybird.co | sh

- name: Build project
run: tb build

- name: Test project
run: tb test run

- name: Deployment check
with:
TINYBIRD_HOST: ${{ secrets.TINYBIRD_HOST }}
TINYBIRD_TOKEN: ${{ secrets.TINYBIRD_TOKEN }}
run: tb --cloud deploy --check
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@ tauri.windows.conf.json
# Cursor
.cursor
.env*.local

# Tinybird
.tinyb
28 changes: 0 additions & 28 deletions apps/web/actions/videos/get-analytics.ts

This file was deleted.

6 changes: 3 additions & 3 deletions apps/web/app/(org)/dashboard/caps/Caps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { useEffectMutation, useRpcClient } from "@/lib/EffectRuntime";
import { useVideosAnalyticsQuery } from "@/lib/Queries/Analytics";
import { usePublicEnv } from "@/utils/public-env";
import { useDashboardContext } from "../Contexts";
import {
NewFolderDialog,
Expand Down Expand Up @@ -54,18 +55,17 @@ export type VideoData = {
export const Caps = ({
data,
count,
dubApiKeyEnabled,
folders,
}: {
data: VideoData;
count: number;
folders: FolderDataType[];
dubApiKeyEnabled: boolean;
}) => {
const router = useRouter();
const params = useSearchParams();
const page = Number(params.get("page")) || 1;
const { user } = useDashboardContext();
const publicEnv = usePublicEnv();
const limit = 15;
const [openNewFolderDialog, setOpenNewFolderDialog] = useState(false);
const totalPages = Math.ceil(count / limit);
Expand All @@ -77,7 +77,7 @@ export const Caps = ({

const analyticsQuery = useVideosAnalyticsQuery(
data.map((video) => video.id),
dubApiKeyEnabled,
publicEnv.analyticsAvailable,
);
const analytics = analyticsQuery.data || {};

Expand Down
7 changes: 1 addition & 6 deletions apps/web/app/(org)/dashboard/caps/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,6 @@ export default async function CapsPage(props: PageProps<"/dashboard/caps">) {
).pipe(runPromise);

return (
<Caps
data={processedVideoData}
folders={foldersData}
count={totalCount}
dubApiKeyEnabled={!!serverEnv().DUB_API_KEY}
/>
<Caps data={processedVideoData} folders={foldersData} count={totalCount} />
);
}
22 changes: 0 additions & 22 deletions apps/web/app/api/analytics/route.ts

This file was deleted.

4 changes: 4 additions & 0 deletions apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ export default ({ children }: PropsWithChildren) =>
webUrl: buildEnv.NEXT_PUBLIC_WEB_URL,
workosAuthAvailable: !!serverEnv().WORKOS_CLIENT_ID,
googleAuthAvailable: !!serverEnv().GOOGLE_CLIENT_ID,
analyticsAvailable:
!!serverEnv().DUB_API_KEY ||
(!!serverEnv().TINYBIRD_HOST &&
!!serverEnv().TINYBIRD_TOKEN),
}}
>
<ReactQueryProvider>
Expand Down
15 changes: 12 additions & 3 deletions apps/web/app/s/[videoId]/_components/ShareVideo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { userSelectProps } from "@cap/database/auth/session";
import type { comments as commentsSchema, videos } from "@cap/database/schema";
import type { comments as commentsSchema } from "@cap/database/schema";
import { NODE_ENV } from "@cap/env";
import { Logo } from "@cap/ui";
import type { ImageUpload } from "@cap/web-domain";
Expand All @@ -11,8 +10,8 @@ import {
useRef,
useState,
} from "react";
import type { OrganizationSettings } from "@/app/(org)/dashboard/dashboard-data";
import { UpgradeModal } from "@/components/UpgradeModal";
import { useEffectMutation, useRpcClient } from "@/lib/EffectRuntime";
import type { VideoData } from "../types";
import { CapVideoPlayer } from "./CapVideoPlayer";
import { HLSVideoPlayer } from "./HLSVideoPlayer";
Expand Down Expand Up @@ -75,6 +74,16 @@ export const ShareVideo = forwardRef<
data.transcriptionStatus,
);

const rpc = useRpcClient();
const mutation = useEffectMutation({
mutationFn: () => rpc.VideoCaptureAnalytics(data.id),
});

// biome-ignore lint/correctness/useExhaustiveDependencies: just cause
useEffect(() => {
if (mutation.isIdle) mutation.mutate();
}, []);

// Handle comments data
useEffect(() => {
if (comments) {
Expand Down
27 changes: 4 additions & 23 deletions apps/web/app/s/[videoId]/_components/tabs/Activity/Analytics.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,14 @@
"use client";

import { use, useEffect, useMemo, useState } from "react";
import { getVideoAnalytics } from "@/actions/videos/get-analytics";
import { use, useMemo } from "react";
import { CapCardAnalytics } from "@/app/(org)/dashboard/caps/components/CapCard/CapCardAnalytics";
import type { CommentType } from "../../../Share";

const Analytics = (props: {
videoId: string;
views: MaybePromise<number>;
comments: CommentType[];
isLoadingAnalytics: boolean;
}) => {
const [views, setViews] = useState(
props.views instanceof Promise ? use(props.views) : props.views,
);

useEffect(() => {
const fetchAnalytics = async () => {
try {
const result = await getVideoAnalytics(props.videoId);

setViews(result.count);
} catch (error) {
console.error("Error fetching analytics:", error);
}
};

fetchAnalytics();
}, [props.videoId]);
const views =
typeof props.views === "number" ? props.views : use(props.views);

const totalComments = useMemo(
() => props.comments.filter((c) => c.type === "text").length,
Expand All @@ -41,7 +22,7 @@ const Analytics = (props: {

return (
<CapCardAnalytics
isLoadingAnalytics={props.isLoadingAnalytics}
isLoadingAnalytics={false}
capId={props.videoId}
displayCount={views}
totalComments={totalComments}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export const Activity = Object.assign(
videoId={videoId}
views={props.views}
comments={comments}
isLoadingAnalytics={false}
/>
</Suspense>
}
Expand Down
21 changes: 9 additions & 12 deletions apps/web/app/s/[videoId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
videos,
videoUploads,
} from "@cap/database/schema";
import type { VideoMetadata } from "@cap/database/types";
import { buildEnv } from "@cap/env";
import { Logo } from "@cap/ui";
import { userIsPro } from "@cap/utils";
Expand All @@ -22,21 +21,14 @@ import {
Videos,
} from "@cap/web-backend";
import { VideosPolicy } from "@cap/web-backend/src/Videos/VideosPolicy";
import {
Comment,
type ImageUpload,
type Organisation,
Policy,
type Video,
} from "@cap/web-domain";
import { Comment, type Organisation, Policy, Video } from "@cap/web-domain";
import { eq, type InferSelectModel, sql } from "drizzle-orm";
import { Effect, Option } from "effect";
import type { Metadata } from "next";
import { headers } from "next/headers";
import Link from "next/link";
import { notFound } from "next/navigation";
import { generateAiMetadata } from "@/actions/videos/generate-ai-metadata";
import { getVideoAnalytics } from "@/actions/videos/get-analytics";
import {
getDashboardData,
type OrganizationSettings,
Expand Down Expand Up @@ -254,7 +246,7 @@ export async function generateMetadata(
export default async function ShareVideoPage(props: PageProps<"/s/[videoId]">) {
const params = await props.params;
const searchParams = await props.searchParams;
const videoId = params.videoId as Video.VideoId;
const videoId = Video.VideoId.make(params.videoId);

return Effect.gen(function* () {
const videosPolicy = yield* VideosPolicy;
Expand Down Expand Up @@ -492,7 +484,7 @@ async function AuthorizedContent({
}
}

const currentMetadata = (video.metadata as VideoMetadata) || {};
const currentMetadata = video.metadata || {};
const metadata = currentMetadata;
let initialAiData = null;

Expand Down Expand Up @@ -679,7 +671,12 @@ async function AuthorizedContent({
);
}).pipe(EffectRuntime.runPromise);

const viewsPromise = getVideoAnalytics(videoId).then((v) => v.count);
const viewsPromise = Effect.flatMap(Videos, (videos) =>
videos.getAnalytics(videoId),
).pipe(
Effect.map((v) => v.count),
EffectRuntime.runPromise,
);

const [
membersList,
Expand Down
1 change: 1 addition & 0 deletions apps/web/utils/public-env.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type PublicEnvContext = {
webUrl: string;
googleAuthAvailable: boolean;
workosAuthAvailable: boolean;
analyticsAvailable: boolean;
};

const Context = createContext<PublicEnvContext | null>(null);
Expand Down
2 changes: 2 additions & 0 deletions packages/env/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ function createServerEnv() {
VERCEL_AWS_ROLE_ARN: z.string().optional(),
WORKFLOWS_RPC_URL: z.string().optional(),
WORKFLOWS_RPC_SECRET: z.string().optional(),
TINYBIRD_HOST: z.string().optional(),
TINYBIRD_TOKEN: z.string().optional(),
},
experimental__runtimeEnv: {
...process.env,
Expand Down
1 change: 1 addition & 0 deletions packages/web-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@cap/database": "workspace:*",
"@cap/utils": "workspace:*",
"@cap/web-domain": "workspace:*",
"@cap/env": "workspace:*",
"@effect/cluster": "^0.50.4",
"@effect/platform": "^0.92.1",
"@effect/rpc": "^0.71.0",
Expand Down
14 changes: 14 additions & 0 deletions packages/web-backend/src/Videos/VideosRpcs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ export const VideosRpcsLive = Video.VideoRpcs.toLayer(
videos.getAnalytics(id).pipe(
Effect.catchTags({
DatabaseError: () => new InternalError({ type: "database" }),
RequestError: () => new InternalError({ type: "httpRequest" }),
ResponseError: () =>
new InternalError({ type: "httpResponse" }),
UnknownException: () => new InternalError({ type: "unknown" }),
}),
Effect.matchEffect({
Expand All @@ -97,6 +100,17 @@ export const VideosRpcsLive = Video.VideoRpcs.toLayer(
UnknownException: () => new InternalError({ type: "unknown" }),
}),
),

VideoCaptureAnalytics: (videoId) =>
videos.captureAnalytics(videoId).pipe(
provideOptionalAuth,
Effect.catchTags({
DatabaseError: () => new InternalError({ type: "database" }),
RequestError: () => new InternalError({ type: "httpRequest" }),
ResponseError: () => new InternalError({ type: "httpResponse" }),
UnknownException: () => new InternalError({ type: "unknown" }),
}),
),
};
}),
);
Loading
Loading