Skip to content

Commit 39fc649

Browse files
committed
feat(invitations): added invitations query hook, migrated all tool files to use absolute imports
1 parent 92403e0 commit 39fc649

File tree

269 files changed

+1542
-1484
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

269 files changed

+1542
-1484
lines changed

apps/sim/app/workspace/[workspaceId]/logs/components/logs-toolbar/components/notifications/notifications.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ import {
3232
useTestNotification,
3333
useUpdateNotification,
3434
} from '@/hooks/queries/notifications'
35-
import { useConnectOAuthService } from '@/hooks/queries/oauth-connections'
36-
import { useSlackAccounts } from '@/hooks/use-slack-accounts'
35+
import { useConnectedAccounts, useConnectOAuthService } from '@/hooks/queries/oauth-connections'
3736
import { CORE_TRIGGER_TYPES, type CoreTriggerType } from '@/stores/logs/filters/types'
3837
import { SlackChannelSelector } from './components/slack-channel-selector'
3938
import { WorkflowSelector } from './components/workflow-selector'
@@ -167,7 +166,8 @@ export function NotificationSettings({
167166
const deleteNotification = useDeleteNotification()
168167
const testNotification = useTestNotification()
169168

170-
const { accounts: slackAccounts, isLoading: isLoadingSlackAccounts } = useSlackAccounts()
169+
const { data: slackAccounts = [], isLoading: isLoadingSlackAccounts } =
170+
useConnectedAccounts('slack')
171171
const connectSlack = useConnectOAuthService()
172172

173173
useEffect(() => {
@@ -530,7 +530,7 @@ export function NotificationSettings({
530530
message:
531531
result.data?.error || (result.data?.success ? 'Test sent successfully' : 'Test failed'),
532532
})
533-
} catch (error) {
533+
} catch (_error) {
534534
setTestStatus({ id, success: false, message: 'Failed to send test' })
535535
}
536536
}

apps/sim/app/workspace/[workspaceId]/providers/workspace-permissions-provider.tsx

Lines changed: 36 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
11
'use client'
22

33
import type React from 'react'
4-
import { createContext, useContext, useEffect, useMemo, useState } from 'react'
4+
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'
55
import { createLogger } from '@sim/logger'
6+
import { useQueryClient } from '@tanstack/react-query'
67
import { useParams } from 'next/navigation'
7-
import { useUserPermissions, type WorkspaceUserPermissions } from '@/hooks/use-user-permissions'
88
import {
9-
useWorkspacePermissions,
9+
useWorkspacePermissionsQuery,
1010
type WorkspacePermissions,
11-
} from '@/hooks/use-workspace-permissions'
11+
workspaceKeys,
12+
} from '@/hooks/queries/workspace'
13+
import { useUserPermissions, type WorkspaceUserPermissions } from '@/hooks/use-user-permissions'
1214
import { useNotificationStore } from '@/stores/notifications'
1315
import { useOperationQueueStore } from '@/stores/operation-queue/store'
1416

1517
const logger = createLogger('WorkspacePermissionsProvider')
1618

1719
interface WorkspacePermissionsContextType {
18-
// Raw workspace permissions data
1920
workspacePermissions: WorkspacePermissions | null
2021
permissionsLoading: boolean
2122
permissionsError: string | null
2223
updatePermissions: (newPermissions: WorkspacePermissions) => void
2324
refetchPermissions: () => Promise<void>
24-
25-
// Computed user permissions (connection-aware)
2625
userPermissions: WorkspaceUserPermissions & { isOfflineMode?: boolean }
27-
28-
// Connection state management
29-
setOfflineMode: (isOffline: boolean) => void
3026
}
3127

3228
const WorkspacePermissionsContext = createContext<WorkspacePermissionsContextType>({
@@ -43,43 +39,27 @@ const WorkspacePermissionsContext = createContext<WorkspacePermissionsContextTyp
4339
isLoading: false,
4440
error: null,
4541
},
46-
setOfflineMode: () => {},
4742
})
4843

4944
interface WorkspacePermissionsProviderProps {
5045
children: React.ReactNode
5146
}
5247

