From f60c008c66e99598066209940df4fbb91067ea2e Mon Sep 17 00:00:00 2001 From: anoopkarnik Date: Tue, 23 Jul 2024 01:43:49 +0530 Subject: [PATCH] added youtube channels --- .../connections/notion-connections.tsx | 18 +- .../connections/openai-connections.tsx | 13 +- .../actions/connections/user-connections.tsx | 12 +- .../connections/youtube-connections.tsx | 184 +++++++++++++++++- apps/dashboard-app/actions/notion/notion.ts | 48 +++-- .../actions/workflows/workflow.ts | 2 +- .../connections/_components/Connected.tsx | 4 +- .../app/(dashboard)/connections/page.tsx | 16 +- .../knowledge-base/_components/Settings.tsx | 2 + .../projects/_components/Settings.tsx | 10 +- .../_components/YoutubeChannelEmbed.tsx | 21 ++ .../youtube/_components/YoutubeGallery.tsx | 43 ++++ .../app/(dashboard)/youtube/page.tsx | 115 +++++++++++ .../app/api/callback/openai/route.ts | 4 +- .../app/api/oauth/youtube/route.ts | 9 +- .../components/ConnectionCard.tsx | 2 +- apps/dashboard-app/components/DbSelection.tsx | 15 +- apps/dashboard-app/components/NotionTable.tsx | 10 - apps/dashboard-app/lib/constant.ts | 14 +- apps/dashboard-app/next.config.mjs | 5 +- .../providers/connections-provider.tsx | 5 +- packages/notion/src/index.ts | 1 + .../migration.sql | 77 ++++++++ .../migration.sql | 76 ++++++++ .../migration.sql | 14 ++ .../migration.sql | 11 ++ .../migration.sql | 3 + .../migration.sql | 14 ++ .../migration.sql | 8 + .../prisma-db/prisma/schema/connection.prisma | 76 +++----- packages/prisma-db/prisma/schema/user.prisma | 7 +- .../prisma-db/prisma/schema/workflow.prisma | 6 +- packages/prisma-db/src/connection.ts | 158 +++++++++++++-- packages/prisma-db/src/notion.ts | 83 -------- packages/prisma-db/src/openAi.ts | 53 ----- packages/prisma-db/src/workflow.ts | 16 +- packages/prisma-db/src/youtube.ts | 52 ----- 37 files changed, 856 insertions(+), 351 deletions(-) create mode 100644 apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeChannelEmbed.tsx create mode 100644 apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeGallery.tsx create mode 100644 apps/dashboard-app/app/(dashboard)/youtube/page.tsx create mode 100644 packages/prisma-db/prisma/migrations/20240719020538_modified_to_connection/migration.sql create mode 100644 packages/prisma-db/prisma/migrations/20240719021558_modified_to_connection/migration.sql create mode 100644 packages/prisma-db/prisma/migrations/20240722171112_added_youtube_video/migration.sql create mode 100644 packages/prisma-db/prisma/migrations/20240722174520_added_youtube_video/migration.sql create mode 100644 packages/prisma-db/prisma/migrations/20240722180125_added_youtube_video/migration.sql create mode 100644 packages/prisma-db/prisma/migrations/20240722180556_added_youtube_video/migration.sql create mode 100644 packages/prisma-db/prisma/migrations/20240722181039_added_youtube_video/migration.sql delete mode 100644 packages/prisma-db/src/notion.ts delete mode 100644 packages/prisma-db/src/openAi.ts delete mode 100644 packages/prisma-db/src/youtube.ts diff --git a/apps/dashboard-app/actions/connections/notion-connections.tsx b/apps/dashboard-app/actions/connections/notion-connections.tsx index 57633f2..b71301f 100644 --- a/apps/dashboard-app/actions/connections/notion-connections.tsx +++ b/apps/dashboard-app/actions/connections/notion-connections.tsx @@ -1,7 +1,6 @@ 'use server' -import { createNotion, createNotionDb, getNotionByAccessToken, getNotionByUserId } from '@repo/prisma-db/repo/notion' - +import { createConnection, getConnectionByAccessToken, getConnectionsByUser, getConnectionsByUserAndType } from '@repo/prisma-db/repo/connection' interface notionProps { access_token: string, notion_connected: any, @@ -11,19 +10,18 @@ interface notionProps { userId: any } -export const onNotionConnection = async ({access_token, notion_connected, workspace_id, workspace_icon, workspace_name, - userId}: any) => { +export const onNotionConnection = async ({access_token, workspace_id, workspace_icon, workspace_name, userId}: any) => { if(access_token){ - const notion_connected = await getNotionByAccessToken(access_token) - if (!notion_connected){ - const notion = await createNotion({access_token, notion_connected, workspace_id, workspace_icon, workspace_name, userId}) - await createNotionDb({notionId: notion.id}) + const notion_connected = await getConnectionByAccessToken(access_token) + if (!notion_connected){ + const notion = await createConnection({type: 'Notion', userId, accessToken: access_token, workspaceName: workspace_name, workspaceIcon: workspace_icon, workspaceId: workspace_id}) + return notion; } } - + return null } export const getNotionConnection = async (userId: string) => { - const connection = await getNotionByUserId(userId) + const connection = await getConnectionsByUserAndType(userId, 'Notion') return connection } \ No newline at end of file diff --git a/apps/dashboard-app/actions/connections/openai-connections.tsx b/apps/dashboard-app/actions/connections/openai-connections.tsx index b12af98..8820a36 100644 --- a/apps/dashboard-app/actions/connections/openai-connections.tsx +++ b/apps/dashboard-app/actions/connections/openai-connections.tsx @@ -1,23 +1,20 @@ 'use server' -import { createOpenAI,getOpenAIByAPIKey,getOpenAIByUserId } from '@repo/prisma-db/repo/openAi' +import { createConnection, getConnectionByAPIKey, getConnectionsByUserAndType } from '@repo/prisma-db/repo/connection' -interface Props { - apiKey: string, - userId: string -} export const onOpenAIConnection = async ({apiKey,userId}:any) => { if(apiKey){ - const openai_connected = await getOpenAIByAPIKey(apiKey) + const openai_connected = await getConnectionByAPIKey(apiKey) if (!openai_connected){ - await createOpenAI({name: 'My OpenAI Key',apiKey,openai_connected, userId}) + const openai = await createConnection({apiKey,type:'OpenAI', userId}) + return openai; } } } export const getOpenAIConnection = async (userId: string) => { - const connection = await getOpenAIByUserId(userId) + const connection = await getConnectionsByUserAndType(userId, 'OpenAI') return connection } \ No newline at end of file diff --git a/apps/dashboard-app/actions/connections/user-connections.tsx b/apps/dashboard-app/actions/connections/user-connections.tsx index 1d2e781..ff1db02 100644 --- a/apps/dashboard-app/actions/connections/user-connections.tsx +++ b/apps/dashboard-app/actions/connections/user-connections.tsx @@ -1,7 +1,7 @@ 'use server' import { getConnectionByUser} from '@repo/prisma-db/repo/user' -import { updateConnection,deleteConnection, deleteYoutubeConnection, deleteNotionConnection, deleteOpenAIConnection } from '@repo/prisma-db/repo/connection' +import { updateConnection,deleteConnection, deleteNotionDb } from '@repo/prisma-db/repo/connection' export const getUserInfo = async (userId: string) => { const user_info:any = await getConnectionByUser(userId); return user_info; @@ -14,14 +14,8 @@ export const updateConnectionById = async (id: string, name: string) => { export const deleteConnectionById = async (id: string) => { const conn = await deleteConnection(id); - if (conn.type === 'Youtube') { - await deleteYoutubeConnection(conn.youtubeId as string); - } - else if (conn.type === 'OpenAI') { - await deleteOpenAIConnection(conn.openaiId as string); - } - else if (conn.type === 'Notion') { - await deleteNotionConnection(conn.notionId as string); + if (conn.type === 'Notion') { + await deleteNotionDb(id); } return conn; } \ No newline at end of file diff --git a/apps/dashboard-app/actions/connections/youtube-connections.tsx b/apps/dashboard-app/actions/connections/youtube-connections.tsx index d7a8e14..27a2815 100644 --- a/apps/dashboard-app/actions/connections/youtube-connections.tsx +++ b/apps/dashboard-app/actions/connections/youtube-connections.tsx @@ -1,19 +1,193 @@ 'use server' -import { createYoutube, getYoutubeByAccessToken, getYoutubeByUserId } from '@repo/prisma-db/repo/youtube' +import { createConnection, getConnectionByAccessToken, getConnectionsByUserAndType } from '@repo/prisma-db/repo/connection' +import axios from 'axios' +import { access } from 'fs' export const onYoutubeConnection = async ({access_token, refresh_token, scopes, userId}: any) => { if(access_token){ - const connected = await getYoutubeByAccessToken(access_token) + const connected = await getConnectionByAccessToken(access_token) if (!connected){ - const youtube = await createYoutube({name:'My Youtube Account', access_token, refresh_token, scopes, userId}) + const results = await GetChannelAndVideoIds(access_token) + const youtube = await createConnection({type:'Youtube', accessToken: access_token, refreshToken:refresh_token, scopes, userId, results}) + return youtube; } } + return null +} +export const GetChannelAndVideoIds = async (accessToken: string) => { + let nextPageChannelToken = true + let results:any = [] + while (nextPageChannelToken){ + let channels; + if (nextPageChannelToken === true){ + channels = await fetch(`https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&mine=true&maxResults=50`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + else{ + channels = await fetch(`https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&mine=true&maxResults=50&pageToken=${nextPageChannelToken}`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + const channelsJson = await channels.json() + console.log(channelsJson) + for (let channel of channelsJson.items){ + let nextPageToken = true + let channelId = channel.snippet.channelId + while (nextPageToken){ + let videos; + if (nextPageToken === true){ + videos = await fetch(`https://www.googleapis.com/youtube/v3/search?mine=true&maxResults=50&channelId=${channelId}`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + else{ + videos = await fetch(`https://www.googleapis.com/youtube/v3/searchh?channelId=${channelId}&mine=true&maxResults=50&pageToken=${nextPageToken}`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + const videosJson = await videos.json() + console.log(videosJson) + for (let video of videosJson.items){ + await results.push({channelId: channelId, videoId: video.id}) + } + if (videosJson.nextPageToken){ + nextPageToken = videosJson.nextPageToken + } + else{ + break + } + } + } + + + if (channelsJson.nextPageToken){ + nextPageChannelToken = channelsJson.nextPageToken + } + else{ + break + } + } + return results; } + export const getYoutubeConnection = async (userId: string) => { - const connection = await getYoutubeByUserId(userId) - return connection + const connections = await getConnectionsByUserAndType(userId, 'Youtube') + let result:any = [] + connections?.forEach((conn: any) => { + result.push({id: conn.id, name: conn.name, icon: '',access_token: conn.accessToken, refresh_token: conn.refreshToken, scopes: conn.scopes}) + }) + return result +} + +export const getChannels = async (userId: string, selectedAccount: string) => { + const connections = await getConnectionsByUserAndType(userId, 'Youtube') + const clientId = process.env.NEXT_PUBLIC_YOUTUBE_CLIENT_ID + const clientSecret = process.env.NEXT_PUBLIC_YOUTUBE_CLIENT_SECRET + if (!connections || connections.length === 0) return [] + let account = connections.find((conn: any) => conn.name === selectedAccount) + const refreshToken = account?.refreshToken + const response = await axios.post(`https://oauth2.googleapis.com/token`,null, { + params:{ + client_id: clientId, + client_secret: clientSecret, + refresh_token: refreshToken, + grant_type: 'refresh_token' + } + }) + console.log(response.data) + let accessToken = response.data.access_token + let nextPageToken = true + let results:any = [] + while (nextPageToken){ + let channels; + if (nextPageToken === true){ + channels = await fetch(`https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&mine=true&maxResults=50`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + else{ + channels = await fetch(`https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&mine=true&maxResults=50&pageToken=${nextPageToken}`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + const channelsJson = await channels.json() + for (let channel of channelsJson.items){ + await results.push({id: channel.id, name: channel.snippet.title, description: channel.snippet.description, + imageId: channel.snippet.thumbnails.high.url, channelId: channel.snippet.channelId}) + } + if (channelsJson.nextPageToken){ + nextPageToken = channelsJson.nextPageToken + } + else{ + break + } + } + return results +} + +export const getVideosByChannel = async (userId: string, channelId: string) => { + const connections = await getConnectionsByUserAndType(userId, 'Youtube') + const clientId = process.env.NEXT_PUBLIC_YOUTUBE_CLIENT_ID + const clientSecret = process.env.NEXT_PUBLIC_YOUTUBE_CLIENT_SECRET + if (!connections || connections.length === 0) return [] + let account = connections[0] + const refreshToken = account?.refreshToken + const response = await axios.post(`https://oauth2.googleapis.com/token`,null, { + params:{ + client_id: clientId, + client_secret: clientSecret, + refresh_token: refreshToken, + grant_type: 'refresh_token' + } + }) + console.log(response.data) + let accessToken = response.data.access_token + let nextPageToken = true + let results:any = [] + while (nextPageToken){ + let videos; + if (nextPageToken === true){ + videos = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=${channelId}&type=video&maxResults=50`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + else{ + videos = await fetch(`https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=${channelId}&type=video&maxResults=50&pageToken=${nextPageToken}`, { + headers: { + Authorization: `Bearer ${accessToken}` + } + }) + } + const videosJson = await videos.json() + for (let video of videosJson.items){ + await results.push({id: video.id.videoId, title: video.snippet.title, description: video.snippet.description, + imageId: video.snippet.thumbnails.high.url}) + } + if (videosJson.nextPageToken){ + nextPageToken = videosJson.nextPageToken + } + else{ + break + } + } + return results } \ No newline at end of file diff --git a/apps/dashboard-app/actions/notion/notion.ts b/apps/dashboard-app/actions/notion/notion.ts index 64b0e1b..4afc1fa 100644 --- a/apps/dashboard-app/actions/notion/notion.ts +++ b/apps/dashboard-app/actions/notion/notion.ts @@ -1,33 +1,45 @@ 'use server' -import { getNotionByUserId, updateNotionDb} from "@repo/prisma-db/repo/notion"; +import { getConnectionsByUserAndType, updateNotionDb} from "@repo/prisma-db/repo/connection"; import { getNotionDatabaseProperties, queryAllNotionDatabase, queryNotionDatabase } from '@repo/notion/notion-client' import { format } from "date-fns"; export const getDatabases = async (token: string) => { - const response = await fetch('https://api.notion.com/v1/search', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${token}`, - 'Content-Type': 'application/json', - 'Notion-Version': '2022-02-22' - }, - body: JSON.stringify({ - filter: { - value: 'database', - property: 'object' - } + try{ + const response = await fetch('https://api.notion.com/v1/search', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json', + 'Notion-Version': '2022-02-22' + }, + body: JSON.stringify({ + filter: { + value: 'database', + property: 'object' + } + }) + }); + const data = await response.json(); + const results:any = []; + data?.results.forEach((conn: any) => { + results.push({id: conn.id, name: conn?.title?.[0]?.text?.content, icon: conn?.icon?.emoji}) }) - }); - const data = await response.json(); - return data.results; + return results + } + catch(err){ + console.log(err) + } + } export const getNotionInfo = async (userId: string) => { - const notion_info = await getNotionByUserId(userId) - return notion_info; + const notion_info = await getConnectionsByUserAndType(userId, 'Notion'); + return notion_info?.[0]; } export const updateNotionDatabase = async (notionId: string, field:string, value: any) => { + + console.log('Update Notion Database', notionId, field, value) const notionDb = await updateNotionDb({id:notionId, field, value} ); return notionDb; } diff --git a/apps/dashboard-app/actions/workflows/workflow.ts b/apps/dashboard-app/actions/workflows/workflow.ts index 9320c36..a374237 100644 --- a/apps/dashboard-app/actions/workflows/workflow.ts +++ b/apps/dashboard-app/actions/workflows/workflow.ts @@ -47,7 +47,7 @@ export const getNodes = async (workflowId:string) => { } export const addNodeToWorkflow = async ({name,description,workflowId,type,userId,actionType,subActionType,actionData}:any) => { - console.log('Adding node to workflow',name,description,workflowId,type,userId,actionType,subActionType,actionData); + logger.info('Adding node to workflow',name,description,workflowId,type,userId,actionType,subActionType,actionData); const node:any = await createNode({name,description,workflowId,type,userId,actionType,subActionType,actionData}); return node; } diff --git a/apps/dashboard-app/app/(dashboard)/connections/_components/Connected.tsx b/apps/dashboard-app/app/(dashboard)/connections/_components/Connected.tsx index da45954..b10609b 100644 --- a/apps/dashboard-app/app/(dashboard)/connections/_components/Connected.tsx +++ b/apps/dashboard-app/app/(dashboard)/connections/_components/Connected.tsx @@ -16,11 +16,13 @@ const Connected = () => { if (session?.data?.user?.id) { const userInfo = await getUserInfo(session.data.user.id); const newConnections: any = []; + if (!userInfo) { + return; + } for (let connection of userInfo?.connections) { const cons = CONNECTIONS.find((con) => con.title === connection.type); if (cons) { const newConnection = { ...cons, ...connection }; - console.log() if (!connections.some((conn:any) => conn.id === newConnection.id)) { newConnections.push(newConnection); } diff --git a/apps/dashboard-app/app/(dashboard)/connections/page.tsx b/apps/dashboard-app/app/(dashboard)/connections/page.tsx index 14ad059..7a3e6fc 100644 --- a/apps/dashboard-app/app/(dashboard)/connections/page.tsx +++ b/apps/dashboard-app/app/(dashboard)/connections/page.tsx @@ -30,6 +30,7 @@ const PlannerPage = () => { const session = useSession() const user = session?.data?.user const userId = user?.id + const connectionsContext = useContext(ConnectionsContext) const handleSelect = (value:any) => { @@ -42,20 +43,19 @@ const PlannerPage = () => { const onUserConnection = async () =>{ if (user){ if (type === 'Notion'){ - await onNotionConnection({access_token,workspace_id,workspace_icon,workspace_name,database_id,userId}) + const notion = await onNotionConnection({access_token,workspace_id,workspace_icon,workspace_name,database_id,userId}) + connectionsContext.setNotionNode(notion) } if (type === 'OpenAI'){ - await onOpenAIConnection({apiKey,userId}) + const openAI = await onOpenAIConnection({apiKey,userId}) + connectionsContext.setOpenAINode(openAI) } if (type === 'Youtube'){ - await onYoutubeConnection({access_token,refresh_token,scopes,userId}) + const youtube = await onYoutubeConnection({access_token,refresh_token,scopes,userId}) } const user_info = await getUserInfo(userId || '') - const newConnections: Record = {} - user_info?.connections.forEach((connection: any) => { - newConnections[connection.type] = true - }) - setConnections(newConnections) + + setConnections(user_info?.connections) } } onUserConnection() diff --git a/apps/dashboard-app/app/(dashboard)/knowledge-base/_components/Settings.tsx b/apps/dashboard-app/app/(dashboard)/knowledge-base/_components/Settings.tsx index e60a174..07f0881 100644 --- a/apps/dashboard-app/app/(dashboard)/knowledge-base/_components/Settings.tsx +++ b/apps/dashboard-app/app/(dashboard)/knowledge-base/_components/Settings.tsx @@ -7,6 +7,7 @@ const Settings = () => { return (

Create or Attach your Knowledge Base Notion DBs

+
@@ -16,6 +17,7 @@ const Settings = () => { +
) } diff --git a/apps/dashboard-app/app/(dashboard)/projects/_components/Settings.tsx b/apps/dashboard-app/app/(dashboard)/projects/_components/Settings.tsx index 53c94e2..e33ddde 100644 --- a/apps/dashboard-app/app/(dashboard)/projects/_components/Settings.tsx +++ b/apps/dashboard-app/app/(dashboard)/projects/_components/Settings.tsx @@ -6,10 +6,12 @@ const Settings = () => { return (
-

Create or Attach your Projects DBs

- - - +

Create or Attach your Projects DBs

+
+ + + +
) } diff --git a/apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeChannelEmbed.tsx b/apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeChannelEmbed.tsx new file mode 100644 index 0000000..62b8a80 --- /dev/null +++ b/apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeChannelEmbed.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +const YouTubeChannelEmbed = ({ channelId }:any) => { + const embedUrl = `https://www.youtube.com/embed?listType=user_uploads&list=${channelId}`; + + return ( +
+ +
+ ); +}; + +export default YouTubeChannelEmbed; diff --git a/apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeGallery.tsx b/apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeGallery.tsx new file mode 100644 index 0000000..4bc051a --- /dev/null +++ b/apps/dashboard-app/app/(dashboard)/youtube/_components/YoutubeGallery.tsx @@ -0,0 +1,43 @@ +'use client' + +import React, { useEffect, useState } from 'react' + +import { getChannels } from '../../../../actions/connections/youtube-connections' +import { useSession } from 'next-auth/react' +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@repo/ui/molecules/shadcn/Card' +import { Button } from '@repo/ui/molecules/shadcn/Button' + +const YoutubeGallery = ({selectedAccount}:any) => { + const [cards, setCards] = useState([]) + const session = useSession() + const userId = session?.data?.user?.id + + useEffect(() => { + const updateCards = async () => { + const channels = await getChannels(userId || '',selectedAccount ) + + setCards(channels) + } + updateCards() + },[userId,selectedAccount]) + + return ( +
+ {cards.length > 0 && ( + cards.map((card:any) => ( + + + {card.name} + + + {card.name} + {card.description.substring(0,200) }......... + + + + )))} +
+ ) +} + +export default YoutubeGallery \ No newline at end of file diff --git a/apps/dashboard-app/app/(dashboard)/youtube/page.tsx b/apps/dashboard-app/app/(dashboard)/youtube/page.tsx new file mode 100644 index 0000000..4094049 --- /dev/null +++ b/apps/dashboard-app/app/(dashboard)/youtube/page.tsx @@ -0,0 +1,115 @@ +'use client' +import React, { useEffect, useState } from 'react' +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@repo/ui/molecules/shadcn/Tabs' +import { useMedia } from "react-use"; +import { Select, SelectContent, SelectItem, SelectTrigger } from '@repo/ui/molecules/shadcn/Select' +import { useRouter } from 'next/navigation' + +import { VideoIcon, VideoOffIcon } from 'lucide-react'; +import YoutubeGallery from './_components/YoutubeGallery'; +import { getChannels, getYoutubeConnection } from '../../../actions/connections/youtube-connections'; +import { useSession } from 'next-auth/react'; + +const ProjectsPage = () => { + const isMobile = useMedia("(max-width: 1324px)", false); + const [selectedValue, setSelectedValue] = useState('Channels') + const [selectedAccount, setSelectedAccount] = useState('My Official Account') + const [accounts, setAccounts] = useState([]) + const session = useSession(); + const userId = session?.data?.user?.id + + const handleSelect = (value:any) => { + setSelectedValue(value) + } + + useEffect(() =>{ + const updateAccounts = async () => { + const accounts = await getYoutubeConnection(userId || '') + setAccounts(accounts) + } + updateAccounts() + },[userId]) + + + if (isMobile){ + return ( +
+ + + {selectedValue === 'Channels' && } + {selectedValue === 'Videos' && } +
+ ) + } + + return ( + + + + +
Channels
+
+ + +
Videos
+
+ +
+ + + + + + +
+ + ) +} + +export default ProjectsPage \ No newline at end of file diff --git a/apps/dashboard-app/app/api/callback/openai/route.ts b/apps/dashboard-app/app/api/callback/openai/route.ts index 26d80ac..32797fe 100644 --- a/apps/dashboard-app/app/api/callback/openai/route.ts +++ b/apps/dashboard-app/app/api/callback/openai/route.ts @@ -4,7 +4,7 @@ export async function GET(req: NextRequest) { const apiKey = req.nextUrl.searchParams.get('apiKey'); const type = 'OpenAI'; if (apiKey) { - return NextResponse.redirect(`${process.env.NEXT_PUBLIC_URL}/dashboard/connections?apiKey=${apiKey}&type=${type}`); + return NextResponse.redirect(`${process.env.NEXT_PUBLIC_URL}/connections?apiKey=${apiKey}&type=${type}`); } - return NextResponse.redirect(`${process.env.NEXT_PUBLIC_URL}/dashboard/connections`); + return NextResponse.redirect(`${process.env.NEXT_PUBLIC_URL}/connections`); } diff --git a/apps/dashboard-app/app/api/oauth/youtube/route.ts b/apps/dashboard-app/app/api/oauth/youtube/route.ts index 3ab4b05..79c0580 100644 --- a/apps/dashboard-app/app/api/oauth/youtube/route.ts +++ b/apps/dashboard-app/app/api/oauth/youtube/route.ts @@ -1,4 +1,3 @@ -import axios from 'axios'; import { NextRequest, NextResponse } from 'next/server'; import { google } from 'googleapis'; @@ -19,12 +18,12 @@ export async function GET(req: NextRequest) { 'https://www.googleapis.com/auth/youtube.upload', ]; + const url = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) - access_type: 'offline', - - // If you only need one scope you can pass it as a string - scope: scopes + access_type: 'offline', + // If you only need one scope you can pass it as a string + scope: scopes }); return NextResponse.redirect(url); } \ No newline at end of file diff --git a/apps/dashboard-app/components/ConnectionCard.tsx b/apps/dashboard-app/components/ConnectionCard.tsx index 2536717..750e713 100644 --- a/apps/dashboard-app/components/ConnectionCard.tsx +++ b/apps/dashboard-app/components/ConnectionCard.tsx @@ -59,7 +59,7 @@ const ConnectionCard = ({connection}:any) => { {connection.description} - + ):( diff --git a/apps/dashboard-app/components/DbSelection.tsx b/apps/dashboard-app/components/DbSelection.tsx index 3a12f8e..cc5f8f9 100644 --- a/apps/dashboard-app/components/DbSelection.tsx +++ b/apps/dashboard-app/components/DbSelection.tsx @@ -1,13 +1,18 @@ +'use selection' + import React, { useContext, useEffect, useState } from 'react' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@repo/ui/molecules/shadcn/Select' import { ConnectionsContext } from '../providers/connections-provider' import { getDatabases } from '../actions/notion/notion' import { Button } from '@repo/ui/molecules/shadcn/Button' import { updateNotionDatabase } from '../actions/notion/notion' +import { useSession } from 'next-auth/react' const DbSelection = ({title,name,fieldName}:any) => { const connectionsContext = useContext(ConnectionsContext) const accessToken = connectionsContext.notionNode?.accessToken + const session = useSession() + const userId = session?.data?.user?.id const [databases, setDatabases] = useState([]) const [selectedDb, setSelectedDb] = useState('') @@ -18,7 +23,7 @@ const DbSelection = ({title,name,fieldName}:any) => { setDatabases(databases) } fetchDatabases() - },[accessToken]) + },[accessToken,userId]) useEffect(() => { if (!connectionsContext) return @@ -228,12 +233,12 @@ const DbSelection = ({title,name,fieldName}:any) => { {databases?.map((database:any) => ( - +
-
{database.icon?.emoji || "⛁"}
+
{database.icon|| "⛁"}
-
{database.title[0]?.text?.content}
+
{database.name}
{database.id}
diff --git a/apps/dashboard-app/components/NotionTable.tsx b/apps/dashboard-app/components/NotionTable.tsx index 68bbd29..199e1e0 100644 --- a/apps/dashboard-app/components/NotionTable.tsx +++ b/apps/dashboard-app/components/NotionTable.tsx @@ -6,17 +6,7 @@ import React, { useContext, useEffect, useState } from 'react' import { ConnectionsContext } from '../providers/connections-provider' import { queryNotionDatabaseAction, queryNotionDatabaseProperties } from '../actions/notion/notion' import { ArrowUpDown } from "lucide-react" -import { MoreHorizontal } from "lucide-react" -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@repo/ui/molecules/shadcn/Dropdown" - const NotionTable = ({dbId}:any) => { const connectionsContext = useContext(ConnectionsContext) diff --git a/apps/dashboard-app/lib/constant.ts b/apps/dashboard-app/lib/constant.ts index c0ad72c..da5536d 100644 --- a/apps/dashboard-app/lib/constant.ts +++ b/apps/dashboard-app/lib/constant.ts @@ -23,7 +23,9 @@ import { LandmarkIcon, ArrowLeftRightIcon, BadgeCentIcon, BluetoothConnectedIcon PieChartIcon, GoalIcon, TrophyIcon, - WormIcon} from "lucide-react"; + WormIcon, + YoutubeIcon, + VideoIcon} from "lucide-react"; import { Connection } from "./types"; import { Image } from "next-auth/providers/42-school"; import { sub } from "date-fns"; @@ -63,6 +65,16 @@ export const sidebarItems = [ title: "Connections", icon: BluetoothConnectedIcon, href: "/connections" + }, + { + title: 'Youtube', + icon: VideoIcon, + href: '/youtube' + }, + { + title: "Settings", + icon: Settings, + href: "/settings" } ] diff --git a/apps/dashboard-app/next.config.mjs b/apps/dashboard-app/next.config.mjs index f8dc20d..71c7c27 100644 --- a/apps/dashboard-app/next.config.mjs +++ b/apps/dashboard-app/next.config.mjs @@ -1,6 +1,9 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - transpilePackages: ["@repo/ui","@repo/next-auth","@repo/prisma-db"] + transpilePackages: ["@repo/ui","@repo/next-auth","@repo/prisma-db"], + images:{ + domains: ['yt.ggpht.com'] + } }; export default nextConfig; diff --git a/apps/dashboard-app/providers/connections-provider.tsx b/apps/dashboard-app/providers/connections-provider.tsx index ed417fa..51d75bc 100644 --- a/apps/dashboard-app/providers/connections-provider.tsx +++ b/apps/dashboard-app/providers/connections-provider.tsx @@ -4,6 +4,7 @@ import React, {createContext, useContext, useEffect, useState} from 'react' import useConnection from '../hooks/useConnection' import { useSession } from 'next-auth/react' import { getNotionInfo } from '../actions/notion/notion' +import { getYoutubeConnection } from '../actions/connections/youtube-connections' export type ConnectionProviderProps = { notionNode: { @@ -116,8 +117,8 @@ export const ConnectionsProvider = ({children}: ConnectionWithChildProps) => { useEffect(() =>{ const onAddConnection = async () =>{ - const notion_info = await getNotionInfo(userId || '') - console.log('Notion Info',notion_info) + const notion_info:any = await getNotionInfo(userId || '') + // const openAi_info = await getOpenAIByUserId(userId || '') if (notion_info){ setNotionNode({notionId: notion_info?.id,accessToken:notion_info?.accessToken,workspacename:notion_info?.workspaceName, diff --git a/packages/notion/src/index.ts b/packages/notion/src/index.ts index 1f9b42e..2a9976c 100644 --- a/packages/notion/src/index.ts +++ b/packages/notion/src/index.ts @@ -30,6 +30,7 @@ export const queryDatabase = async ({apiToken,database_id, body}:any) =>{ }) if (response.hasOwnProperty('status')){ logger.error(JSON.stringify(response)) + return {results:[],has_more:false,next_cursor:''}; } else{ logger.info(`sucessfully queried database - length - ${response.results.length} - has_more - ${response.has_more} - cursor - ${response.next_cursor}`); diff --git a/packages/prisma-db/prisma/migrations/20240719020538_modified_to_connection/migration.sql b/packages/prisma-db/prisma/migrations/20240719020538_modified_to_connection/migration.sql new file mode 100644 index 0000000..d91a538 --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240719020538_modified_to_connection/migration.sql @@ -0,0 +1,77 @@ +/* + Warnings: + + - You are about to drop the column `notionId` on the `Connections` table. All the data in the column will be lost. + - You are about to drop the column `openaiId` on the `Connections` table. All the data in the column will be lost. + - You are about to drop the column `youtubeId` on the `Connections` table. All the data in the column will be lost. + - You are about to drop the column `notionId` on the `NotionDb` table. All the data in the column will be lost. + - You are about to drop the `Notion` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `OpenAI` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Youtube` table. If the table is not empty, all the data it contains will be lost. + - A unique constraint covering the columns `[workspaceId]` on the table `Connections` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[connectionId]` on the table `NotionDb` will be added. If there are existing duplicate values, this will fail. + - Added the required column `updatedAt` to the `Connections` table without a default value. This is not possible if the table is not empty. + - Added the required column `updatedAt` to the `NotionDb` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "connection_schema"."Connections" DROP CONSTRAINT "Connections_notionId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."Connections" DROP CONSTRAINT "Connections_openaiId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."Connections" DROP CONSTRAINT "Connections_youtubeId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."Notion" DROP CONSTRAINT "Notion_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."NotionDb" DROP CONSTRAINT "NotionDb_notionId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."OpenAI" DROP CONSTRAINT "OpenAI_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."Youtube" DROP CONSTRAINT "Youtube_userId_fkey"; + +-- DropIndex +DROP INDEX "connection_schema"."NotionDb_notionId_key"; + +-- AlterTable +ALTER TABLE "connection_schema"."Connections" DROP COLUMN "notionId", +DROP COLUMN "openaiId", +DROP COLUMN "youtubeId", +ADD COLUMN "accessToken" TEXT, +ADD COLUMN "apiKey" TEXT, +ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "refreshToken" TEXT, +ADD COLUMN "scopes" TEXT, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL, +ADD COLUMN "workspaceIcon" TEXT, +ADD COLUMN "workspaceId" TEXT, +ADD COLUMN "workspaceName" TEXT; + +-- AlterTable +ALTER TABLE "connection_schema"."NotionDb" DROP COLUMN "notionId", +ADD COLUMN "connectionId" TEXT, +ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL; + +-- DropTable +DROP TABLE "connection_schema"."Notion"; + +-- DropTable +DROP TABLE "connection_schema"."OpenAI"; + +-- DropTable +DROP TABLE "connection_schema"."Youtube"; + +-- CreateIndex +CREATE UNIQUE INDEX "Connections_workspaceId_key" ON "connection_schema"."Connections"("workspaceId"); + +-- CreateIndex +CREATE UNIQUE INDEX "NotionDb_connectionId_key" ON "connection_schema"."NotionDb"("connectionId"); + +-- AddForeignKey +ALTER TABLE "connection_schema"."NotionDb" ADD CONSTRAINT "NotionDb_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "connection_schema"."Connections"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/packages/prisma-db/prisma/migrations/20240719021558_modified_to_connection/migration.sql b/packages/prisma-db/prisma/migrations/20240719021558_modified_to_connection/migration.sql new file mode 100644 index 0000000..5b6579b --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240719021558_modified_to_connection/migration.sql @@ -0,0 +1,76 @@ +/* + Warnings: + + - You are about to drop the `Connections` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Workflows` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropForeignKey +ALTER TABLE "connection_schema"."Connections" DROP CONSTRAINT "Connections_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "connection_schema"."NotionDb" DROP CONSTRAINT "NotionDb_connectionId_fkey"; + +-- DropForeignKey +ALTER TABLE "workflow_schema"."Event" DROP CONSTRAINT "Event_workflowId_fkey"; + +-- DropForeignKey +ALTER TABLE "workflow_schema"."Node" DROP CONSTRAINT "Node_workflowId_fkey"; + +-- DropForeignKey +ALTER TABLE "workflow_schema"."Workflows" DROP CONSTRAINT "Workflows_userId_fkey"; + +-- DropTable +DROP TABLE "connection_schema"."Connections"; + +-- DropTable +DROP TABLE "workflow_schema"."Workflows"; + +-- CreateTable +CREATE TABLE "connection_schema"."Connection" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL DEFAULT 'New Connection', + "type" TEXT NOT NULL, + "accessToken" TEXT, + "refreshToken" TEXT, + "scopes" TEXT, + "workspaceId" TEXT, + "workspaceName" TEXT, + "workspaceIcon" TEXT, + "apiKey" TEXT, + "userId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Connection_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "workflow_schema"."Workflow" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "publish" BOOLEAN DEFAULT false, + "description" TEXT NOT NULL, + "lastRun" TEXT, + "userId" TEXT NOT NULL, + + CONSTRAINT "Workflow_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Connection_workspaceId_key" ON "connection_schema"."Connection"("workspaceId"); + +-- AddForeignKey +ALTER TABLE "connection_schema"."NotionDb" ADD CONSTRAINT "NotionDb_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "connection_schema"."Connection"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "connection_schema"."Connection" ADD CONSTRAINT "Connection_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user_schema"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "workflow_schema"."Workflow" ADD CONSTRAINT "Workflow_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user_schema"."User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "workflow_schema"."Node" ADD CONSTRAINT "Node_workflowId_fkey" FOREIGN KEY ("workflowId") REFERENCES "workflow_schema"."Workflow"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "workflow_schema"."Event" ADD CONSTRAINT "Event_workflowId_fkey" FOREIGN KEY ("workflowId") REFERENCES "workflow_schema"."Workflow"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/packages/prisma-db/prisma/migrations/20240722171112_added_youtube_video/migration.sql b/packages/prisma-db/prisma/migrations/20240722171112_added_youtube_video/migration.sql new file mode 100644 index 0000000..1a22e2e --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240722171112_added_youtube_video/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "connection_schema"."Youtube" ( + "id" TEXT NOT NULL, + "videoId" TEXT NOT NULL, + "watched" BOOLEAN NOT NULL DEFAULT false, + "connectionId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Youtube_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "connection_schema"."Youtube" ADD CONSTRAINT "Youtube_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "connection_schema"."Connection"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/packages/prisma-db/prisma/migrations/20240722174520_added_youtube_video/migration.sql b/packages/prisma-db/prisma/migrations/20240722174520_added_youtube_video/migration.sql new file mode 100644 index 0000000..c2a014a --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240722174520_added_youtube_video/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - Added the required column `channelId` to the `Youtube` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "connection_schema"."Youtube" ADD COLUMN "channelId" TEXT NOT NULL; + +-- CreateIndex +CREATE INDEX "Youtube_channelId_watched_idx" ON "connection_schema"."Youtube"("channelId", "watched"); diff --git a/packages/prisma-db/prisma/migrations/20240722180125_added_youtube_video/migration.sql b/packages/prisma-db/prisma/migrations/20240722180125_added_youtube_video/migration.sql new file mode 100644 index 0000000..5a00a91 --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240722180125_added_youtube_video/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "connection_schema"."Youtube" ALTER COLUMN "videoId" DROP NOT NULL, +ALTER COLUMN "channelId" DROP NOT NULL; diff --git a/packages/prisma-db/prisma/migrations/20240722180556_added_youtube_video/migration.sql b/packages/prisma-db/prisma/migrations/20240722180556_added_youtube_video/migration.sql new file mode 100644 index 0000000..48f0803 --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240722180556_added_youtube_video/migration.sql @@ -0,0 +1,14 @@ +/* + Warnings: + + - Made the column `connectionId` on table `Youtube` required. This step will fail if there are existing NULL values in that column. + +*/ +-- DropForeignKey +ALTER TABLE "connection_schema"."Youtube" DROP CONSTRAINT "Youtube_connectionId_fkey"; + +-- AlterTable +ALTER TABLE "connection_schema"."Youtube" ALTER COLUMN "connectionId" SET NOT NULL; + +-- AddForeignKey +ALTER TABLE "connection_schema"."Youtube" ADD CONSTRAINT "Youtube_connectionId_fkey" FOREIGN KEY ("connectionId") REFERENCES "connection_schema"."Connection"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/packages/prisma-db/prisma/migrations/20240722181039_added_youtube_video/migration.sql b/packages/prisma-db/prisma/migrations/20240722181039_added_youtube_video/migration.sql new file mode 100644 index 0000000..283175b --- /dev/null +++ b/packages/prisma-db/prisma/migrations/20240722181039_added_youtube_video/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - A unique constraint covering the columns `[connectionId]` on the table `Youtube` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateIndex +CREATE UNIQUE INDEX "Youtube_connectionId_key" ON "connection_schema"."Youtube"("connectionId"); diff --git a/packages/prisma-db/prisma/schema/connection.prisma b/packages/prisma-db/prisma/schema/connection.prisma index 48c9b05..7c62373 100644 --- a/packages/prisma-db/prisma/schema/connection.prisma +++ b/packages/prisma-db/prisma/schema/connection.prisma @@ -1,17 +1,3 @@ -model Notion { - id String @id @default(uuid()) - accessToken String @unique - workspaceId String @unique - workspaceName String - workspaceIcon String - User User @relation(fields: [userId], references: [id]) - userId String - connections Connections[] - notionDb NotionDb? - - @@schema("connection_schema") -} - model NotionDb { id String @id @default(uuid()) accountsDb Json? @@ -45,47 +31,49 @@ model NotionDb { goalsDb Json? rewardsDb Json? punishmentsDb Json? - notionId String @unique - notion Notion? @relation(fields: [notionId], references: [id]) - @@schema("connection_schema") - -} + connection Connection? @relation(fields: [connectionId], references: [id]) + connectionId String? @unique -model OpenAI { - id String @id @default(uuid()) - apiKey String @unique - User User @relation(fields: [userId], references: [id]) - userId String - connections Connections[] + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt @@schema("connection_schema") -} - -model Youtube { - id String @id @default(uuid()) - accessToken String? @unique - refreshToken String? @unique - scopes String? - connections Connections[] - User User @relation(fields: [userId], references: [id]) - userId String - @@schema("connection_schema") } -model Connections { +model Connection { id String @id @default(uuid()) name String @default("New Connection") - type String - Notion Notion? @relation(fields: [notionId], references: [id]) - notionId String? - OpenAI OpenAI? @relation(fields: [openaiId], references: [id]) - openaiId String? - Youtube Youtube? @relation(fields: [youtubeId], references: [id]) - youtubeId String? + type String + accessToken String? + refreshToken String? + scopes String? + workspaceId String? @unique + workspaceName String? + workspaceIcon String? + apiKey String? + notionDb NotionDb? + youtube Youtube[] User User? @relation(fields: [userId], references: [id]) userId String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@schema("connection_schema") +} + +model Youtube { + id String @id @default(uuid()) + videoId String? + channelId String? + watched Boolean @default(false) + connection Connection @relation(fields: [connectionId], references: [id]) + connectionId String + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([channelId,watched]) @@schema("connection_schema") } \ No newline at end of file diff --git a/packages/prisma-db/prisma/schema/user.prisma b/packages/prisma-db/prisma/schema/user.prisma index e8ac9fb..64c568b 100644 --- a/packages/prisma-db/prisma/schema/user.prisma +++ b/packages/prisma-db/prisma/schema/user.prisma @@ -8,11 +8,8 @@ model User { accounts Account[] sessions Session[] password String? - Notion Notion[] - OpenAI OpenAI[] - Youtube Youtube[] - connections Connections[] - workflows Workflows[] + connections Connection[] + workflows Workflow[] nodes Node[] createdAt DateTime @default(now()) diff --git a/packages/prisma-db/prisma/schema/workflow.prisma b/packages/prisma-db/prisma/schema/workflow.prisma index f363334..2e03aec 100644 --- a/packages/prisma-db/prisma/schema/workflow.prisma +++ b/packages/prisma-db/prisma/schema/workflow.prisma @@ -1,4 +1,4 @@ -model Workflows { +model Workflow { id String @id @default(uuid()) nodes Node[] name String @@ -23,7 +23,7 @@ model Node { subActionType String? actionData Json? actionId String? - worklows Workflows @relation(fields: [workflowId], references: [id]) + worklows Workflow @relation(fields: [workflowId], references: [id]) userId String? User User? @relation(fields: [userId], references: [id]) @@schema("workflow_schema") @@ -32,7 +32,7 @@ model Node { model Event { id String @id @default(uuid()) workflowId String - Workflows Workflows @relation(fields: [workflowId], references: [id]) + Workflows Workflow @relation(fields: [workflowId], references: [id]) status String createdAt DateTime @default(now()) diff --git a/packages/prisma-db/src/connection.ts b/packages/prisma-db/src/connection.ts index a117aa1..745012e 100644 --- a/packages/prisma-db/src/connection.ts +++ b/packages/prisma-db/src/connection.ts @@ -1,7 +1,7 @@ import db from '@repo/prisma-db/client'; export const updateConnection = async (id: string, name: string) => { - const connection = await db.connections.update({ + const connection = await db.connection.update({ where: { id }, @@ -13,7 +13,7 @@ export const updateConnection = async (id: string, name: string) => { } export const deleteConnection = async (id: string) => { - const connection = await db.connections.delete({ + const connection = await db.connection.delete({ where: { id } @@ -21,29 +21,163 @@ export const deleteConnection = async (id: string) => { return connection; } -export const deleteYoutubeConnection = async (id: string) => { - const connection = await db.youtube.delete({ +export const deleteNotionDb = async (id: string) => { + const notionDb = await db.notionDb.delete({ where: { id } }); - return connection; + return notionDb; } -export const deleteOpenAIConnection = async (id: string) => { - const connection = await db.openAI.delete({ +export const getConnectionsByUser = async (userId: string) => { + const connections = await db.connection.findMany({ where: { - id + userId } }); - return connection; + return connections; +} + +export const getConnectionsByUserAndType = async (userId: string, type: string) => { + try { + if (type === 'Notion'){ + const connections = await db.connection.findMany({ + where: { + userId, + type + }, + include: { + notionDb: true + } + }); + console.log('Connections', connections) + return connections; + } + else{ + const connections = await db.connection.findMany({ + where: { + userId, + type + } + }); + return connections; + } + } + catch (error) { + return null; + } +} + +export const getConnectionByAccessToken = async (accessToken: string) => { + try{ + const connection = await db.connection.findFirst({ + where: { + accessToken + } + }); + return connection; + } + catch (error){ + return null; + } } -export const deleteNotionConnection = async (id: string) => { - const connection = await db.notion.delete({ +export const getConnectionByAPIKey = async (apiKey: string) => { + const connection = await db.connection.findFirst({ where: { - id + apiKey } }); return connection; +} + +export const createConnection = async ({type, userId, accessToken, workspaceName, workspaceIcon, workspaceId, apiKey, + refreshToken, scopes, results}: any) => { + console.log('Creating connection', type, userId, accessToken, workspaceName, workspaceIcon, workspaceId, apiKey, refreshToken, scopes) + if (type === 'Notion'){ + const result = await db.$transaction(async (db) =>{ + + const notion = await db.connection.create({ + data:{ + userId: userId, + workspaceIcon: workspaceIcon, + workspaceName: workspaceName, + name: workspaceName, + workspaceId: workspaceId, + accessToken: accessToken, + type: type, + } + }) + const notionDb = await db.notionDb.create({ + data:{ + connectionId: notion.id, + } + }) + return { notion, notionDb } + }); + return result; + } + else if (type === 'OpenAI'){ + const openAI = await db.connection.create({ + data:{ + name: 'My OpenAI Key', + userId: userId, + apiKey: apiKey, + type: type, + } + }) + return openAI; + } + else if (type === 'Youtube'){ + const result = await db.$transaction(async (transaction) =>{ + const connection = await transaction.connection.create({ + data:{ + name: 'My Youtube Account', + userId: userId, + accessToken: accessToken, + refreshToken: refreshToken, + scopes: scopes, + type: type, + } + }) + const youtube = await transaction.youtube.createMany({ + data: results.map((result: any) => { + return { + connectionId: connection.id, + videoId: result.videoId, + channelId: result.channelId, + } + }) + + }) + return { connection, youtube } + }); + return result; + } + return null; +} + +export const updateNotionDb = async ({ id, field, value }: { id: string, field: string, value: any }) => { + const notionDb = await db.notionDb.update({ + where: { + connectionId: id + }, + data: { + [field]: value, + } + }); + return notionDb; + }; + +export const updateYoutube = async ({id,watched}:any) =>{ + const youtube = await db.youtube.update({ + where:{ + id: id + }, + data:{ + watched + } + }) + return youtube; } \ No newline at end of file diff --git a/packages/prisma-db/src/notion.ts b/packages/prisma-db/src/notion.ts deleted file mode 100644 index 6a7f440..0000000 --- a/packages/prisma-db/src/notion.ts +++ /dev/null @@ -1,83 +0,0 @@ -import db from './index' - -interface notionProps { - access_token: string, - notion_connected: any, - workspace_id: string, - workspace_icon: string, - workspace_name: string, - userId: string -} - -export const getNotionByAccessToken = async (access_token: string) => { - if(access_token){ - const notion_connected = await db.notion.findFirst({ - where:{ - accessToken: access_token, - }, - include:{ - connections: { - select: { - type: true - } - } - } - }) - return notion_connected; - } -} - -export const createNotion = async ({access_token,notion_connected,workspace_id,workspace_icon,workspace_name,userId}:notionProps) =>{ - const notion = await db.notion.create({ - data:{ - userId: userId, - workspaceIcon: workspace_icon, - workspaceName: workspace_name, - workspaceId: workspace_id, - accessToken: access_token, - connections: { - create: { - userId: userId, - name: workspace_name, - type: "Notion" - } - } - } - }) - return notion -} - - -export const getNotionByUserId = async (userId: string) => { - const connection = await db.notion.findFirst({ - where:{ - userId - }, - include:{ - notionDb: true - } - }) - return connection -} - -export const createNotionDb = async ({notionId}:any) =>{ - await db.notionDb.create({ - data:{ - notionId - } - }) - -} - -export const updateNotionDb = async ({ id, field, value }: { id: string, field: string, value: any }) => { - console.log('updateNotionDb', id, field, value) - const notionDb = await db.notionDb.update({ - where: { - notionId: id - }, - data: { - [field]: value, - } - }); - return notionDb; - }; diff --git a/packages/prisma-db/src/openAi.ts b/packages/prisma-db/src/openAi.ts deleted file mode 100644 index 116a89c..0000000 --- a/packages/prisma-db/src/openAi.ts +++ /dev/null @@ -1,53 +0,0 @@ -import db from './index' - -interface openAIProps { - name: string, - apiKey: string, - openai_connected: any, - userId: string -} - -export const getOpenAIByAPIKey = async (apiKey: string) => { - if(apiKey){ - const connected = await db.openAI.findFirst({ - where:{ - apiKey: apiKey, - }, - include:{ - connections: { - select: { - type: true - } - } - } - }) - return connected; - } -} - -export const createOpenAI = async ({name,apiKey, openai_connected,userId}:openAIProps) =>{ - if (apiKey && !openai_connected){ - await db.openAI.create({ - data:{ - userId: userId, - apiKey: apiKey, - connections: { - create: { - userId: userId, - name: name, - type: "OpenAI" - } - } - } - }) - } - } - -export const getOpenAIByUserId = async (userId: string) => { - const connection = await db.openAI.findFirst({ - where:{ - userId - } - }) - return connection -} \ No newline at end of file diff --git a/packages/prisma-db/src/workflow.ts b/packages/prisma-db/src/workflow.ts index 63ac675..1712884 100644 --- a/packages/prisma-db/src/workflow.ts +++ b/packages/prisma-db/src/workflow.ts @@ -16,7 +16,7 @@ interface NodeProps { export const createWorkflow = async ({name,description,userId}:WorkflowProps) => { - const workflow = await db.workflows.create({ + const workflow = await db.workflow.create({ data:{ name, description, @@ -28,7 +28,7 @@ export const createWorkflow = async ({name,description,userId}:WorkflowProps) => export const getWorkflowsByUserId = async (userId: string) => { if (userId){ - const workflows = await db.workflows.findMany({ + const workflows = await db.workflow.findMany({ where:{ userId }, @@ -41,7 +41,7 @@ export const getWorkflowsByUserId = async (userId: string) => { } export const editWorkflow = async (workflowId: string, name: string, description: string) => { - const workflow = await db.workflows.update({ + const workflow = await db.workflow.update({ where:{ id: workflowId }, @@ -67,7 +67,7 @@ export const startAction = async (id:string,actionId: string) => { export const publishWorkflow = async (workflowId: string, state:boolean) => { - const workflow = await db.workflows.update({ + const workflow = await db.workflow.update({ where:{ id: workflowId }, @@ -80,7 +80,7 @@ export const publishWorkflow = async (workflowId: string, state:boolean) => { } export const updateWorkflowLastRun = async (workflowId: string, lastRun: string) => { - const workflow = await db.workflows.update({ + const workflow = await db.workflow.update({ where:{ id: workflowId }, @@ -93,7 +93,7 @@ export const updateWorkflowLastRun = async (workflowId: string, lastRun: string) export const getNodesByWorkflowId = async (id: string) => { - const nodes = await db.workflows.findFirst({ + const nodes = await db.workflow.findFirst({ where:{ id }, @@ -105,7 +105,7 @@ export const getNodesByWorkflowId = async (id: string) => { } export const getActiveWorkflows = async () => { - const workflows = await db.workflows.findMany({ + const workflows = await db.workflow.findMany({ where:{ publish: true }, @@ -161,7 +161,7 @@ export const editNode = async ({id,name,description,workflowId,type,userId,actio export const deleteWorkflow = async (workflowId: string) => { - const workflow = await db.workflows.delete({ + const workflow = await db.workflow.delete({ where:{ id: workflowId } diff --git a/packages/prisma-db/src/youtube.ts b/packages/prisma-db/src/youtube.ts deleted file mode 100644 index a550870..0000000 --- a/packages/prisma-db/src/youtube.ts +++ /dev/null @@ -1,52 +0,0 @@ -import db from './index' - -export const createYoutube = async ({name,access_token,refresh_token,scopes,userId}:any) =>{ - const youtube = await db.youtube.create({ - data:{ - userId: userId, - accessToken: access_token, - refreshToken: refresh_token, - scopes: scopes, - connections: { - create: { - userId: userId, - name: name, - type: "Youtube" - } - } - } - }) - return youtube -} - -export const getYoutubeByAccessToken = async (access_token: string) => { - if(access_token){ - try { - const connected = await db.youtube.findUnique({ - where:{ - accessToken: access_token, - }, - include:{ - connections: { - select: { - type: true - } - } - } - }) - return connected; - } catch (error) { - return null - } - } - return null -} - -export const getYoutubeByUserId = async (userId: string) => { - const connection = await db.youtube.findFirst({ - where:{ - userId - } - }) - return connection -} \ No newline at end of file