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/docs/content/docs/en/tools/google_bigquery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ description: Query, list, and insert data in Google BigQuery

import { BlockInfoCard } from "@/components/ui/block-info-card"

<BlockInfoCard
<BlockInfoCard
type="google_bigquery"
color="#E0E0E0"
/>

{/* MANUAL-CONTENT-START:intro */}
[Google BigQuery](https://cloud.google.com/bigquery) is Google Cloud's fully managed, serverless data warehouse designed for large-scale data analytics. BigQuery lets you run fast SQL queries on massive datasets, making it ideal for business intelligence, data exploration, and machine learning pipelines. It supports standard SQL, streaming inserts, and integrates with the broader Google Cloud ecosystem.

In Sim, the Google BigQuery integration allows your agents to query datasets, list tables, inspect schemas, and insert rows as part of automated workflows. This enables use cases such as automated reporting, data pipeline orchestration, real-time data ingestion, and analytics-driven decision making. By connecting Sim with BigQuery, your agents can pull insights from petabytes of data, write results back to tables, and keep your analytics workflows running without manual intervention.
{/* MANUAL-CONTENT-END */}

## Usage Instructions

Connect to Google BigQuery to run SQL queries, list datasets and tables, get table metadata, and insert rows.
Expand Down
8 changes: 7 additions & 1 deletion apps/docs/content/docs/en/tools/google_books.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ description: Search and retrieve book information

import { BlockInfoCard } from "@/components/ui/block-info-card"

<BlockInfoCard
<BlockInfoCard
type="google_books"
color="#E0E0E0"
/>

{/* MANUAL-CONTENT-START:intro */}
[Google Books](https://books.google.com) is Google's comprehensive book discovery and metadata service, providing access to millions of books from publishers, libraries, and digitized collections worldwide. The Google Books API enables programmatic search and retrieval of detailed book information including titles, authors, descriptions, ratings, and publication details.

In Sim, the Google Books integration allows your agents to search for books and retrieve volume details as part of automated workflows. This enables use cases such as content research, reading list curation, bibliographic data enrichment, ISBN lookups, and knowledge gathering from published works. By connecting Sim with Google Books, your agents can discover and analyze book metadata, filter by availability or format, and incorporate literary references into their outputs—all without manual research.
{/* MANUAL-CONTENT-END */}

## Usage Instructions

Search for books using the Google Books API. Find volumes by title, author, ISBN, or keywords, and retrieve detailed information about specific books including descriptions, ratings, and publication details.
Expand Down
8 changes: 7 additions & 1 deletion apps/docs/content/docs/en/tools/google_tasks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ description: Manage Google Tasks

import { BlockInfoCard } from "@/components/ui/block-info-card"

<BlockInfoCard
<BlockInfoCard
type="google_tasks"
color="#E0E0E0"
/>

{/* MANUAL-CONTENT-START:intro */}
[Google Tasks](https://support.google.com/tasks) is Google's lightweight task management service, integrated into Gmail, Google Calendar, and the standalone Google Tasks app. It provides a simple way to create, organize, and track to-do items with support for due dates, subtasks, and task lists. As part of Google Workspace, Google Tasks keeps your action items synchronized across all your devices.

In Sim, the Google Tasks integration allows your agents to create, read, update, delete, and list tasks and task lists as part of automated workflows. This enables use cases such as automated task creation from incoming data, to-do list management based on workflow triggers, task status tracking, and deadline monitoring. By connecting Sim with Google Tasks, your agents can manage action items programmatically, keep teams organized, and ensure nothing falls through the cracks.
{/* MANUAL-CONTENT-END */}

## Usage Instructions

Integrate Google Tasks into your workflow. Create, read, update, delete, and list tasks and task lists.
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/content/docs/en/tools/table.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ description: User-defined data tables for storing and querying structured data

import { BlockInfoCard } from "@/components/ui/block-info-card"

<BlockInfoCard
<BlockInfoCard
type="table"
color="#10B981"
/>

{/* MANUAL-CONTENT-START:intro */}
Tables allow you to create and manage custom data tables directly within Sim. Store, query, and manipulate structured data within your workflows without needing external database integrations.

**Why Use Tables?**
Expand All @@ -26,6 +27,7 @@ Tables allow you to create and manage custom data tables directly within Sim. St
- Batch operations for bulk inserts
- Bulk updates and deletes by filter
- Up to 10,000 rows per table, 100 tables per workspace
{/* MANUAL-CONTENT-END */}

## Creating Tables

Expand Down
10 changes: 10 additions & 0 deletions apps/sim/app/workspace/[workspaceId]/w/[workflowId]/workflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2534,6 +2534,16 @@ const WorkflowContent = React.memo(() => {
window.removeEventListener('remove-from-subflow', handleRemoveFromSubflow as EventListener)
}, [blocks, edgesForDisplay, getNodeAbsolutePosition, collaborativeBatchUpdateParent])

useEffect(() => {
const handleToggleWorkflowLock = (e: CustomEvent<{ blockIds: string[] }>) => {
collaborativeBatchToggleLocked(e.detail.blockIds)
}

window.addEventListener('toggle-workflow-lock', handleToggleWorkflowLock as EventListener)
return () =>
window.removeEventListener('toggle-workflow-lock', handleToggleWorkflowLock as EventListener)
}, [collaborativeBatchToggleLocked])

/**
* Updates container dimensions in displayNodes during drag or keyboard movement.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,24 @@ interface ContextMenuProps {
* Set to true when user cannot leave (e.g., last admin)
*/
disableLeave?: boolean
/**
* Callback when lock/unlock is clicked
*/
onToggleLock?: () => void
/**
* Whether to show the lock option (default: false)
* Set to true for workflows that support locking
*/
showLock?: boolean
/**
* Whether the lock option is disabled (default: false)
* Set to true when user lacks permissions
*/
disableLock?: boolean
/**
* Whether the workflow is currently locked (all blocks locked)
*/
isLocked?: boolean
}

/**
Expand Down Expand Up @@ -321,6 +339,10 @@ export function ContextMenu({
onLeave,
showLeave = false,
disableLeave = false,
onToggleLock,
showLock = false,
disableLock = false,
isLocked = false,
}: ContextMenuProps) {
const [hexInput, setHexInput] = useState(currentColor || '#ffffff')

Expand Down Expand Up @@ -372,7 +394,8 @@ export function ContextMenu({
(showRename && onRename) ||
(showCreate && onCreate) ||
(showCreateFolder && onCreateFolder) ||
(showColorChange && onColorChange)
(showColorChange && onColorChange) ||
(showLock && onToggleLock)
const hasCopySection = (showDuplicate && onDuplicate) || (showExport && onExport)

return (
Expand Down Expand Up @@ -495,6 +518,19 @@ export function ContextMenu({
</PopoverFolder>
)}

{showLock && onToggleLock && (
<PopoverItem
rootOnly
disabled={disableLock}
onClick={() => {
onToggleLock()
onClose()
}}
>
{isLocked ? 'Unlock' : 'Lock'}
</PopoverItem>
)}

{/* Copy and export actions */}
{hasEditSection && hasCopySection && <PopoverDivider rootOnly />}
{showDuplicate && onDuplicate && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MoreHorizontal } from 'lucide-react'
import Link from 'next/link'
import { useParams } from 'next/navigation'
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
import { getWorkflowLockToggleIds } from '@/app/workspace/[workspaceId]/w/[workflowId]/utils'
import { ContextMenu } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/context-menu/context-menu'
import { DeleteModal } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/delete-modal/delete-modal'
import { Avatars } from '@/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/workflow-item/avatars/avatars'
Expand All @@ -27,6 +28,7 @@ import {
import { useFolderStore } from '@/stores/folders/store'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import type { WorkflowMetadata } from '@/stores/workflows/registry/types'
import { useWorkflowStore } from '@/stores/workflows/workflow/store'

interface WorkflowItemProps {
workflow: WorkflowMetadata
Expand Down Expand Up @@ -169,6 +171,29 @@ export function WorkflowItem({
[workflow.id, updateWorkflow]
)

const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
const isActiveWorkflow = workflow.id === activeWorkflowId

const isWorkflowLocked = useWorkflowStore(
useCallback(
(state) => {
if (!isActiveWorkflow) return false
const blockValues = Object.values(state.blocks)
if (blockValues.length === 0) return false
return blockValues.every((block) => block.locked)
},
[isActiveWorkflow]
)
)

const handleToggleLock = useCallback(() => {
if (!isActiveWorkflow) return
const blocks = useWorkflowStore.getState().blocks
const blockIds = getWorkflowLockToggleIds(blocks, !isWorkflowLocked)
if (blockIds.length === 0) return
window.dispatchEvent(new CustomEvent('toggle-workflow-lock', { detail: { blockIds } }))
}, [isActiveWorkflow, isWorkflowLocked])

const isEditingRef = useRef(false)

const {
Expand Down Expand Up @@ -461,6 +486,10 @@ export function WorkflowItem({
disableExport={!userPermissions.canEdit}
disableColorChange={!userPermissions.canEdit}
disableDelete={!userPermissions.canEdit || !canDeleteSelection}
onToggleLock={handleToggleLock}
showLock={isActiveWorkflow && !isMixedSelection && selectedWorkflows.size <= 1}
disableLock={!userPermissions.canAdmin}
isLocked={isWorkflowLocked}
/>

<DeleteModal
Expand Down