From 39fc649284fb7540dc1a44938a6568ee69511bf4 Mon Sep 17 00:00:00 2001 From: waleed Date: Fri, 30 Jan 2026 16:52:01 -0800 Subject: [PATCH 1/4] feat(invitations): added invitations query hook, migrated all tool files to use absolute imports --- .../notifications/notifications.tsx | 8 +- .../workspace-permissions-provider.tsx | 90 ++- .../settings-modal/components/files/files.tsx | 7 +- .../components/permissions-table.tsx | 7 +- .../components/invite-modal/invite-modal.tsx | 566 +++++++----------- .../w/components/sidebar/hooks/index.ts | 2 +- .../sidebar/hooks/use-workspace-management.ts | 389 ++++-------- apps/sim/hooks/queries/invitations.ts | 350 +++++++++++ apps/sim/hooks/queries/oauth-connections.ts | 92 ++- apps/sim/hooks/queries/workspace.ts | 208 ++++++- apps/sim/hooks/use-slack-accounts.ts | 52 -- apps/sim/hooks/use-user-permissions.ts | 4 +- apps/sim/hooks/use-workspace-permissions.ts | 107 ---- apps/sim/tools/a2a/cancel_task.ts | 4 +- .../sim/tools/a2a/delete_push_notification.ts | 7 +- apps/sim/tools/a2a/get_agent_card.ts | 4 +- apps/sim/tools/a2a/get_push_notification.ts | 7 +- apps/sim/tools/a2a/get_task.ts | 4 +- apps/sim/tools/a2a/resubscribe.ts | 4 +- apps/sim/tools/a2a/send_message.ts | 4 +- apps/sim/tools/a2a/set_push_notification.ts | 7 +- apps/sim/tools/apify/run_actor_async.ts | 2 +- apps/sim/tools/apify/run_actor_sync.ts | 2 +- apps/sim/tools/google_groups/add_alias.ts | 5 +- apps/sim/tools/google_groups/add_member.ts | 2 +- apps/sim/tools/google_groups/create_group.ts | 2 +- apps/sim/tools/google_groups/delete_group.ts | 2 +- apps/sim/tools/google_groups/get_group.ts | 2 +- apps/sim/tools/google_groups/get_member.ts | 2 +- apps/sim/tools/google_groups/get_settings.ts | 5 +- apps/sim/tools/google_groups/has_member.ts | 2 +- apps/sim/tools/google_groups/list_aliases.ts | 5 +- apps/sim/tools/google_groups/list_groups.ts | 2 +- apps/sim/tools/google_groups/list_members.ts | 5 +- apps/sim/tools/google_groups/remove_alias.ts | 5 +- apps/sim/tools/google_groups/remove_member.ts | 5 +- apps/sim/tools/google_groups/update_group.ts | 2 +- apps/sim/tools/google_groups/update_member.ts | 5 +- .../tools/google_groups/update_settings.ts | 5 +- apps/sim/tools/http/webhook_request.ts | 2 +- .../incidentio/incident_statuses_list.ts | 4 +- .../tools/incidentio/incident_types_list.ts | 4 +- apps/sim/tools/incidentio/severities_list.ts | 5 +- apps/sim/tools/incidentio/users_list.ts | 5 +- apps/sim/tools/incidentio/users_show.ts | 5 +- apps/sim/tools/incidentio/workflows_create.ts | 2 +- apps/sim/tools/incidentio/workflows_delete.ts | 2 +- apps/sim/tools/incidentio/workflows_list.ts | 2 +- apps/sim/tools/incidentio/workflows_show.ts | 2 +- apps/sim/tools/incidentio/workflows_update.ts | 2 +- apps/sim/tools/intercom/get_company.ts | 3 - apps/sim/tools/intercom/get_conversation.ts | 3 - apps/sim/tools/intercom/list_companies.ts | 3 - apps/sim/tools/intercom/list_contacts.ts | 3 - apps/sim/tools/intercom/list_conversations.ts | 3 - apps/sim/tools/intercom/reply_conversation.ts | 3 - apps/sim/tools/intercom/search_contacts.ts | 3 - apps/sim/tools/kalshi/amend_order.ts | 4 +- apps/sim/tools/kalshi/cancel_order.ts | 4 +- apps/sim/tools/kalshi/create_order.ts | 4 +- apps/sim/tools/kalshi/get_balance.ts | 4 +- apps/sim/tools/kalshi/get_candlesticks.ts | 4 +- apps/sim/tools/kalshi/get_event.ts | 4 +- apps/sim/tools/kalshi/get_events.ts | 8 +- apps/sim/tools/kalshi/get_exchange_status.ts | 4 +- apps/sim/tools/kalshi/get_fills.ts | 6 +- apps/sim/tools/kalshi/get_market.ts | 4 +- apps/sim/tools/kalshi/get_markets.ts | 6 +- apps/sim/tools/kalshi/get_order.ts | 4 +- apps/sim/tools/kalshi/get_orderbook.ts | 4 +- apps/sim/tools/kalshi/get_orders.ts | 6 +- apps/sim/tools/kalshi/get_positions.ts | 6 +- apps/sim/tools/kalshi/get_series_by_ticker.ts | 4 +- apps/sim/tools/kalshi/get_trades.ts | 8 +- apps/sim/tools/kalshi/types.ts | 5 - apps/sim/tools/mailchimp/add_member.ts | 6 +- apps/sim/tools/mailchimp/add_member_tags.ts | 2 +- .../tools/mailchimp/add_or_update_member.ts | 6 +- .../sim/tools/mailchimp/add_segment_member.ts | 9 +- .../mailchimp/add_subscriber_to_automation.ts | 7 +- apps/sim/tools/mailchimp/archive_member.ts | 5 +- apps/sim/tools/mailchimp/create_audience.ts | 4 +- .../tools/mailchimp/create_batch_operation.ts | 4 +- apps/sim/tools/mailchimp/create_campaign.ts | 6 +- apps/sim/tools/mailchimp/create_interest.ts | 7 +- .../mailchimp/create_interest_category.ts | 7 +- .../tools/mailchimp/create_landing_page.ts | 7 +- .../sim/tools/mailchimp/create_merge_field.ts | 7 +- apps/sim/tools/mailchimp/create_segment.ts | 4 +- apps/sim/tools/mailchimp/create_template.ts | 5 +- apps/sim/tools/mailchimp/delete_audience.ts | 5 +- .../tools/mailchimp/delete_batch_operation.ts | 5 +- apps/sim/tools/mailchimp/delete_campaign.ts | 5 +- apps/sim/tools/mailchimp/delete_interest.ts | 5 +- .../mailchimp/delete_interest_category.ts | 5 +- .../tools/mailchimp/delete_landing_page.ts | 5 +- apps/sim/tools/mailchimp/delete_member.ts | 5 +- .../sim/tools/mailchimp/delete_merge_field.ts | 5 +- apps/sim/tools/mailchimp/delete_segment.ts | 5 +- apps/sim/tools/mailchimp/delete_template.ts | 5 +- apps/sim/tools/mailchimp/get_audience.ts | 7 +- apps/sim/tools/mailchimp/get_audiences.ts | 7 +- apps/sim/tools/mailchimp/get_automation.ts | 7 +- apps/sim/tools/mailchimp/get_automations.ts | 7 +- .../tools/mailchimp/get_batch_operation.ts | 7 +- .../tools/mailchimp/get_batch_operations.ts | 7 +- apps/sim/tools/mailchimp/get_campaign.ts | 9 +- .../tools/mailchimp/get_campaign_content.ts | 9 +- .../tools/mailchimp/get_campaign_report.ts | 9 +- .../tools/mailchimp/get_campaign_reports.ts | 9 +- apps/sim/tools/mailchimp/get_campaigns.ts | 9 +- apps/sim/tools/mailchimp/get_interest.ts | 7 +- .../mailchimp/get_interest_categories.ts | 5 +- .../tools/mailchimp/get_interest_category.ts | 7 +- apps/sim/tools/mailchimp/get_interests.ts | 5 +- apps/sim/tools/mailchimp/get_landing_page.ts | 7 +- apps/sim/tools/mailchimp/get_landing_pages.ts | 7 +- apps/sim/tools/mailchimp/get_member.ts | 9 +- apps/sim/tools/mailchimp/get_member_tags.ts | 5 +- apps/sim/tools/mailchimp/get_members.ts | 9 +- apps/sim/tools/mailchimp/get_merge_field.ts | 5 +- apps/sim/tools/mailchimp/get_merge_fields.ts | 7 +- apps/sim/tools/mailchimp/get_segment.ts | 7 +- .../tools/mailchimp/get_segment_members.ts | 7 +- apps/sim/tools/mailchimp/get_segments.ts | 5 +- apps/sim/tools/mailchimp/get_template.ts | 7 +- apps/sim/tools/mailchimp/get_templates.ts | 7 +- apps/sim/tools/mailchimp/pause_automation.ts | 2 +- .../tools/mailchimp/publish_landing_page.ts | 2 +- .../sim/tools/mailchimp/remove_member_tags.ts | 2 +- .../tools/mailchimp/remove_segment_member.ts | 2 +- .../sim/tools/mailchimp/replicate_campaign.ts | 2 +- apps/sim/tools/mailchimp/schedule_campaign.ts | 2 +- apps/sim/tools/mailchimp/send_campaign.ts | 2 +- .../tools/mailchimp/set_campaign_content.ts | 6 +- apps/sim/tools/mailchimp/start_automation.ts | 2 +- apps/sim/tools/mailchimp/unarchive_member.ts | 6 +- .../tools/mailchimp/unpublish_landing_page.ts | 2 +- .../tools/mailchimp/unschedule_campaign.ts | 2 +- apps/sim/tools/mailchimp/update_audience.ts | 4 +- apps/sim/tools/mailchimp/update_campaign.ts | 6 +- apps/sim/tools/mailchimp/update_interest.ts | 4 +- .../mailchimp/update_interest_category.ts | 4 +- .../tools/mailchimp/update_landing_page.ts | 4 +- apps/sim/tools/mailchimp/update_member.ts | 6 +- .../sim/tools/mailchimp/update_merge_field.ts | 4 +- apps/sim/tools/mailchimp/update_segment.ts | 4 +- apps/sim/tools/mailchimp/update_template.ts | 4 +- apps/sim/tools/search/tool.ts | 2 +- apps/sim/tools/shopify/adjust_inventory.ts | 4 +- apps/sim/tools/shopify/cancel_order.ts | 4 +- apps/sim/tools/shopify/create_customer.ts | 4 +- apps/sim/tools/shopify/create_fulfillment.ts | 4 +- apps/sim/tools/shopify/create_product.ts | 4 +- apps/sim/tools/shopify/delete_customer.ts | 2 +- apps/sim/tools/shopify/delete_product.ts | 2 +- apps/sim/tools/shopify/get_collection.ts | 4 +- apps/sim/tools/shopify/get_customer.ts | 4 +- apps/sim/tools/shopify/get_inventory_level.ts | 7 +- apps/sim/tools/shopify/get_order.ts | 4 +- apps/sim/tools/shopify/get_product.ts | 4 +- apps/sim/tools/shopify/list_collections.ts | 4 +- apps/sim/tools/shopify/list_customers.ts | 4 +- .../sim/tools/shopify/list_inventory_items.ts | 7 +- apps/sim/tools/shopify/list_locations.ts | 4 +- apps/sim/tools/shopify/list_orders.ts | 4 +- apps/sim/tools/shopify/list_products.ts | 4 +- apps/sim/tools/shopify/update_customer.ts | 4 +- apps/sim/tools/shopify/update_order.ts | 4 +- apps/sim/tools/shopify/update_product.ts | 4 +- apps/sim/tools/similarweb/bounce_rate.ts | 5 +- apps/sim/tools/similarweb/pages_per_visit.ts | 5 +- apps/sim/tools/similarweb/traffic_visits.ts | 5 +- apps/sim/tools/similarweb/visit_duration.ts | 5 +- apps/sim/tools/similarweb/website_overview.ts | 5 +- apps/sim/tools/spotify/add_to_queue.ts | 2 +- .../tools/spotify/add_tracks_to_playlist.ts | 5 +- apps/sim/tools/spotify/check_saved_tracks.ts | 5 +- apps/sim/tools/spotify/create_playlist.ts | 5 +- apps/sim/tools/spotify/get_album.ts | 6 +- apps/sim/tools/spotify/get_album_tracks.ts | 2 +- apps/sim/tools/spotify/get_albums.ts | 2 +- apps/sim/tools/spotify/get_artist.ts | 2 +- apps/sim/tools/spotify/get_artist_albums.ts | 5 +- .../tools/spotify/get_artist_top_tracks.ts | 7 +- apps/sim/tools/spotify/get_artists.ts | 2 +- apps/sim/tools/spotify/get_categories.ts | 5 +- apps/sim/tools/spotify/get_current_user.ts | 5 +- .../tools/spotify/get_currently_playing.ts | 2 +- apps/sim/tools/spotify/get_devices.ts | 2 +- .../sim/tools/spotify/get_followed_artists.ts | 2 +- apps/sim/tools/spotify/get_new_releases.ts | 7 +- apps/sim/tools/spotify/get_playback_state.ts | 10 +- apps/sim/tools/spotify/get_playlist.ts | 4 +- apps/sim/tools/spotify/get_playlist_tracks.ts | 7 +- apps/sim/tools/spotify/get_queue.ts | 2 +- apps/sim/tools/spotify/get_recently_played.ts | 7 +- apps/sim/tools/spotify/get_saved_albums.ts | 2 +- apps/sim/tools/spotify/get_saved_tracks.ts | 7 +- apps/sim/tools/spotify/get_top_artists.ts | 2 +- apps/sim/tools/spotify/get_top_tracks.ts | 7 +- apps/sim/tools/spotify/get_track.ts | 7 +- apps/sim/tools/spotify/get_tracks.ts | 7 +- apps/sim/tools/spotify/get_user_playlists.ts | 5 +- apps/sim/tools/spotify/pause.ts | 2 +- apps/sim/tools/spotify/play.ts | 2 +- .../spotify/remove_tracks_from_playlist.ts | 4 +- apps/sim/tools/spotify/save_tracks.ts | 2 +- apps/sim/tools/spotify/search.ts | 6 +- apps/sim/tools/spotify/set_volume.ts | 2 +- apps/sim/tools/spotify/skip_next.ts | 2 +- apps/sim/tools/spotify/skip_previous.ts | 2 +- apps/sim/tools/stagehand/extract.ts | 3 - apps/sim/tools/typeform/insights.ts | 3 - apps/sim/tools/wealthbox/read_contact.ts | 3 - apps/sim/tools/wealthbox/read_note.ts | 3 - apps/sim/tools/wordpress/create_category.ts | 2 +- apps/sim/tools/wordpress/create_comment.ts | 2 +- apps/sim/tools/wordpress/create_page.ts | 2 +- apps/sim/tools/wordpress/create_post.ts | 2 +- apps/sim/tools/wordpress/create_tag.ts | 2 +- apps/sim/tools/wordpress/delete_comment.ts | 2 +- apps/sim/tools/wordpress/delete_media.ts | 2 +- apps/sim/tools/wordpress/delete_page.ts | 2 +- apps/sim/tools/wordpress/delete_post.ts | 2 +- apps/sim/tools/wordpress/get_current_user.ts | 2 +- apps/sim/tools/wordpress/get_media.ts | 2 +- apps/sim/tools/wordpress/get_page.ts | 2 +- apps/sim/tools/wordpress/get_post.ts | 2 +- apps/sim/tools/wordpress/get_user.ts | 2 +- apps/sim/tools/wordpress/list_categories.ts | 2 +- apps/sim/tools/wordpress/list_comments.ts | 2 +- apps/sim/tools/wordpress/list_media.ts | 2 +- apps/sim/tools/wordpress/list_pages.ts | 2 +- apps/sim/tools/wordpress/list_posts.ts | 2 +- apps/sim/tools/wordpress/list_tags.ts | 2 +- apps/sim/tools/wordpress/list_users.ts | 2 +- apps/sim/tools/wordpress/search_content.ts | 2 +- apps/sim/tools/wordpress/update_comment.ts | 2 +- apps/sim/tools/wordpress/update_page.ts | 2 +- apps/sim/tools/wordpress/update_post.ts | 2 +- apps/sim/tools/wordpress/upload_media.ts | 11 +- .../zendesk/autocomplete_organizations.ts | 5 +- apps/sim/tools/zendesk/create_organization.ts | 6 +- .../zendesk/create_organizations_bulk.ts | 2 +- apps/sim/tools/zendesk/create_ticket.ts | 6 +- apps/sim/tools/zendesk/create_tickets_bulk.ts | 2 +- apps/sim/tools/zendesk/create_user.ts | 2 +- apps/sim/tools/zendesk/create_users_bulk.ts | 2 +- apps/sim/tools/zendesk/delete_organization.ts | 5 +- apps/sim/tools/zendesk/delete_ticket.ts | 5 +- apps/sim/tools/zendesk/delete_user.ts | 5 +- apps/sim/tools/zendesk/get_current_user.ts | 5 +- apps/sim/tools/zendesk/get_organization.ts | 9 +- apps/sim/tools/zendesk/get_organizations.ts | 5 +- apps/sim/tools/zendesk/get_ticket.ts | 9 +- apps/sim/tools/zendesk/get_tickets.ts | 5 +- apps/sim/tools/zendesk/get_user.ts | 5 +- apps/sim/tools/zendesk/get_users.ts | 5 +- apps/sim/tools/zendesk/merge_tickets.ts | 5 +- apps/sim/tools/zendesk/search.ts | 10 +- apps/sim/tools/zendesk/search_count.ts | 5 +- apps/sim/tools/zendesk/search_users.ts | 5 +- apps/sim/tools/zendesk/update_organization.ts | 6 +- apps/sim/tools/zendesk/update_ticket.ts | 6 +- apps/sim/tools/zendesk/update_tickets_bulk.ts | 5 +- apps/sim/tools/zendesk/update_user.ts | 2 +- apps/sim/tools/zendesk/update_users_bulk.ts | 2 +- biome.json | 27 +- 269 files changed, 1542 insertions(+), 1484 deletions(-) create mode 100644 apps/sim/hooks/queries/invitations.ts delete mode 100644 apps/sim/hooks/use-slack-accounts.ts delete mode 100644 apps/sim/hooks/use-workspace-permissions.ts 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 216ccf8414..81bbfa3a28 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 @@ -32,8 +32,7 @@ import { useTestNotification, useUpdateNotification, } from '@/hooks/queries/notifications' -import { useConnectOAuthService } from '@/hooks/queries/oauth-connections' -import { useSlackAccounts } from '@/hooks/use-slack-accounts' +import { useConnectedAccounts, useConnectOAuthService } from '@/hooks/queries/oauth-connections' import { CORE_TRIGGER_TYPES, type CoreTriggerType } from '@/stores/logs/filters/types' import { SlackChannelSelector } from './components/slack-channel-selector' import { WorkflowSelector } from './components/workflow-selector' @@ -167,7 +166,8 @@ export function NotificationSettings({ const deleteNotification = useDeleteNotification() const testNotification = useTestNotification() - const { accounts: slackAccounts, isLoading: isLoadingSlackAccounts } = useSlackAccounts() + const { data: slackAccounts = [], isLoading: isLoadingSlackAccounts } = + useConnectedAccounts('slack') const connectSlack = useConnectOAuthService() useEffect(() => { @@ -530,7 +530,7 @@ export function NotificationSettings({ message: result.data?.error || (result.data?.success ? 'Test sent successfully' : 'Test failed'), }) - } catch (error) { + } catch (_error) { setTestStatus({ id, success: false, message: 'Failed to send test' }) } } diff --git a/apps/sim/app/workspace/[workspaceId]/providers/workspace-permissions-provider.tsx b/apps/sim/app/workspace/[workspaceId]/providers/workspace-permissions-provider.tsx index 607d177888..ab198204d0 100644 --- a/apps/sim/app/workspace/[workspaceId]/providers/workspace-permissions-provider.tsx +++ b/apps/sim/app/workspace/[workspaceId]/providers/workspace-permissions-provider.tsx @@ -1,32 +1,28 @@ 'use client' import type React from 'react' -import { createContext, useContext, useEffect, useMemo, useState } from 'react' +import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react' import { createLogger } from '@sim/logger' +import { useQueryClient } from '@tanstack/react-query' import { useParams } from 'next/navigation' -import { useUserPermissions, type WorkspaceUserPermissions } from '@/hooks/use-user-permissions' import { - useWorkspacePermissions, + useWorkspacePermissionsQuery, type WorkspacePermissions, -} from '@/hooks/use-workspace-permissions' + workspaceKeys, +} from '@/hooks/queries/workspace' +import { useUserPermissions, type WorkspaceUserPermissions } from '@/hooks/use-user-permissions' import { useNotificationStore } from '@/stores/notifications' import { useOperationQueueStore } from '@/stores/operation-queue/store' const logger = createLogger('WorkspacePermissionsProvider') interface WorkspacePermissionsContextType { - // Raw workspace permissions data workspacePermissions: WorkspacePermissions | null permissionsLoading: boolean permissionsError: string | null updatePermissions: (newPermissions: WorkspacePermissions) => void refetchPermissions: () => Promise - - // Computed user permissions (connection-aware) userPermissions: WorkspaceUserPermissions & { isOfflineMode?: boolean } - - // Connection state management - setOfflineMode: (isOffline: boolean) => void } const WorkspacePermissionsContext = createContext({ @@ -43,7 +39,6 @@ const WorkspacePermissionsContext = createContext {}, }) interface WorkspacePermissionsProviderProps { @@ -51,35 +46,20 @@ interface WorkspacePermissionsProviderProps { } /** - * Provider that manages workspace permissions and user access - * Also provides connection-aware permissions that enforce read-only mode when offline + * Provides workspace permissions and connection-aware user access throughout the app. + * Enforces read-only mode when offline to prevent data loss. */ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsProviderProps) { const params = useParams() const workspaceId = params?.workspaceId as string + const queryClient = useQueryClient() - // Manage offline mode state locally - const [isOfflineMode, setIsOfflineMode] = useState(false) - - // Track whether we've already surfaced an offline notification to avoid duplicates const [hasShownOfflineNotification, setHasShownOfflineNotification] = useState(false) - - // Get operation error state directly from the store (avoid full useCollaborativeWorkflow subscription) const hasOperationError = useOperationQueueStore((state) => state.hasOperationError) - const addNotification = useNotificationStore((state) => state.addNotification) - // Set offline mode when there are operation errors - useEffect(() => { - if (hasOperationError) { - setIsOfflineMode(true) - } - }, [hasOperationError]) + const isOfflineMode = hasOperationError - /** - * Surface a global notification when entering offline mode. - * Uses the shared notifications system instead of bespoke UI in individual components. - */ useEffect(() => { if (!isOfflineMode || hasShownOfflineNotification) { return @@ -89,7 +69,6 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP addNotification({ level: 'error', message: 'Connection unavailable', - // Global notification (no workflowId) so it is visible regardless of the active workflow action: { type: 'refresh', message: '', @@ -101,40 +80,44 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP } }, [addNotification, hasShownOfflineNotification, isOfflineMode]) - // Fetch workspace permissions and loading state const { - permissions: workspacePermissions, - loading: permissionsLoading, - error: permissionsError, - updatePermissions, - refetch: refetchPermissions, - } = useWorkspacePermissions(workspaceId) - - // Get base user permissions from workspace permissions + data: workspacePermissions, + isLoading: permissionsLoading, + error: permissionsErrorObj, + refetch, + } = useWorkspacePermissionsQuery(workspaceId) + + const permissionsError = permissionsErrorObj?.message ?? null + + const updatePermissions = useCallback( + (newPermissions: WorkspacePermissions) => { + if (!workspaceId) return + queryClient.setQueryData(workspaceKeys.permissions(workspaceId), newPermissions) + }, + [workspaceId, queryClient] + ) + + const refetchPermissions = useCallback(async () => { + await refetch() + }, [refetch]) + const baseUserPermissions = useUserPermissions( - workspacePermissions, + workspacePermissions ?? null, permissionsLoading, permissionsError ) - // Note: Connection-based error detection removed - only rely on operation timeouts - // The 5-second operation timeout system will handle all error cases - - // Create connection-aware permissions that override user permissions when offline const userPermissions = useMemo((): WorkspaceUserPermissions & { isOfflineMode?: boolean } => { if (isOfflineMode) { - // In offline mode, force read-only permissions regardless of actual user permissions return { ...baseUserPermissions, canEdit: false, canAdmin: false, - // Keep canRead true so users can still view content canRead: baseUserPermissions.canRead, isOfflineMode: true, } } - // When online, use normal permissions return { ...baseUserPermissions, isOfflineMode: false, @@ -143,13 +126,12 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP const contextValue = useMemo( () => ({ - workspacePermissions, + workspacePermissions: workspacePermissions ?? null, permissionsLoading, permissionsError, updatePermissions, refetchPermissions, userPermissions, - setOfflineMode: setIsOfflineMode, }), [ workspacePermissions, @@ -169,8 +151,8 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP } /** - * Hook to access workspace permissions and data from context - * This provides both raw workspace permissions and computed user permissions + * Accesses workspace permissions data and operations from context. + * Must be used within a WorkspacePermissionsProvider. */ export function useWorkspacePermissionsContext(): WorkspacePermissionsContextType { const context = useContext(WorkspacePermissionsContext) @@ -183,8 +165,8 @@ export function useWorkspacePermissionsContext(): WorkspacePermissionsContextTyp } /** - * Hook to access user permissions from context - * This replaces individual useUserPermissions calls and includes connection-aware permissions + * Accesses the current user's computed permissions including offline mode status. + * Convenience hook that extracts userPermissions from the context. */ export function useUserPermissionsContext(): WorkspaceUserPermissions & { isOfflineMode?: boolean diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/files/files.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/files/files.tsx index 824dbf0263..92422d6ee0 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/files/files.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/files/files.tsx @@ -21,14 +21,13 @@ import { cn } from '@/lib/core/utils/cn' import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace' import { getFileExtension } from '@/lib/uploads/utils/file-utils' import { getDocumentIcon } from '@/app/workspace/[workspaceId]/knowledge/components' +import { useWorkspacePermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' import { useDeleteWorkspaceFile, useStorageInfo, useUploadWorkspaceFile, useWorkspaceFiles, } from '@/hooks/queries/workspace-files' -import { useUserPermissions } from '@/hooks/use-user-permissions' -import { useWorkspacePermissions } from '@/hooks/use-workspace-permissions' const logger = createLogger('FileUploadsSettings') const isBillingEnabled = isTruthy(getEnv('NEXT_PUBLIC_BILLING_ENABLED')) @@ -94,9 +93,7 @@ export function Files() { const fileInputRef = useRef(null) const scrollContainerRef = useRef(null) - const { permissions: workspacePermissions, loading: permissionsLoading } = - useWorkspacePermissions(workspaceId) - const userPermissions = useUserPermissions(workspacePermissions, permissionsLoading) + const { userPermissions, permissionsLoading } = useWorkspacePermissionsContext() const handleUploadClick = () => { fileInputRef.current?.click() diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal/components/permissions-table.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal/components/permissions-table.tsx index b27970559e..92f0b9cafb 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal/components/permissions-table.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal/components/permissions-table.tsx @@ -4,7 +4,7 @@ import { Badge, Button, Tooltip } from '@/components/emcn' import { useSession } from '@/lib/auth/auth-client' import type { PermissionType } from '@/lib/workspaces/permissions/utils' import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider' -import type { WorkspacePermissions } from '@/hooks/use-workspace-permissions' +import type { WorkspacePermissions } from '@/hooks/queries/workspace' import { PermissionSelector } from './permission-selector' import { PermissionsTableSkeleton } from './permissions-table-skeleton' import type { UserPermissions } from './types' @@ -14,7 +14,7 @@ export interface PermissionsTableProps { onPermissionChange: (userId: string, permissionType: PermissionType) => void onRemoveMember?: (userId: string, email: string) => void onRemoveInvitation?: (invitationId: string, email: string) => void - onResendInvitation?: (invitationId: string, email: string) => void + onResendInvitation?: (invitationId: string) => void disabled?: boolean existingUserPermissionChanges: Record> isSaving?: boolean @@ -143,7 +143,6 @@ export const PermissionsTable = ({
{allUsers.map((user) => { const isCurrentUser = user.isCurrentUser === true - const isExistingUser = filteredExistingUsers.some((eu) => eu.email === user.email) const isPendingInvitation = user.isPendingInvitation === true const userIdentifier = user.userId || user.email const originalPermission = workspacePermissions?.users?.find( @@ -205,7 +204,7 @@ export const PermissionsTable = ({ - -
- )} +
+ + +