5348
/**
54-
* Provider that manages workspace permissions and user access
55-
* Also provides connection-aware permissions that enforce read-only mode when offline
49+
* Provides workspace permissions and connection-aware user access throughout the app.
50+
* Enforces read-only mode when offline to prevent data loss.
5651
*/
5752
export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsProviderProps) {
5853
const params = useParams()
5954
const workspaceId = params?.workspaceId as string
55+
const queryClient = useQueryClient()
6056

61-
// Manage offline mode state locally
62-
const [isOfflineMode, setIsOfflineMode] = useState(false)
63-
64-
// Track whether we've already surfaced an offline notification to avoid duplicates
6557
const [hasShownOfflineNotification, setHasShownOfflineNotification] = useState(false)
66-
67-
// Get operation error state directly from the store (avoid full useCollaborativeWorkflow subscription)
6858
const hasOperationError = useOperationQueueStore((state) => state.hasOperationError)
69-
7059
const addNotification = useNotificationStore((state) => state.addNotification)
7160

72-
// Set offline mode when there are operation errors
73-
useEffect(() => {
74-
if (hasOperationError) {
75-
setIsOfflineMode(true)
76-
}
77-
}, [hasOperationError])
61+
const isOfflineMode = hasOperationError
7862

79-
/**
80-
* Surface a global notification when entering offline mode.
81-
* Uses the shared notifications system instead of bespoke UI in individual components.
82-
*/
8363
useEffect(() => {
8464
if (!isOfflineMode || hasShownOfflineNotification) {
8565
return
@@ -89,7 +69,6 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
8969
addNotification({
9070
level: 'error',
9171
message: 'Connection unavailable',
92-
// Global notification (no workflowId) so it is visible regardless of the active workflow
9372
action: {
9473
type: 'refresh',
9574
message: '',
@@ -101,40 +80,44 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
10180
}
10281
}, [addNotification, hasShownOfflineNotification, isOfflineMode])
10382

104-
// Fetch workspace permissions and loading state
10583
const {
106-
permissions: workspacePermissions,
107-
loading: permissionsLoading,
108-
error: permissionsError,
109-
updatePermissions,
110-
refetch: refetchPermissions,
111-
} = useWorkspacePermissions(workspaceId)
112-
113-
// Get base user permissions from workspace permissions
84+
data: workspacePermissions,
85+
isLoading: permissionsLoading,
86+
error: permissionsErrorObj,
87+
refetch,
88+
} = useWorkspacePermissionsQuery(workspaceId)
89+
90+
const permissionsError = permissionsErrorObj?.message ?? null
91+
92+
const updatePermissions = useCallback(
93+
(newPermissions: WorkspacePermissions) => {
94+
if (!workspaceId) return
95+
queryClient.setQueryData(workspaceKeys.permissions(workspaceId), newPermissions)
96+
},
97+
[workspaceId, queryClient]
98+
)
99+
100+
const refetchPermissions = useCallback(async () => {
101+
await refetch()
102+
}, [refetch])
103+
114104
const baseUserPermissions = useUserPermissions(
115-
workspacePermissions,
105+
workspacePermissions ?? null,
116106
permissionsLoading,
117107
permissionsError
118108
)
119109

120-
// Note: Connection-based error detection removed - only rely on operation timeouts
121-
// The 5-second operation timeout system will handle all error cases
122-
123-
// Create connection-aware permissions that override user permissions when offline
124110
const userPermissions = useMemo((): WorkspaceUserPermissions & { isOfflineMode?: boolean } => {
125111
if (isOfflineMode) {
126-
// In offline mode, force read-only permissions regardless of actual user permissions
127112
return {
128113
...baseUserPermissions,
129114
canEdit: false,
130115
canAdmin: false,
131-
// Keep canRead true so users can still view content
132116
canRead: baseUserPermissions.canRead,
133117
isOfflineMode: true,
134118
}
135119
}
136120

137-
// When online, use normal permissions
138121
return {
139122
...baseUserPermissions,
140123
isOfflineMode: false,
@@ -143,13 +126,12 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
143126

144127
const contextValue = useMemo(
145128
() => ({
146-
workspacePermissions,
129+
workspacePermissions: workspacePermissions ?? null,
147130
permissionsLoading,
148131
permissionsError,
149132
updatePermissions,
150133
refetchPermissions,
151134
userPermissions,
152-
setOfflineMode: setIsOfflineMode,
153135
}),
154136
[
155137
workspacePermissions,
@@ -169,8 +151,8 @@ export function WorkspacePermissionsProvider({ children }: WorkspacePermissionsP
169151
}
170152

171153
/**
172-
* Hook to access workspace permissions and data from context
173-
* This provides both raw workspace permissions and computed user permissions
154+
* Accesses workspace permissions data and operations from context.
155+
* Must be used within a WorkspacePermissionsProvider.
174156
*/
175157
export function useWorkspacePermissionsContext(): WorkspacePermissionsContextType {
176158
const context = useContext(WorkspacePermissionsContext)
@@ -183,8 +165,8 @@ export function useWorkspacePermissionsContext(): WorkspacePermissionsContextTyp
183165
}
184166

185167
/**
186-
* Hook to access user permissions from context
187-
* This replaces individual useUserPermissions calls and includes connection-aware permissions
168+
* Accesses the current user's computed permissions including offline mode status.
169+
* Convenience hook that extracts userPermissions from the context.
188170
*/
189171
export function useUserPermissionsContext(): WorkspaceUserPermissions & {
190172
isOfflineMode?: boolean

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/settings-modal/components/files/files.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@ import { cn } from '@/lib/core/utils/cn'
2121
import type { WorkspaceFileRecord } from '@/lib/uploads/contexts/workspace'
2222
import { getFileExtension } from '@/lib/uploads/utils/file-utils'
2323
import { getDocumentIcon } from '@/app/workspace/[workspaceId]/knowledge/components'
24+
import { useWorkspacePermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
2425
import {
2526
useDeleteWorkspaceFile,
2627
useStorageInfo,
2728
useUploadWorkspaceFile,
2829
useWorkspaceFiles,
2930
} from '@/hooks/queries/workspace-files'
30-
import { useUserPermissions } from '@/hooks/use-user-permissions'
31-
import { useWorkspacePermissions } from '@/hooks/use-workspace-permissions'
3231

3332
const logger = createLogger('FileUploadsSettings')
3433
const isBillingEnabled = isTruthy(getEnv('NEXT_PUBLIC_BILLING_ENABLED'))
@@ -94,9 +93,7 @@ export function Files() {
9493
const fileInputRef = useRef<HTMLInputElement>(null)
9594
const scrollContainerRef = useRef<HTMLDivElement>(null)
9695

97-
const { permissions: workspacePermissions, loading: permissionsLoading } =
98-
useWorkspacePermissions(workspaceId)
99-
const userPermissions = useUserPermissions(workspacePermissions, permissionsLoading)
96+
const { userPermissions, permissionsLoading } = useWorkspacePermissionsContext()
10097

10198
const handleUploadClick = () => {
10299
fileInputRef.current?.click()

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workspace-header/components/invite-modal/components/permissions-table.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Badge, Button, Tooltip } from '@/components/emcn'
44
import { useSession } from '@/lib/auth/auth-client'
55
import type { PermissionType } from '@/lib/workspaces/permissions/utils'
66
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
7-
import type { WorkspacePermissions } from '@/hooks/use-workspace-permissions'
7+
import type { WorkspacePermissions } from '@/hooks/queries/workspace'
88
import { PermissionSelector } from './permission-selector'
99
import { PermissionsTableSkeleton } from './permissions-table-skeleton'
1010
import type { UserPermissions } from './types'
@@ -14,7 +14,7 @@ export interface PermissionsTableProps {
1414
onPermissionChange: (userId: string, permissionType: PermissionType) => void
1515
onRemoveMember?: (userId: string, email: string) => void
1616
onRemoveInvitation?: (invitationId: string, email: string) => void
17-
onResendInvitation?: (invitationId: string, email: string) => void
17+
onResendInvitation?: (invitationId: string) => void
1818
disabled?: boolean
1919
existingUserPermissionChanges: Record<string, Partial<UserPermissions>>
2020
isSaving?: boolean
@@ -143,7 +143,6 @@ export const PermissionsTable = ({
143143
<div>
144144
{allUsers.map((user) => {
145145
const isCurrentUser = user.isCurrentUser === true
146-
const isExistingUser = filteredExistingUsers.some((eu) => eu.email === user.email)
147146
const isPendingInvitation = user.isPendingInvitation === true
148147
const userIdentifier = user.userId || user.email
149148
const originalPermission = workspacePermissions?.users?.find(
@@ -205,7 +204,7 @@ export const PermissionsTable = ({
205204
<span className='inline-flex'>
206205
<Button
207206
variant='ghost'
208-
onClick={() => onResendInvitation(user.invitationId!, user.email)}
207+
onClick={() => onResendInvitation(user.invitationId!)}
209208
disabled={
210209
disabled ||
211210
isSaving ||

0 commit comments

Comments
 (0)