Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 7 additions & 1 deletion apps/http-backend/src/routes/userRoutes/userRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ router.get(
Data: getWorkflow,
});
} catch (error: any) {
console.log("Error Fetching the workflow ", error.meesage);
console.log("Error Fetching the workflow ", error.message);
return res
.status(statusCodes.INTERNAL_SERVER_ERROR)
.json({ message: "Internal server from fetching the workflow" });
Expand Down Expand Up @@ -350,6 +350,12 @@ router.post('/create/trigger', userMiddleware, async(req: AuthRequest, res: Resp
// trigger type pettla db lo ledu aa column
}
})
await prismaClient.workflow.update({
where:{ id: dataSafe.data.WorkflowId },
data:{
isEmpty: false
}
})
Comment on lines +353 to +358

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for workflow update.

The workflow update operation at lines 401-406 lacks error handling. If this update fails after the trigger has been successfully created, it would leave the system in an inconsistent state where:

  • The trigger exists in the database
  • The workflow's isEmpty flag remains true (incorrect)

This could lead to unexpected behavior in the UI or other parts of the system that rely on the isEmpty flag.

🔎 Proposed fix
      })
-      await prismaClient.workflow.update({
-        where:{ id: dataSafe.data.WorkflowId },
-        data:{
-          isEmpty: false
-        }
-      })
+      try {
+        await prismaClient.workflow.update({
+          where:{ id: dataSafe.data.WorkflowId },
+          data:{
+            isEmpty: false
+          }
+        })
+      } catch (updateError) {
+        console.log("Warning: Failed to update workflow isEmpty flag:", updateError);
+        // Note: trigger was created successfully but isEmpty flag may be stale
+      }

      if(createdTrigger){
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await prismaClient.workflow.update({
where:{ id: dataSafe.data.WorkflowId },
data:{
isEmpty: false
}
})
try {
await prismaClient.workflow.update({
where:{ id: dataSafe.data.WorkflowId },
data:{
isEmpty: false
}
})
} catch (updateError) {
console.log("Warning: Failed to update workflow isEmpty flag:", updateError);
// Note: trigger was created successfully but isEmpty flag may be stale
}
🤖 Prompt for AI Agents
In apps/http-backend/src/routes/userRoutes/userRoutes.ts around lines 401-406,
the prismaClient.workflow.update call has no error handling which can leave a
created trigger in DB while the workflow.isEmpty stays true; wrap the update in
error handling or (preferably) perform the trigger creation and workflow update
inside a prisma transaction so both succeed or both rollback; if you cannot
convert to a transaction, catch errors from the update, delete the newly created
trigger to rollback the partial change, log the failure with context, and
rethrow or return an appropriate error response.


if(createdTrigger){
return res.status(statusCodes.CREATED).json({
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/components/nodes/CreateWorkFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ export const CreateWorkFlow = () => {
};

return (
<div style={{ width: "100%", height: "100vh" }}>
<ReactFlow
<div style={{ width: "100%", height: "100%" }}>
<ReactFlow fitViewOptions={{minZoom:0.1}}
nodeTypes={nodeTypes}
nodes={nodes}
edges={edges}
Expand Down
5 changes: 4 additions & 1 deletion apps/web/app/components/nodes/GoogleSheetFormClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { useAppSelector } from '@/app/hooks/redux';
interface GoogleSheetFormClientProps {
type: string;
nodeType: string;

position: number;
initialData?: {
range?: string;
operation?: string;
Expand All @@ -24,7 +26,7 @@ interface GoogleSheetFormClientProps {
};
}

export function GoogleSheetFormClient({ type, nodeType, initialData }: GoogleSheetFormClientProps) {
export function GoogleSheetFormClient({ type, nodeType, position, initialData }: GoogleSheetFormClientProps) {
const [selectedCredential, setSelectedCredential] = useState<string>(initialData?.credentialId || '');
const [documents, setDocuments] = useState<Array<{ id: string; name: string }>>([]);
const [selectedDocument, setSelectedDocument] = useState<string>(initialData?.spreadSheetId || '');
Expand Down Expand Up @@ -190,6 +192,7 @@ export function GoogleSheetFormClient({ type, nodeType, initialData }: GoogleShe
node_Trigger:nodeId,
workflowId,
type:nodeTypeParsed,
position: position,
name: `Google sheet - ${nodeTypeParsed}`,
credentialId: selectedCredential,
spreadsheetId: selectedDocument,
Expand Down
4 changes: 3 additions & 1 deletion apps/web/app/components/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ function SessionSync(){
if(status === 'authenticated'){
dispatch(userAction.setUserStatus('Authenticated'));
const id = (data?.user as any)?.id ?? null;
console.log("user from Session Sync ", id)
// console.log("user from Session Sync ", id)
dispatch(userAction.setUserId(id))
dispatch(userAction.setEmail(data.user?.email ? data.user.email : null))
dispatch(userAction.setUserName(data.user?.name ? data.user.name : null))
}
if(status === 'unauthenticated'){
dispatch(userAction.setUserId(null))
Expand Down
216 changes: 216 additions & 0 deletions apps/web/app/components/ui/app-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSubButton,
SidebarTrigger,
} from '@workspace/ui/components/sidebar'

import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '@workspace/ui/components/collapsible'

import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from '@workspace/ui/components/dropdown-menu'
import { ChevronDown, ChevronUp, Key, LogOut, LucideLayoutDashboard, PlusCircle, User2, WorkflowIcon } from 'lucide-react'
import { useEffect, useState } from 'react'
import { createWorkflow, getAllCredentials, getAllWorkflows, getEmptyWorkflow } from '@/app/workflow/lib/config'
import { useAppDispatch, useAppSelector } from '@/app/hooks/redux'
import { userAction } from '@/store/slices/userSlice'
import { workflowActions } from '@/store/slices/workflowSlice'
import { toast } from 'sonner'
import { signOut } from 'next-auth/react'
import { useRouter } from 'next/navigation'

export function AppSidebar() {

const user = useAppSelector((s)=> s.user)
const flow = useAppSelector(s=>s.workflow) // workflow
const dispatch = useAppDispatch()
const router = useRouter()
const [selectedWorkflow, setSelectedWorkflow] = useState<string | null >(flow.workflow_id)
const [workflow, setWorkflow] = useState<Array<any>>()
const [creds, setCreds] = useState<Array<any>>()
useEffect(()=>{
async function getWorkflows(){
const flows = await getAllWorkflows();
if(flows) setWorkflow(flows)
}

async function getCreds(){
const credentials = await getAllCredentials();
if(credentials) setCreds(credentials)
}

if(!creds) getCreds()
if(!workflow) getWorkflows()
},[selectedWorkflow])

const workflowHandler = (wId: string)=>{
dispatch(workflowActions.setWorkflowId(wId))
}
const credHandler = (cId: string)=> {
// console.log(cId);

}
const logout = async()=>{
toast.info("Logging out...")
await signOut({redirect: false})
dispatch(userAction.clearUser())
dispatch(workflowActions.clearWorkflow())
router.push('/login')
}

const createNewWorkflow = async()=>{
const workflow = await getEmptyWorkflow()

if(workflow){
const {id, isEmpty} = workflow
dispatch(workflowActions.setWorkflowId(id))
dispatch(workflowActions.setWorkflowStatus(isEmpty))
toast.info("You are in empty workflow")
}
else{
const newWorkflow = await createWorkflow()
dispatch(workflowActions.clearWorkflow())
setSelectedWorkflow(null)
dispatch(workflowActions.setWorkflowId(newWorkflow.id))
dispatch(workflowActions.setWorkflowStatus(newWorkflow.isEmpty))
toast.success("Workflow created")
}
}
// console.log(`workflow form ${workflow}`)
return (
<Sidebar collapsible='icon'>
<SidebarHeader className='flex items-center justify-between p-4'>
<span className='text-2xl font-bold'>Logo</span>
<SidebarTrigger />
</SidebarHeader>

<SidebarContent>
<SidebarMenu>

<SidebarMenuItem>
<SidebarMenuButton className='text-xl font-bold text-white h-14' onClick={createNewWorkflow}>
<PlusCircle className='m-2'/> Create Workflow
</SidebarMenuButton>
</SidebarMenuItem>

{/* WORKFLOWS LIST */}
<Collapsible defaultOpen className="group/collapsible">
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
<WorkflowIcon className='m-2'/>
<span>Workflows</span>
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub className="max-h-64 overflow-y-auto cursor-pointer">
{workflow ? (workflow.length === 0 ? (
<SidebarMenuSubItem key={0}>
<SidebarMenuSubButton>
<span>Create Workflow</span>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
) : (workflow.map((i:any) => (
<SidebarMenuSubItem onClick={()=>workflowHandler(i.id)} key={i.id}>
<SidebarMenuSubButton isActive={flow.workflow_id === i.id}>
<span>{i.name}</span>
</SidebarMenuSubButton>
</SidebarMenuSubItem>)
))) : (<span>Loading...</span>
)
}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
{/* CREDENTIALS LIST */}
<Collapsible className="group/collapsible">
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
<Key className='m-2'/>
<span>Credentials</span>
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub className="max-h-32 overflow-y-auto cursor-pointer">
{creds ? (creds.length === 0 ?
(<SidebarMenuSubItem key={0}>
<SidebarMenuSubButton>
<span>No credentials avaliable</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo in user-facing text.

"avaliable" should be "available".

-                                   <span>No credentials avaliable</span>
+                                   <span>No credentials available</span>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<span>No credentials avaliable</span>
<span>No credentials available</span>
🤖 Prompt for AI Agents
In apps/web/app/components/ui/app-sidebar.tsx around line 157, there's a typo in
the user-facing string "No credentials avaliable"; update the text to "No
credentials available" to fix the misspelling, keeping casing and spacing
consistent with surrounding UI copy.

</SidebarMenuSubButton>
</SidebarMenuSubItem>
) : creds.map((i:any) => (
<SidebarMenuSubItem key={i.id}>
<SidebarMenuSubButton>
<span>credential - {i.type}</span>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))) : (
<SidebarMenuSubItem key={0}>
<SidebarMenuSubButton>
<span>Loading...</span>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
)
}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
</SidebarMenu>
</SidebarContent>

<SidebarFooter>
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton className='h-auto'>
<User2 />
<div className='flex flex-col'>
<p className='font-bold'>{user.name}</p>
<p className='font-light'>
{user.email}
</p>
</div>
<ChevronUp className="ml-auto" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
side="top"
className="w-[--radix-popper-anchor-width] flex gap-1 justify-between"
>
<DropdownMenuItem>
<span >Dashboard</span>
<LucideLayoutDashboard className='text-white'/>
</DropdownMenuItem>
<DropdownMenuItem onClick={logout} className='bg-red-600 hover:bg-red-400'>
<span>Sign out</span>
<LogOut className='text-white'/>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
</SidebarFooter>
</Sidebar>
)
}
18 changes: 15 additions & 3 deletions apps/web/app/workflow/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
"use client";

import { SidebarProvider, SidebarTrigger } from "@workspace/ui/components/sidebar";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unused import.

SidebarTrigger is imported but never used in the component.

🔎 Proposed fix
-import { SidebarProvider, SidebarTrigger } from "@workspace/ui/components/sidebar";
+import { SidebarProvider } from "@workspace/ui/components/sidebar";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { SidebarProvider, SidebarTrigger } from "@workspace/ui/components/sidebar";
import { SidebarProvider } from "@workspace/ui/components/sidebar";
🤖 Prompt for AI Agents
In apps/web/app/workflow/page.tsx around line 3, the import statement brings in
SidebarTrigger which is not used; remove SidebarTrigger from the import so only
SidebarProvider is imported (or delete the entire import if SidebarProvider is
also unused), and run a quick search to ensure there are no remaining references
to SidebarTrigger before committing.

import CreateWorkFlow from "../components/nodes/CreateWorkFlow";
import { AppSidebar } from "../components/ui/app-sidebar";
// import WorkFlow from "../components/nodes/WorkFlow";
// import CreateWorkFlow from "../components/workflow";

export default function Workf() {

return (
<div className=" flex -col h-screen w-screen fitems-center justify-center bg-[#0f0f1a]">
{/* <WorkFlow/> */}
<CreateWorkFlow/>
<>
<div className="flex w-screen h-screen bg-white">
<div className=" w-auto h-full text-black">
<SidebarProvider>
<AppSidebar />

{/* {children} */}
</SidebarProvider>
</div>
<div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix CSS class typos.

The className string contains two typos:

  • fitems-center should be items-center
  • flex -col should be flex-col
🔎 Proposed fix
-    <div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">
+    <div className="flex flex-col h-[95vh] w-full items-center justify-center bg-[#0f0f1a]">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className=" flex -col h-[95vh] w-full fitems-center justify-center bg-[#0f0f1a]">
<div className="flex flex-col h-[95vh] w-full items-center justify-center bg-[#0f0f1a]">
🤖 Prompt for AI Agents
In apps/web/app/workflow/page.tsx around line 21 the className has typos:
replace "flex -col" with "flex-col" and "fitems-center" with "items-center" so
the final className uses "flex-col items-center justify-center" (keeping the
other utility classes and spacing intact).

<CreateWorkFlow/>
</div>
</div>
</>
);
}
14 changes: 12 additions & 2 deletions apps/web/store/slices/userSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import {createSlice, PayloadAction } from '@reduxjs/toolkit'
export type AuthStatus = 'Authenticated' | 'Unauthenticated'
export interface UserSlice {
userId: string | null;
status: AuthStatus
status: AuthStatus;
email: string | null;
name: string | null;
}

const initialState: UserSlice = {
userId: null,
status: 'Unauthenticated'
status: 'Unauthenticated',
email: null,
name: null
};

const userSlice = createSlice({
Expand All @@ -21,6 +25,12 @@ const userSlice = createSlice({
setUserStatus(state, action: PayloadAction<AuthStatus>){
state.status = action.payload;
},
setUserName(state, action: PayloadAction<string | null>){
state.name = action.payload
},
setEmail(state, action: PayloadAction<string | null>){
state.email = action.payload
},
clearUser(){
return initialState;
}
Expand Down
1 change: 0 additions & 1 deletion packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const NodeSchema = z.object({

export const WorkflowSchema = z.object({
Name: z.string(),
UserId: z.string(),
Config: z.any(),

});
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
"lint": "eslint . --max-warnings 0"
},
"dependencies": {
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-dropdown-menu": "^2.1.16",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-select": "^2.2.6",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-tooltip": "^1.2.8",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.475.0",
Expand Down
Loading