diff --git a/apps/sim/app/(landing)/careers/page.tsx b/apps/sim/app/(landing)/careers/page.tsx index 2f12b3d9c4..b91aa1ec66 100644 --- a/apps/sim/app/(landing)/careers/page.tsx +++ b/apps/sim/app/(landing)/careers/page.tsx @@ -1,7 +1,7 @@ 'use client' import { useRef, useState } from 'react' -import { Loader2, X } from 'lucide-react' +import { X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' @@ -499,16 +499,11 @@ export default function CareersPage() { className='min-w-[200px] rounded-[10px] border border-[#6F3DFA] bg-gradient-to-b from-[#8357FF] to-[#6F3DFA] text-white shadow-[inset_0_2px_4px_0_#9B77FF] transition-all duration-300 hover:opacity-90 disabled:opacity-50' size='lg' > - {isSubmitting ? ( - <> - - Submitting... - - ) : submitStatus === 'success' ? ( - 'Submitted' - ) : ( - 'Submit Application' - )} + {isSubmitting + ? 'Submitting...' + : submitStatus === 'success' + ? 'Submitted' + : 'Submit Application'} diff --git a/apps/sim/app/_shell/providers/theme-provider.tsx b/apps/sim/app/_shell/providers/theme-provider.tsx index a6bc5444e0..cbb31e4423 100644 --- a/apps/sim/app/_shell/providers/theme-provider.tsx +++ b/apps/sim/app/_shell/providers/theme-provider.tsx @@ -7,7 +7,7 @@ import { ThemeProvider as NextThemesProvider } from 'next-themes' export function ThemeProvider({ children, ...props }: ThemeProviderProps) { const pathname = usePathname() - // Force light mode on public/marketing pages, dark mode everywhere else + // Force light mode on public/marketing pages, allow user preference elsewhere const isLightModePage = pathname === '/' || pathname.startsWith('/login') || @@ -27,10 +27,10 @@ export function ThemeProvider({ children, ...props }: ThemeProviderProps) { {children} diff --git a/apps/sim/app/_shell/zoom-prevention.tsx b/apps/sim/app/_shell/zoom-prevention.tsx deleted file mode 100644 index 66f0ceb74b..0000000000 --- a/apps/sim/app/_shell/zoom-prevention.tsx +++ /dev/null @@ -1,33 +0,0 @@ -'use client' - -import { useEffect } from 'react' - -export function ZoomPrevention() { - useEffect(() => { - const preventZoom = (e: KeyboardEvent | WheelEvent) => { - // Prevent zoom on ctrl/cmd + wheel - if (e instanceof WheelEvent && (e.ctrlKey || e.metaKey)) { - e.preventDefault() - } - - // Prevent zoom on ctrl/cmd + plus/minus/zero - if (e instanceof KeyboardEvent && (e.ctrlKey || e.metaKey)) { - if (e.key === '=' || e.key === '-' || e.key === '0') { - e.preventDefault() - } - } - } - - // Add event listeners - document.addEventListener('wheel', preventZoom, { passive: false }) - document.addEventListener('keydown', preventZoom) - - // Cleanup - return () => { - document.removeEventListener('wheel', preventZoom) - document.removeEventListener('keydown', preventZoom) - } - }, []) - - return null -} diff --git a/apps/sim/app/_styles/globals.css b/apps/sim/app/_styles/globals.css index f67e27e375..3212f37f99 100644 --- a/apps/sim/app/_styles/globals.css +++ b/apps/sim/app/_styles/globals.css @@ -8,7 +8,7 @@ */ :root { --sidebar-width: 232px; - --panel-width: 244px; + --panel-width: 260px; --toolbar-triggers-height: 300px; --editor-connections-height: 200px; --terminal-height: 196px; @@ -26,41 +26,6 @@ height: var(--terminal-height); } -/** - * Workflow component z-index fixes and background colors - */ -.workflow-container .react-flow__edges { - z-index: 0 !important; -} - -.workflow-container .react-flow__node { - z-index: 21 !important; -} - -.workflow-container .react-flow__handle { - z-index: 30 !important; -} - -.workflow-container .react-flow__edge [data-testid="workflow-edge"] { - z-index: 0 !important; -} - -.workflow-container .react-flow__edge-labels { - z-index: 60 !important; -} - -.workflow-container, -.workflow-container .react-flow__pane, -.workflow-container .react-flow__renderer { - background-color: var(--bg) !important; -} - -.dark .workflow-container, -.dark .workflow-container .react-flow__pane, -.dark .workflow-container .react-flow__renderer { - background-color: var(--bg) !important; -} - /** * Landing loop animation styles (keyframes defined in tailwind.config.ts) */ @@ -75,101 +40,93 @@ } /** - * Dark color tokens - single source of truth for all colors (dark-only) + * Color tokens - single source of truth for all colors + * Light mode: Warm theme + * Dark mode: Dark neutral theme */ @layer base { :root, .light { - /* Neutrals (surfaces) - shadcn stone palette */ - --bg: #ffffff; /* pure white for landing/auth pages */ - --surface-1: #fafaf9; /* stone-50 */ - --surface-2: #ffffff; /* white */ - --surface-3: #f5f5f4; /* stone-100 */ - --surface-4: #f5f5f4; /* stone-100 */ - --surface-5: #eeedec; /* stone-150 */ - --surface-6: #f5f5f4; /* stone-100 */ - --surface-9: #f5f5f4; /* stone-100 */ - --surface-11: #e7e5e4; /* stone-200 */ - --surface-12: #d6d3d1; /* stone-300 */ - --surface-13: #a8a29e; /* stone-400 */ - --surface-14: #78716c; /* stone-500 */ - --surface-15: #57534e; /* stone-600 */ - --surface-elevated: #ffffff; /* white */ - --bg-strong: #e7e5e4; /* stone-200 */ - - /* Text - shadcn stone palette for proper contrast */ - --text-primary: #1c1917; /* stone-900 */ - --text-secondary: #292524; /* stone-800 */ - --text-tertiary: #57534e; /* stone-600 */ - --text-muted: #78716c; /* stone-500 */ - --text-subtle: #a8a29e; /* stone-400 */ - --text-inverse: #fafaf9; /* stone-50 */ + --bg: #fcfcf9; /* main canvas - warm off-white */ + --surface-1: #f9faf7; /* sidebar, panels - very close to bg */ + --surface-2: #fcfcf9; /* cards, modals - matches bg */ + --surface-3: #f6f7f4; /* popovers, elevated */ + --surface-4: #f2f3f0; /* buttons base */ + --border: #e5e6e1; /* primary border */ + --surface-5: #ecede8; /* inputs, hover states */ + --border-1: #d7dcda; /* stronger border - sage gray */ + --surface-6: #d7dcda; /* scroll thumbs, active states */ + + /* Text - warm neutrals */ + --text-primary: #1a1a1a; + --text-secondary: #2d2d2d; + --text-tertiary: #525252; + --text-muted: #737373; + --text-subtle: #8c8c8c; + --text-inverse: #f0fff6; --text-error: #dc2626; - /* Borders / dividers - shadcn stone palette */ - --border: #d6d3d1; /* stone-300 */ - --border-strong: #d6d3d1; /* stone-300 */ - --divider: #e7e5e4; /* stone-200 */ - --border-muted: #e7e5e4; /* stone-200 */ - --border-success: #d6d3d1; /* stone-300 */ + /* Borders / dividers */ + --divider: #e8e9e4; + --border-muted: #dfe0db; + --border-success: #d7dcda; /* Brand & state */ --brand-400: #8e4cfb; - --brand-500: #6f3dfa; --brand-secondary: #33b4ff; --brand-tertiary: #22c55e; - --brand-tertiary-2: #33c481; + --brand-tertiary-2: #32bd7e; --warning: #ea580c; /* Utility */ --white: #ffffff; - /* Font weights - lighter for light mode (-20 from dark) */ + /* Font weights - lighter for light mode */ --font-weight-base: 430; --font-weight-medium: 450; --font-weight-semibold: 500; - /* RGB for opacity usage - stone palette */ - --surface-4-rgb: 245 245 244; /* stone-100 */ - --surface-5-rgb: 238 237 236; /* stone-150 */ - --surface-7-rgb: 245 245 244; /* stone-100 */ - --surface-9-rgb: 245 245 244; /* stone-100 */ - --divider-rgb: 231 229 228; /* stone-200 */ + /* RGB for opacity usage */ + --surface-4-rgb: 242 243 240; + --surface-5-rgb: 236 237 232; + --surface-7-rgb: 246 247 244; + --surface-9-rgb: 232 233 228; + --divider-rgb: 232 233 228; --white-rgb: 255 255 255; --black-rgb: 0 0 0; - /* Extended palette - mapped to shadcn stone palette */ - --c-0D0D0D: #0c0a09; /* stone-950 */ - --c-1A1A1A: #1c1917; /* stone-900 */ - --c-1F1F1F: #1c1917; /* stone-900 */ - --c-2A2A2A: #292524; /* stone-800 */ - --c-383838: #44403c; /* stone-700 */ - --c-414141: #57534e; /* stone-600 */ + /* Extended palette */ + --c-0D0D0D: #0d0d0d; + --c-1A1A1A: #1a1a1a; + --c-1F1F1F: #1f1f1f; + --c-2A2A2A: #2a2a2a; + --c-383838: #383838; + --c-414141: #414141; --c-442929: #442929; --c-491515: #491515; - --c-575757: #78716c; /* stone-500 */ - --c-686868: #78716c; /* stone-500 */ - --c-707070: #78716c; /* stone-500 */ - --c-727272: #78716c; /* stone-500 */ - --c-737373: #78716c; /* stone-500 */ - --c-808080: #a8a29e; /* stone-400 */ - --c-858585: #a8a29e; /* stone-400 */ - --c-868686: #a8a29e; /* stone-400 */ - --c-8D8D8D: #a8a29e; /* stone-400 */ - --c-939393: #a8a29e; /* stone-400 */ - --c-A8A8A8: #a8a29e; /* stone-400 */ - --c-B8B8B8: #d6d3d1; /* stone-300 */ - --c-C0C0C0: #d6d3d1; /* stone-300 */ - --c-CDCDCD: #d6d3d1; /* stone-300 */ - --c-D0D0D0: #d6d3d1; /* stone-300 */ - --c-D2D2D2: #d6d3d1; /* stone-300 */ - --c-E0E0E0: #e7e5e4; /* stone-200 */ - --c-E5E5E5: #e7e5e4; /* stone-200 */ - --c-E8E8E8: #e7e5e4; /* stone-200 */ - --c-EEEEEE: #f5f5f4; /* stone-100 */ - --c-F0F0F0: #f5f5f4; /* stone-100 */ - --c-F4F4F4: #fafaf9; /* stone-50 */ - --c-F5F5F5: #fafaf9; /* stone-50 */ + --c-575757: #575757; + --c-686868: #686868; + --c-707070: #707070; + --c-727272: #727272; + --c-737373: #737373; + --c-808080: #808080; + --c-858585: #858585; + --c-868686: #868686; + --c-8D8D8D: #8d8d8d; + --c-939393: #939393; + --c-A8A8A8: #a8a8a8; + --c-B8B8B8: #b8b8b8; + --c-C0C0C0: #c0c0c0; + --c-CDCDCD: #cdcdcd; + --c-D0D0D0: #d0d0d0; + --c-D2D2D2: #d2d2d2; + --c-E0E0E0: #e0e0e0; + --c-E5E5E5: #e5e5e5; + --c-E8E8E8: #e8e8e8; + --c-EEEEEE: #eeeeee; + --c-F0F0F0: #f0f0f0; + --c-F4F4F4: #f4f4f4; + --c-F5F5F5: #f5f5f5; /* Blues and cyans */ --c-00B0B0: #00b0b0; @@ -203,30 +160,24 @@ /* Terminal status badges */ --terminal-status-error-bg: #feeeee; --terminal-status-error-border: #f87171; - --terminal-status-info-bg: #f5f5f4; /* stone-100 */ - --terminal-status-info-border: #a8a29e; /* stone-400 */ - --terminal-status-info-color: #57534e; /* stone-600 */ + --terminal-status-info-bg: #f5f5f4; + --terminal-status-info-border: #a8a29e; + --terminal-status-info-color: #57534e; --terminal-status-warning-bg: #fef9e7; --terminal-status-warning-border: #f5c842; --terminal-status-warning-color: #a16207; } .dark { - /* Neutrals (surfaces) */ + /* Surface */ --bg: #1b1b1b; --surface-1: #1e1e1e; --surface-2: #232323; --surface-3: #242424; - --surface-4: #252525; - --surface-5: #272727; - --surface-6: #282828; - --surface-9: #363636; - --surface-11: #3d3d3d; - --surface-12: #434343; - --surface-13: #454545; - --surface-14: #4a4a4a; - --surface-15: #5a5a5a; - --surface-elevated: #202020; - --bg-strong: #0c0c0c; + --surface-4: #292929; + --border: #2c2c2c; + --surface-5: #363636; + --border-1: #3d3d3d; + --surface-6: #454545; /* Text */ --text-primary: #e6e6e6; @@ -237,9 +188,7 @@ --text-inverse: #1b1b1b; --text-error: #ef4444; - /* Borders / dividers */ - --border: #2c2c2c; - --border-strong: #303030; + /* --border-strong: #303030; */ --divider: #393939; --border-muted: #424242; --border-success: #575757; @@ -248,7 +197,7 @@ --brand-400: #8e4cfb; --brand-secondary: #33b4ff; --brand-tertiary: #22c55e; - --brand-tertiary-2: #33c481; + --brand-tertiary-2: #32bd7e; --warning: #ff6600; /* Utility */ @@ -260,7 +209,7 @@ --font-weight-semibold: 550; /* RGB for opacity usage */ - --surface-4-rgb: 37 37 37; + --surface-4-rgb: 41 41 41; --surface-5-rgb: 39 39 39; --surface-7-rgb: 44 44 44; --surface-9-rgb: 54 54 54; @@ -395,34 +344,34 @@ } ::-webkit-scrollbar-thumb { - background-color: var(--surface-12); + background-color: var(--surface-6); border-radius: var(--radius); } ::-webkit-scrollbar-thumb:hover { - background-color: var(--surface-13); + background-color: var(--surface-6); } /* Dark Mode Global Scrollbar */ .dark ::-webkit-scrollbar-track { - background: var(--surface-5); + background: var(--surface-4); } .dark ::-webkit-scrollbar-thumb { - background-color: var(--surface-12); + background-color: var(--surface-6); } .dark ::-webkit-scrollbar-thumb:hover { - background-color: var(--surface-13); + background-color: var(--surface-6); } * { scrollbar-width: thin; - scrollbar-color: var(--surface-12) var(--surface-1); + scrollbar-color: var(--surface-6) var(--surface-1); } .dark * { - scrollbar-color: var(--surface-12) var(--surface-5); + scrollbar-color: var(--surface-6) var(--surface-4); } .copilot-scrollable { @@ -438,8 +387,8 @@ } .panel-tab-active { - background-color: var(--white); - color: var(--text-inverse); + background-color: var(--surface-5); + color: var(--text-primary); border-color: var(--border-muted); } @@ -450,7 +399,7 @@ } .panel-tab-inactive:hover { - background-color: var(--surface-9); + background-color: var(--surface-5); color: var(--text-primary); } @@ -642,7 +591,7 @@ input[type="search"]::-ms-clear { } html[data-panel-active-tab="copilot"] .panel-container [data-tab-button="copilot"] { - background-color: var(--surface-11) !important; + background-color: var(--border-1) !important; color: var(--text-primary) !important; } html[data-panel-active-tab="copilot"] .panel-container [data-tab-button="toolbar"], @@ -652,7 +601,7 @@ input[type="search"]::-ms-clear { } html[data-panel-active-tab="toolbar"] .panel-container [data-tab-button="toolbar"] { - background-color: var(--surface-11) !important; + background-color: var(--border-1) !important; color: var(--text-primary) !important; } html[data-panel-active-tab="toolbar"] .panel-container [data-tab-button="copilot"], @@ -662,7 +611,7 @@ input[type="search"]::-ms-clear { } html[data-panel-active-tab="editor"] .panel-container [data-tab-button="editor"] { - background-color: var(--surface-11) !important; + background-color: var(--border-1) !important; color: var(--text-primary) !important; } html[data-panel-active-tab="editor"] .panel-container [data-tab-button="copilot"], diff --git a/apps/sim/app/api/billing/route.ts b/apps/sim/app/api/billing/route.ts index 33e1559afa..5c8bb42801 100644 --- a/apps/sim/app/api/billing/route.ts +++ b/apps/sim/app/api/billing/route.ts @@ -93,6 +93,7 @@ export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url) const context = searchParams.get('context') || 'user' const contextId = searchParams.get('id') + const includeOrg = searchParams.get('includeOrg') === 'true' // Validate context parameter if (!['user', 'organization'].includes(context)) { @@ -115,14 +116,38 @@ export async function GET(request: NextRequest) { if (context === 'user') { // Get user billing (may include organization if they're part of one) billingData = await getSimplifiedBillingSummary(session.user.id, contextId || undefined) + // Attach effective billing blocked status (includes org owner check) const billingStatus = await getEffectiveBillingStatus(session.user.id) + billingData = { ...billingData, billingBlocked: billingStatus.billingBlocked, billingBlockedReason: billingStatus.billingBlockedReason, blockedByOrgOwner: billingStatus.blockedByOrgOwner, } + + // Optionally include organization membership and role + if (includeOrg) { + const userMembership = await db + .select({ + organizationId: member.organizationId, + role: member.role, + }) + .from(member) + .where(eq(member.userId, session.user.id)) + .limit(1) + + if (userMembership.length > 0) { + billingData = { + ...billingData, + organization: { + id: userMembership[0].organizationId, + role: userMembership[0].role as 'owner' | 'admin' | 'member', + }, + } + } + } } else { // Get user role in organization for permission checks first const memberRecord = await db diff --git a/apps/sim/app/chat/components/auth/email/email-auth.tsx b/apps/sim/app/chat/components/auth/email/email-auth.tsx index 63281b454e..1711a9ce4f 100644 --- a/apps/sim/app/chat/components/auth/email/email-auth.tsx +++ b/apps/sim/app/chat/components/auth/email/email-auth.tsx @@ -1,7 +1,6 @@ 'use client' import { type KeyboardEvent, useEffect, useState } from 'react' -import { Loader2 } from 'lucide-react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { InputOTP, InputOTPGroup, InputOTPSlot } from '@/components/ui/input-otp' @@ -299,14 +298,7 @@ export default function EmailAuth({ className={`${buttonClass} flex w-full items-center justify-center gap-2 rounded-[10px] border font-medium text-[15px] text-white transition-all duration-200`} disabled={isSendingOtp} > - {isSendingOtp ? ( - <> - - Sending Code... - - ) : ( - 'Continue' - )} + {isSendingOtp ? 'Sending Code...' : 'Continue'} ) : ( diff --git a/apps/sim/app/invite/components/status-card.tsx b/apps/sim/app/invite/components/status-card.tsx index 65a2a30dc3..043300b080 100644 --- a/apps/sim/app/invite/components/status-card.tsx +++ b/apps/sim/app/invite/components/status-card.tsx @@ -162,14 +162,7 @@ export function InviteStatusCard({ onClick={action.onClick} disabled={action.disabled || action.loading} > - {action.loading ? ( - <> - - {action.label}... - - ) : ( - action.label - )} + {action.loading ? `${action.label}...` : action.label} ))} diff --git a/apps/sim/app/layout.tsx b/apps/sim/app/layout.tsx index bb40e8156f..da80a06d21 100644 --- a/apps/sim/app/layout.tsx +++ b/apps/sim/app/layout.tsx @@ -11,7 +11,6 @@ import { HydrationErrorHandler } from '@/app/_shell/hydration-error-handler' import { QueryProvider } from '@/app/_shell/providers/query-provider' import { SessionProvider } from '@/app/_shell/providers/session-provider' import { ThemeProvider } from '@/app/_shell/providers/theme-provider' -import { ZoomPrevention } from '@/app/_shell/zoom-prevention' import { season } from '@/app/_styles/fonts/season/season' export const viewport: Viewport = { @@ -85,7 +84,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) var panelWidth = panelState && panelState.panelWidth; var maxPanelWidth = window.innerWidth * 0.4; - if (panelWidth >= 244 && panelWidth <= maxPanelWidth) { + if (panelWidth >= 260 && panelWidth <= maxPanelWidth) { document.documentElement.style.setProperty('--panel-width', panelWidth + 'px'); } else if (panelWidth > maxPanelWidth) { document.documentElement.style.setProperty('--panel-width', maxPanelWidth + 'px'); @@ -190,10 +189,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) - - - {children} - + {children} diff --git a/apps/sim/app/playground/page.tsx b/apps/sim/app/playground/page.tsx index 7a3804211a..8e3fb2fa22 100644 --- a/apps/sim/app/playground/page.tsx +++ b/apps/sim/app/playground/page.tsx @@ -317,10 +317,10 @@ export default function PlaygroundPage() { - - + + - + Item 1 @@ -550,7 +550,7 @@ export default function PlaygroundPage() { ].map(({ Icon, name }) => ( -
+
diff --git a/apps/sim/app/templates/[id]/template.tsx b/apps/sim/app/templates/[id]/template.tsx index 9b8c32a00a..5eead061a8 100644 --- a/apps/sim/app/templates/[id]/template.tsx +++ b/apps/sim/app/templates/[id]/template.tsx @@ -732,7 +732,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template <> {!currentUserId ? ( ) : isWorkspaceContext ? (
) : ( -
+
)} @@ -1001,7 +1001,7 @@ export default function TemplateDetails({ isWorkspaceContext = false }: Template />
) : ( -
+
)} diff --git a/apps/sim/app/templates/components/template-card.tsx b/apps/sim/app/templates/components/template-card.tsx index 35d23e5766..195cb20ecc 100644 --- a/apps/sim/app/templates/components/template-card.tsx +++ b/apps/sim/app/templates/components/template-card.tsx @@ -27,15 +27,15 @@ interface TemplateCardProps { export function TemplateCardSkeleton({ className }: { className?: string }) { return ( -
-
+
+
-
+
{Array.from({ length: 3 }).map((_, index) => (
))}
@@ -43,14 +43,14 @@ export function TemplateCardSkeleton({ className }: { className?: string }) {
-
-
+
+
-
-
-
-
+
+
+
+
@@ -195,7 +195,7 @@ function TemplateCardInner({ return (
) : ( -
+
)}
-

{title}

+

+ {title} +

{blockTypes.length > 4 ? ( @@ -241,10 +243,12 @@ function TemplateCardInner({ ) })}
- +{blockTypes.length - 3} + + +{blockTypes.length - 3} +
) : ( @@ -276,24 +280,26 @@ function TemplateCardInner({ {author}
) : ( -
- +
+
)}
- {author} + + {author} + {isVerified && }
-
+
{usageCount} diff --git a/apps/sim/app/templates/templates.tsx b/apps/sim/app/templates/templates.tsx index 46e5c447ec..945bccc8f9 100644 --- a/apps/sim/app/templates/templates.tsx +++ b/apps/sim/app/templates/templates.tsx @@ -149,7 +149,7 @@ export default function Templates({
-
+
- {processing ? ( - - ) : data?.currentPreferences.unsubscribeAll ? ( + {data?.currentPreferences.unsubscribeAll ? ( ) : null} - {data?.currentPreferences.unsubscribeAll - ? 'Unsubscribed from All Emails' - : 'Unsubscribe from All Marketing Emails'} + {processing + ? 'Unsubscribing...' + : data?.currentPreferences.unsubscribeAll + ? 'Unsubscribed from All Emails' + : 'Unsubscribe from All Marketing Emails'}
diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx index c1952eed35..14f47d5597 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/create-chunk-modal/create-chunk-modal.tsx @@ -1,7 +1,7 @@ 'use client' import { useRef, useState } from 'react' -import { AlertCircle, Loader2 } from 'lucide-react' +import { AlertCircle } from 'lucide-react' import { Button, Label, @@ -157,19 +157,12 @@ export function CreateChunkModal({ Cancel @@ -181,7 +174,7 @@ export function CreateChunkModal({ Discard Changes -

+

You have unsaved changes. Are you sure you want to close without saving?

@@ -193,12 +186,7 @@ export function CreateChunkModal({ > Keep Editing - diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx index 96115db673..7fc8da5623 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/delete-chunk-modal/delete-chunk-modal.tsx @@ -69,7 +69,7 @@ export function DeleteChunkModal({ Delete Chunk -

+

Are you sure you want to delete this chunk?{' '} This action cannot be undone.

@@ -78,12 +78,7 @@ export function DeleteChunkModal({ - diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx index 1f40cd20dd..b8335bbb9d 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/document-tags-modal/document-tags-modal.tsx @@ -1,7 +1,6 @@ 'use client' import { useCallback, useEffect, useState } from 'react' -import { Loader2 } from 'lucide-react' import { Button, Combobox, @@ -575,7 +574,7 @@ export function DocumentTagsModal({ Cancel
diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx index 368a5df579..4dbff71ed1 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/components/edit-chunk-modal/edit-chunk-modal.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import * as DialogPrimitive from '@radix-ui/react-dialog' -import { AlertCircle, ChevronDown, ChevronUp, Loader2, X } from 'lucide-react' +import { AlertCircle, ChevronDown, ChevronUp, X } from 'lucide-react' import { Button, Label, @@ -275,19 +275,12 @@ export function EditChunkModal({ {userPermissions.canEdit && ( )} @@ -300,7 +293,7 @@ export function EditChunkModal({ Unsaved Changes -

+

You have unsaved changes to this chunk content. {pendingNavigation ? ' Do you want to discard your changes and navigate to the next chunk?' @@ -318,12 +311,7 @@ export function EditChunkModal({ > Keep Editing - diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx index 494139db99..1f74ce9db1 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/[documentId]/document.tsx @@ -234,7 +234,7 @@ function DocumentLoading({

-
+
-
@@ -851,7 +851,7 @@ export function Document({
-
+
setIsCreateChunkModalOpen(true)} disabled={documentData?.processingStatus === 'failed' || !userPermissions.canEdit} - variant='primary' + variant='tertiary' className='h-[32px] rounded-[6px]' > Create Chunk @@ -1092,18 +1092,13 @@ export function Document({ )} {documentData?.processingStatus === 'completed' && totalPages > 1 && ( -
+
- -
+
{Array.from({ length: Math.min(totalPages, 5) }, (_, i) => { let page: number if (totalPages <= 5) { @@ -1133,13 +1128,8 @@ export function Document({ })}
-
@@ -1229,7 +1219,7 @@ export function Document({ Delete Document -

+

Are you sure you want to delete "{effectiveDocumentName}"? This will permanently delete the document and all {documentData?.chunkCount ?? 0} chunk {documentData?.chunkCount === 1 ? '' : 's'} within it.{' '} @@ -1245,10 +1235,9 @@ export function Document({ Cancel diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx index 2c4ce5a3a8..c68b11c99a 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/base.tsx @@ -185,7 +185,7 @@ function KnowledgeBaseLoading({ knowledgeBaseName }: KnowledgeBaseLoadingProps)

-
+
-
@@ -973,7 +973,7 @@ export function KnowledgeBase({
-
+
Add Documents @@ -1253,18 +1253,17 @@ export function KnowledgeBase({ )} {totalPages > 1 && ( -
+
-
+
{Array.from({ length: Math.min(totalPages, 5) }, (_, i) => { let page: number if (totalPages <= 5) { @@ -1298,9 +1297,8 @@ export function KnowledgeBase({ variant='ghost' onClick={nextPage} disabled={!hasNextPage || isLoadingDocuments} - className='h-8 w-8 p-0' > - +
@@ -1315,7 +1313,7 @@ export function KnowledgeBase({ Delete Knowledge Base -

+

Are you sure you want to delete "{knowledgeBaseName}"? This will permanently delete the knowledge base and all {pagination.total} document {pagination.total === 1 ? '' : 's'} within it.{' '} @@ -1330,12 +1328,7 @@ export function KnowledgeBase({ > Cancel - @@ -1346,7 +1339,7 @@ export function KnowledgeBase({ Delete Document -

+

Are you sure you want to delete " {documents.find((doc) => doc.id === documentToDelete)?.filename ?? 'this document'}"?{' '} This action cannot be undone. @@ -1362,11 +1355,7 @@ export function KnowledgeBase({ > Cancel - @@ -1377,7 +1366,7 @@ export function KnowledgeBase({ Delete Documents -

+

Are you sure you want to delete {selectedDocuments.size} document {selectedDocuments.size === 1 ? '' : 's'}?{' '} This action cannot be undone. @@ -1387,12 +1376,7 @@ export function KnowledgeBase({ - - - Enable {disabledCount > 1 ? `${disabledCount} items` : 'item'} - + Enable )} @@ -72,14 +70,12 @@ export function ActionBar({ variant='ghost' onClick={onDisable} disabled={isLoading} - className='hover:!text-[var(--text-inverse)] h-[28px] w-[28px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)]' + className='hover:!text-[var(--text-inverse)] h-[28px] w-[28px] rounded-[8px] bg-[var(--surface-5)] p-0 text-[var(--text-secondary)] hover:bg-[var(--brand-secondary)]' > - - Disable {enabledCount > 1 ? `${enabledCount} items` : 'item'} - + Disable )} @@ -90,12 +86,12 @@ export function ActionBar({ variant='ghost' onClick={onDelete} disabled={isLoading} - className='hover:!text-[var(--text-inverse)] h-[28px] w-[28px] rounded-[8px] bg-[var(--surface-9)] p-0 text-[#868686] hover:bg-[var(--brand-secondary)]' + className='hover:!text-[var(--text-inverse)] h-[28px] w-[28px] rounded-[8px] bg-[var(--surface-5)] p-0 text-[var(--text-secondary)] hover:bg-[var(--brand-secondary)]' > - Delete items + Delete )}

diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-documents-modal/add-documents-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-documents-modal/add-documents-modal.tsx index e88c79fe9e..3c59565f9a 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-documents-modal/add-documents-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/[id]/components/add-documents-modal/add-documents-modal.tsx @@ -352,7 +352,7 @@ export function AddDocumentsModal({ Cancel
@@ -468,7 +460,7 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM Delete Tag
-

+

Are you sure you want to delete the "{selectedTag?.displayName}" tag? This will remove this tag from {selectedTagUsage?.documentCount || 0} document {selectedTagUsage?.documentCount !== 1 ? 's' : ''}.{' '} @@ -494,12 +486,7 @@ export function BaseTagsModal({ open, onOpenChange, knowledgeBaseId }: BaseTagsM > Cancel - diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx index 50ba8d61d7..c643347a55 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/base-card/base-card.tsx @@ -67,26 +67,26 @@ function formatAbsoluteDate(dateString: string): string { */ export function BaseCardSkeleton() { return ( -

+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
@@ -122,9 +122,9 @@ export function BaseCard({ id, title, docCount, description, updatedAt }: BaseCa return ( -
+
-

+

{title}

{shortId && {shortId}} @@ -139,7 +139,7 @@ export function BaseCard({ id, title, docCount, description, updatedAt }: BaseCa {updatedAt && ( - + last updated: {formatRelativeTime(updatedAt)} diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/components/constants.ts b/apps/sim/app/workspace/[workspaceId]/knowledge/components/constants.ts index 07d6943b84..aa5b7618fe 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/components/constants.ts +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/constants.ts @@ -1,8 +1,8 @@ export const filterButtonClass = - 'w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[var(--white)] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-elevated)]' + 'w-full justify-between rounded-[10px] border-[#E5E5E5] bg-[var(--white)] font-normal text-sm dark:border-[#414141] dark:bg-[var(--surface-2)]' export const dropdownContentClass = - 'w-[220px] rounded-lg border-[#E5E5E5] bg-[var(--white)] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-elevated)]' + 'w-[220px] rounded-lg border-[#E5E5E5] bg-[var(--white)] p-0 shadow-xs dark:border-[#414141] dark:bg-[var(--surface-2)]' export const commandListClass = 'overflow-y-auto overflow-x-hidden' diff --git a/apps/sim/app/workspace/[workspaceId]/knowledge/components/create-base-modal/create-base-modal.tsx b/apps/sim/app/workspace/[workspaceId]/knowledge/components/create-base-modal/create-base-modal.tsx index 928fd52954..4434093045 100644 --- a/apps/sim/app/workspace/[workspaceId]/knowledge/components/create-base-modal/create-base-modal.tsx +++ b/apps/sim/app/workspace/[workspaceId]/knowledge/components/create-base-modal/create-base-modal.tsx @@ -388,7 +388,7 @@ export function CreateBaseModal({ />
-
+
@@ -562,7 +562,7 @@ export function CreateBaseModal({ Cancel
-
+
setIsCreateModalOpen(true)} disabled={userPermissions.canEdit !== true} - variant='primary' + variant='tertiary' className='h-[32px] rounded-[6px]' > Create diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx index d4e4fab887..24a80a8f80 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/line-chart/line-chart.tsx @@ -671,7 +671,7 @@ function LineChartComponent({ const top = Math.min(Math.max(anchorY - 26, padding.top), height - padding.bottom - 18) return (
{currentHoverDate && ( diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/status-bar/status-bar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/status-bar/status-bar.tsx index 38510f497b..b701c78e8a 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/status-bar/status-bar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/components/status-bar/status-bar.tsx @@ -97,7 +97,7 @@ export function StatusBar({ {hoverIndex !== null && segments[hoverIndex] && (
onToggleWorkflow(workflow.workflowId)} > diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/dashboard.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/dashboard.tsx index ebbb3a88db..5aaafb4652 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/dashboard.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/dashboard/dashboard.tsx @@ -36,7 +36,7 @@ const SKELETON_BAR_HEIGHTS = [ function GraphCardSkeleton({ title }: { title: string }) { return ( -
+
{title} @@ -570,7 +570,7 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
-
+
Runs @@ -597,7 +597,7 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
-
+
Errors @@ -624,7 +624,7 @@ export default function Dashboard({ logs, isLoading, error }: DashboardProps) {
-
+
Latency diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/index.ts b/apps/sim/app/workspace/[workspaceId]/logs/components/index.ts index 3458318613..b59a2eac56 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/index.ts @@ -4,9 +4,4 @@ export { FileCards } from './log-details/components/file-download' export { FrozenCanvas } from './log-details/components/frozen-canvas' export { TraceSpans } from './log-details/components/trace-spans' export { LogsList } from './logs-list' -export { - AutocompleteSearch, - Controls, - LogsToolbar, - NotificationSettings, -} from './logs-toolbar' +export { AutocompleteSearch, LogsToolbar, NotificationSettings } from './logs-toolbar' diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-spans/trace-spans.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-spans/trace-spans.tsx index 39020ea1cd..f422241cbe 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-spans/trace-spans.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-spans/trace-spans.tsx @@ -277,10 +277,10 @@ function ExpandableRowHeader({ aria-expanded={hasChildren ? isExpanded : undefined} aria-label={hasChildren ? (isExpanded ? 'Collapse' : 'Expand') : undefined} > -
+
{hasChildren && ( )} @@ -418,14 +418,14 @@ function InputOutputSection({ 'font-medium text-[12px] transition-colors', isError ? 'text-[var(--text-error)]' - : 'text-[var(--text-tertiary)] group-hover:text-[var(--text-secondary)]' + : 'text-[var(--text-tertiary)] group-hover:text-[var(--text-primary)]' )} > {label} +
{span.children!.map((child, childIndex) => ( 0 && isCardExpanded && ( -
+
{inlineChildren.map((childSpan, index) => ( +
{[...toolCallSpans, ...inlineChildren].map((childSpan, index) => { const childId = childSpan.id || `${spanId}-inline-${index}` const childIsError = childSpan.status === 'error' @@ -731,7 +731,7 @@ const TraceSpanItem = memo(function TraceSpanItem({ {/* Nested children */} {showChildrenInProgressBar && hasNestedChildren && isNestedExpanded && ( -
+
{childSpan.children!.map((nestedChild, nestedIndex) => ( - - - - handleTimeRangeSelect('All time')} - > - All time - - -
- - {specificTimeRanges.map((range) => ( - handleTimeRangeSelect(range)} - > - {range} - - ))} - - - - ) -} - -interface ControlsProps { - searchQuery?: string - setSearchQuery?: (v: string) => void - isRefetching: boolean - resetToNow: () => void - live: boolean - setLive: (v: (prev: boolean) => boolean) => void - viewMode: string - setViewMode: (mode: 'logs' | 'dashboard') => void - searchComponent?: ReactNode - showExport?: boolean - onExport?: () => void - canConfigureNotifications?: boolean - onConfigureNotifications?: () => void -} - -export function Controls({ - searchQuery, - setSearchQuery, - isRefetching, - resetToNow, - live, - setLive, - viewMode, - setViewMode, - searchComponent, - onExport, - canConfigureNotifications, - onConfigureNotifications, -}: ControlsProps) { - return ( -
- {searchComponent ? ( - searchComponent - ) : ( -
- - setSearchQuery?.(e.target.value)} - className='h-9 w-full border-[#E5E5E5] bg-[var(--white)] pr-10 pl-9 dark:border-[#414141] dark:bg-[var(--surface-elevated)]' - /> - {searchQuery && ( - - )} -
- )} - -
- {viewMode !== 'dashboard' && ( - - - - - - - - - Export as CSV - - - - Configure Notifications - - - - - )} - - - - - - {isRefetching ? 'Refreshing...' : 'Refresh'} - - -
- -
- -
- - -
-
- -
- -
-
- ) -} - -export default Controls diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/controls/index.ts b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/controls/index.ts deleted file mode 100644 index 0c5bf9faf6..0000000000 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/controls/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Controls, default } from './controls' diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx index 81bedb0393..a5c09c005e 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx @@ -39,9 +39,6 @@ import { WorkflowSelector } from './components/workflow-selector' const logger = createLogger('NotificationSettings') -const PRIMARY_BUTTON_STYLES = - '!bg-[var(--brand-tertiary-2)] !text-[var(--text-inverse)] hover:!bg-[var(--brand-tertiary-2)]/90' - type NotificationType = 'webhook' | 'email' | 'slack' type LogLevel = 'info' | 'error' type AlertRule = @@ -618,10 +615,9 @@ export function NotificationSettings({
@@ -1379,7 +1372,7 @@ function EmailTag({ email, onRemove, isInvalid }: EmailTagProps) { 'flex w-auto items-center gap-[4px] rounded-[4px] border px-[6px] py-[2px] text-[12px]', isInvalid ? 'border-[var(--text-error)] bg-[color-mix(in_srgb,var(--text-error)_10%,transparent)] text-[var(--text-error)] dark:bg-[color-mix(in_srgb,var(--text-error)_16%,transparent)]' - : 'border-[var(--surface-11)] bg-[var(--surface-5)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]' + : 'border-[var(--border-1)] bg-[var(--surface-4)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]' )} > {email} diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/search/search.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/search/search.tsx index e5ccb326db..2569d6c5fb 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/search/search.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/search/search.tsx @@ -163,7 +163,7 @@ export function AutocompleteSearch({ }} > -
+
{/* Search Icon */} @@ -266,8 +266,8 @@ export function AutocompleteSearch({ data-index={0} className={cn( 'w-full rounded-[6px] px-3 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--border-focus)]', - 'hover:bg-[var(--surface-9)]', - highlightedIndex === 0 && 'bg-[var(--surface-9)]' + 'hover:bg-[var(--surface-5)]', + highlightedIndex === 0 && 'bg-[var(--surface-5)]' )} onMouseEnter={() => setHighlightedIndex(0)} onMouseDown={(e) => { @@ -296,8 +296,8 @@ export function AutocompleteSearch({ data-index={index} className={cn( 'w-full rounded-[6px] px-3 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--border-focus)]', - 'hover:bg-[var(--surface-9)]', - isHighlighted && 'bg-[var(--surface-9)]' + 'hover:bg-[var(--surface-5)]', + isHighlighted && 'bg-[var(--surface-5)]' )} onMouseEnter={() => setHighlightedIndex(index)} onMouseDown={(e) => { @@ -339,8 +339,8 @@ export function AutocompleteSearch({ data-index={index} className={cn( 'w-full rounded-[6px] px-3 py-2 text-left transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--border-focus)]', - 'hover:bg-[var(--surface-9)]', - index === highlightedIndex && 'bg-[var(--surface-9)]' + 'hover:bg-[var(--surface-5)]', + index === highlightedIndex && 'bg-[var(--surface-5)]' )} onMouseEnter={() => setHighlightedIndex(index)} onMouseDown={(e) => { diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/index.ts b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/index.ts index a18f450876..2884924bb2 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/index.ts @@ -1,4 +1,3 @@ -export { Controls } from './components/controls' export { NotificationSettings } from './components/notifications' export { AutocompleteSearch } from './components/search' export { LogsToolbar } from './logs-toolbar' diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx index a84c69ac44..9bb8c9778a 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/logs-toolbar.tsx @@ -302,7 +302,7 @@ export function LogsToolbar({
{/* More options popover */} - + {/* View mode toggle */}
onViewModeChange(isDashboardView ? 'logs' : 'dashboard')} > diff --git a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts index 1997309fe5..852b0e9959 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/utils.ts +++ b/apps/sim/app/workspace/[workspaceId]/logs/utils.ts @@ -5,108 +5,57 @@ import { getIntegrationMetadata } from '@/lib/logs/get-trigger-options' import { getBlock } from '@/blocks/registry' const CORE_TRIGGER_TYPES = ['manual', 'api', 'schedule', 'chat', 'webhook'] as const -const RUNNING_COLOR = '#22c55e' as const -const PENDING_COLOR = '#f59e0b' as const +/** Possible execution status values for workflow logs */ export type LogStatus = 'error' | 'pending' | 'running' | 'info' -/** - * Checks if a hex color is gray/neutral (low saturation) or too light/dark - */ -export function isGrayOrNeutral(hex: string): boolean { - const r = Number.parseInt(hex.slice(1, 3), 16) - const g = Number.parseInt(hex.slice(3, 5), 16) - const b = Number.parseInt(hex.slice(5, 7), 16) - - const max = Math.max(r, g, b) - const min = Math.min(r, g, b) - const lightness = (max + min) / 2 / 255 - - const delta = max - min - const saturation = delta === 0 ? 0 : delta / (1 - Math.abs(2 * lightness - 1)) / 255 - - return saturation < 0.2 || lightness > 0.8 || lightness < 0.25 -} - -/** - * Converts a hex color to a background variant with appropriate opacity - */ -export function hexToBackground(hex: string): string { - const r = Number.parseInt(hex.slice(1, 3), 16) - const g = Number.parseInt(hex.slice(3, 5), 16) - const b = Number.parseInt(hex.slice(5, 7), 16) - return `rgba(${r}, ${g}, ${b}, 0.2)` +/** Configuration mapping log status to Badge variant and display label */ +const STATUS_VARIANT_MAP: Record< + LogStatus, + { variant: React.ComponentProps['variant']; label: string } +> = { + error: { variant: 'red', label: 'Error' }, + pending: { variant: 'amber', label: 'Pending' }, + running: { variant: 'green', label: 'Running' }, + info: { variant: 'gray', label: 'Info' }, } -/** - * Lightens a hex color to make it more vibrant for text - */ -export function lightenColor(hex: string, percent = 30): string { - const r = Number.parseInt(hex.slice(1, 3), 16) - const g = Number.parseInt(hex.slice(3, 5), 16) - const b = Number.parseInt(hex.slice(5, 7), 16) - - const newR = Math.min(255, Math.round(r + (255 - r) * (percent / 100))) - const newG = Math.min(255, Math.round(g + (255 - g) * (percent / 100))) - const newB = Math.min(255, Math.round(b + (255 - b) * (percent / 100))) - - return `#${newR.toString(16).padStart(2, '0')}${newG.toString(16).padStart(2, '0')}${newB.toString(16).padStart(2, '0')}` +/** Configuration mapping core trigger types to Badge color variants */ +const TRIGGER_VARIANT_MAP: Record['variant']> = { + manual: 'gray-secondary', + api: 'blue', + schedule: 'teal', + chat: 'purple', + webhook: 'orange', } interface StatusBadgeProps { + /** The execution status to display */ status: LogStatus } /** - * Displays a styled badge for a log execution status + * Renders a colored badge indicating log execution status. + * @param props - Component props containing the status + * @returns A Badge with dot indicator and status label */ export const StatusBadge = React.memo(({ status }: StatusBadgeProps) => { - const config = { - error: { - bg: 'var(--terminal-status-error-bg)', - color: 'var(--text-error)', - label: 'Error', - }, - pending: { - bg: hexToBackground(PENDING_COLOR), - color: lightenColor(PENDING_COLOR, 65), - label: 'Pending', - }, - running: { - bg: hexToBackground(RUNNING_COLOR), - color: lightenColor(RUNNING_COLOR, 65), - label: 'Running', - }, - info: { - bg: 'var(--terminal-status-info-bg)', - color: 'var(--terminal-status-info-color)', - label: 'Info', - }, - }[status] - - return React.createElement( - 'div', - { - className: - 'inline-flex items-center gap-[6px] rounded-[6px] px-[9px] py-[2px] font-medium text-[12px]', - style: { backgroundColor: config.bg, color: config.color }, - }, - React.createElement('div', { - className: 'h-[6px] w-[6px] rounded-[2px]', - style: { backgroundColor: config.color }, - }), - config.label - ) + const config = STATUS_VARIANT_MAP[status] + return React.createElement(Badge, { variant: config.variant, dot: true }, config.label) }) StatusBadge.displayName = 'StatusBadge' interface TriggerBadgeProps { + /** The trigger type identifier (e.g., 'manual', 'api', or integration block type) */ trigger: string } /** - * Displays a styled badge for a workflow trigger type + * Renders a colored badge indicating the workflow trigger type. + * Core triggers display with their designated colors; integrations show with icons. + * @param props - Component props containing the trigger type + * @returns A Badge with appropriate styling for the trigger type */ export const TriggerBadge = React.memo(({ trigger }: TriggerBadgeProps) => { const metadata = getIntegrationMetadata(trigger) @@ -114,37 +63,20 @@ export const TriggerBadge = React.memo(({ trigger }: TriggerBadgeProps) => { const block = isIntegration ? getBlock(trigger) : null const IconComponent = block?.icon - const isUnknownIntegration = isIntegration && trigger !== 'generic' && !block - if ( - trigger === 'manual' || - trigger === 'generic' || - isUnknownIntegration || - isGrayOrNeutral(metadata.color) - ) { + const coreVariant = TRIGGER_VARIANT_MAP[trigger] + if (coreVariant) { + return React.createElement(Badge, { variant: coreVariant }, metadata.label) + } + + if (IconComponent) { return React.createElement( Badge, - { - variant: 'default', - className: - 'inline-flex items-center gap-[6px] rounded-[6px] px-[9px] py-[2px] font-medium text-[12px]', - }, - IconComponent && React.createElement(IconComponent, { className: 'h-[12px] w-[12px]' }), + { variant: 'gray-secondary', icon: IconComponent }, metadata.label ) } - const textColor = lightenColor(metadata.color, 65) - - return React.createElement( - 'div', - { - className: - 'inline-flex items-center gap-[6px] rounded-[6px] px-[9px] py-[2px] font-medium text-[12px]', - style: { backgroundColor: hexToBackground(metadata.color), color: textColor }, - }, - IconComponent && React.createElement(IconComponent, { className: 'h-[12px] w-[12px]' }), - metadata.label - ) + return React.createElement(Badge, { variant: 'gray-secondary' }, metadata.label) }) TriggerBadge.displayName = 'TriggerBadge' diff --git a/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx b/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx index 5199252d00..529dcb6b0b 100644 --- a/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx +++ b/apps/sim/app/workspace/[workspaceId]/templates/components/template-card.tsx @@ -29,19 +29,19 @@ export function TemplateCardSkeleton({ className }: { className?: string }) { return (
-
+
-
+
{Array.from({ length: 3 }).map((_, index) => (
))}
@@ -49,14 +49,14 @@ export function TemplateCardSkeleton({ className }: { className?: string }) {
-
-
+
+
-
-
-
-
+
+
+
+
@@ -202,7 +202,7 @@ function TemplateCardInner({
@@ -223,12 +223,14 @@ function TemplateCardInner({ cursorStyle='pointer' /> ) : ( -
+
)}
-

{title}

+

+ {title} +

{blockTypes.length > 4 ? ( @@ -251,10 +253,12 @@ function TemplateCardInner({ ) })}
- +{blockTypes.length - 3} + + +{blockTypes.length - 3} +
) : ( @@ -286,24 +290,26 @@ function TemplateCardInner({ {author}
) : ( -
- +
+
)}
- {author} + + {author} + {isVerified && }
-
+
{usageCount} diff --git a/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx b/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx index 54f75ff22d..e21ddf305a 100644 --- a/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx +++ b/apps/sim/app/workspace/[workspaceId]/templates/templates.tsx @@ -186,7 +186,7 @@ export default function Templates({
-
+
(null) const timeoutRef = useRef(null) const abortControllerRef = useRef(null) + const preventZoomRef = usePreventZoom() // File upload hook const { @@ -784,7 +788,8 @@ export function Chat() { return (
{/* File thumbnails */} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/chat-message/chat-message.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/chat-message/chat-message.tsx index ae9c5759ee..a669650216 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/chat-message/chat-message.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/components/chat-message/chat-message.tsx @@ -156,7 +156,7 @@ export function ChatMessage({ message }: ChatMessageProps) { )} {formattedContent && !formattedContent.startsWith('Uploaded') && ( -
+
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/command-list/command-list.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/command-list/command-list.tsx index 22ccc5b9ae..e23cc92f0d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/command-list/command-list.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/command-list/command-list.tsx @@ -8,6 +8,7 @@ import { Button } from '@/components/emcn' import { AgentIcon } from '@/components/icons' import { cn } from '@/lib/core/utils/cn' import { createLogger } from '@/lib/logs/console/logger' +import { usePreventZoom } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks' import { useSearchModalStore } from '@/stores/search-modal/store' const logger = createLogger('WorkflowCommandList') @@ -58,6 +59,7 @@ export function CommandList() { const params = useParams() const router = useRouter() const { open: openSearchModal } = useSearchModalStore() + const preventZoomRef = usePreventZoom() const workspaceId = params.workspaceId as string | undefined @@ -171,6 +173,7 @@ export function CommandList() { return (
{ const viewport = useViewport() const session = useSession() const currentUserId = session.data?.user?.id + const preventZoomRef = usePreventZoom() const cursors = useMemo(() => { return presenceUsers @@ -41,7 +43,7 @@ const CursorsComponent = () => { } return ( -
+
{cursors.map(({ id, name, cursor, color }) => { const x = cursor.x * viewport.zoom + viewport.x const y = cursor.y * viewport.zoom + viewport.y diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/diff-controls/diff-controls.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/diff-controls/diff-controls.tsx index 570b2edc04..3935fcefeb 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/diff-controls/diff-controls.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/diff-controls/diff-controls.tsx @@ -3,6 +3,7 @@ import clsx from 'clsx' import { Eye, EyeOff } from 'lucide-react' import { Button } from '@/components/emcn' import { createLogger } from '@/lib/logs/console/logger' +import { usePreventZoom } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks' import { useCopilotStore } from '@/stores/panel/copilot/store' import { useTerminalStore } from '@/stores/terminal' import { useWorkflowDiffStore } from '@/stores/workflow-diff' @@ -308,6 +309,8 @@ export const DiffControls = memo(function DiffControls() { }) }, [clearPreviewYaml, updatePreviewToolCallState, rejectChanges]) + const preventZoomRef = usePreventZoom() + // Don't show anything if no diff is available or diff is not ready if (!hasActiveDiff || !isDiffReady) { return null @@ -315,6 +318,7 @@ export const DiffControls = memo(function DiffControls() { return (
Accept diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx index fb7f292697..249962aeb6 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/error/index.tsx @@ -3,6 +3,7 @@ import { Component, type ReactNode, useEffect } from 'react' import { createLogger } from '@/lib/logs/console/logger' import { Panel } from '@/app/workspace/[workspaceId]/w/[workflowId]/components' +import { usePreventZoom } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks' import { Sidebar } from '@/app/workspace/[workspaceId]/w/components/sidebar/sidebar' const logger = createLogger('ErrorBoundary') @@ -23,12 +24,13 @@ export function ErrorUI({ onReset, fullScreen = false, }: ErrorUIProps) { + const preventZoomRef = usePreventZoom() const containerClass = fullScreen ? 'flex flex-col w-full h-screen bg-[var(--surface-1)]' : 'flex flex-col w-full h-full bg-[var(--surface-1)]' return ( -
+
{/* Sidebar */} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/index.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/index.ts index 948fc180cf..123cab3b1a 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/index.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/index.ts @@ -4,7 +4,6 @@ export { DiffControls } from './diff-controls/diff-controls' export { ErrorBoundary } from './error/index' export { Notifications } from './notifications/notifications' export { Panel } from './panel/panel' -export { SkeletonLoading } from './skeleton-loading/skeleton-loading' export { SubflowNodeComponent } from './subflows/subflow-node' export { Terminal } from './terminal/terminal' export { WandPromptBar } from './wand-prompt-bar/wand-prompt-bar' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/note-block/note-block.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/note-block/note-block.tsx index 4ca430d854..655cf84f9b 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/note-block/note-block.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/note-block/note-block.tsx @@ -27,6 +27,21 @@ function extractFieldValue(rawValue: unknown): string | undefined { return undefined } +/** + * Extract YouTube video ID from various YouTube URL formats + */ +function getYouTubeVideoId(url: string): string | null { + const patterns = [ + /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/, + /youtube\.com\/watch\?.*v=([a-zA-Z0-9_-]{11})/, + ] + for (const pattern of patterns) { + const match = url.match(pattern) + if (match) return match[1] + } + return null +} + /** * Compact markdown renderer for note blocks with tight spacing */ @@ -36,39 +51,41 @@ const NoteMarkdown = memo(function NoteMarkdown({ content }: { content: string } remarkPlugins={[remarkGfm]} components={{ p: ({ children }: any) => ( -

{children}

+

+ {children} +

), h1: ({ children }: any) => ( -

+

{children}

), h2: ({ children }: any) => ( -

+

{children}

), h3: ({ children }: any) => ( -

+

{children}

), h4: ({ children }: any) => ( -

+

{children}

), ul: ({ children }: any) => ( -
    +
      {children}
    ), ol: ({ children }: any) => ( -
      +
        {children}
      ), - li: ({ children }: any) =>
    1. {children}
    2. , + li: ({ children }: any) =>
    3. {children}
    4. , code: ({ inline, className, children, ...props }: any) => { const isInline = inline || !className?.includes('language-') @@ -76,7 +93,7 @@ const NoteMarkdown = memo(function NoteMarkdown({ content }: { content: string } return ( {children} @@ -92,22 +109,51 @@ const NoteMarkdown = memo(function NoteMarkdown({ content }: { content: string } ) }, - a: ({ href, children }: any) => ( - - {children} - - ), + a: ({ href, children }: any) => { + const videoId = href ? getYouTubeVideoId(href) : null + if (videoId) { + return ( + + + {children} + + +