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
13 changes: 13 additions & 0 deletions apps/sim/app/playground/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
Cursor,
DatePicker,
DocumentAttachment,
Download,
Duplicate,
Expand,
Eye,
Expand Down Expand Up @@ -51,6 +52,7 @@ import {
NoWrap,
PanelLeft,
Play,
PlayOutline,
Popover,
PopoverBackButton,
PopoverContent,
Expand Down Expand Up @@ -214,6 +216,9 @@ export default function PlaygroundPage() {
<VariantRow label='primary'>
<Button variant='primary'>Primary</Button>
</VariantRow>
<VariantRow label='destructive'>
<Button variant='destructive'>Destructive</Button>
</VariantRow>
<VariantRow label='secondary'>
<Button variant='secondary'>Secondary</Button>
</VariantRow>
Expand Down Expand Up @@ -290,6 +295,9 @@ export default function PlaygroundPage() {
<VariantRow label='outline'>
<Badge variant='outline'>Outline</Badge>
</VariantRow>
<VariantRow label='type'>
<Badge variant='type'>Type</Badge>
</VariantRow>
<VariantRow label='green'>
<Badge variant='green'>Green</Badge>
<Badge variant='green' dot>
Expand Down Expand Up @@ -323,6 +331,9 @@ export default function PlaygroundPage() {
<VariantRow label='teal'>
<Badge variant='teal'>Teal</Badge>
</VariantRow>
<VariantRow label='cyan'>
<Badge variant='cyan'>Cyan</Badge>
</VariantRow>
<VariantRow label='gray'>
<Badge variant='gray'>Gray</Badge>
</VariantRow>
Expand Down Expand Up @@ -996,6 +1007,7 @@ export default function PlaygroundPage() {
{ Icon: Copy, name: 'Copy' },
{ Icon: Cursor, name: 'Cursor' },
{ Icon: DocumentAttachment, name: 'DocumentAttachment' },
{ Icon: Download, name: 'Download' },
{ Icon: Duplicate, name: 'Duplicate' },
{ Icon: Expand, name: 'Expand' },
{ Icon: Eye, name: 'Eye' },
Expand All @@ -1011,6 +1023,7 @@ export default function PlaygroundPage() {
{ Icon: NoWrap, name: 'NoWrap' },
{ Icon: PanelLeft, name: 'PanelLeft' },
{ Icon: Play, name: 'Play' },
{ Icon: PlayOutline, name: 'PlayOutline' },
{ Icon: Redo, name: 'Redo' },
{ Icon: Rocket, name: 'Rocket' },
{ Icon: Trash, name: 'Trash' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
>({})
const [isSubmitting, setIsSubmitting] = useState(false)
const [isSaving, setIsSaving] = useState(false)
const [showSent, setShowSent] = useState(false)
const cooldownIntervalsRef = useRef<Map<string, NodeJS.Timeout>>(new Map())
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [successMessage, setSuccessMessage] = useState<string | null>(null)
const [memberToRemove, setMemberToRemove] = useState<{ userId: string; email: string } | null>(
null
)
Expand Down Expand Up @@ -121,10 +120,17 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
useEffect(() => {
if (open) {
setErrorMessage(null)
setSuccessMessage(null)
}
}, [open])

useEffect(() => {
const intervalsRef = cooldownIntervalsRef.current
return () => {
intervalsRef.forEach((interval) => clearInterval(interval))
intervalsRef.clear()
}
}, [])

const addEmail = useCallback(
(email: string) => {
if (!email.trim()) return false
Expand Down Expand Up @@ -255,11 +261,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
}

setExistingUserPermissionChanges({})

setSuccessMessage(
`Permission changes saved for ${updates.length} user${updates.length !== 1 ? 's' : ''}!`
)
setTimeout(() => setSuccessMessage(null), 3000)
} catch (error) {
logger.error('Error saving permission changes:', error)
const errorMsg =
Expand All @@ -282,9 +283,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
if (!userPerms.canAdmin || !hasPendingChanges) return

setExistingUserPermissionChanges({})
setSuccessMessage('Changes restored to original permissions!')

setTimeout(() => setSuccessMessage(null), 3000)
}, [userPerms.canAdmin, hasPendingChanges])

const handleRemoveMemberClick = useCallback((userId: string, email: string) => {
Expand Down Expand Up @@ -337,9 +335,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
delete updated[memberToRemove.userId]
return updated
})

setSuccessMessage(`${memberToRemove.email} has been removed from the workspace`)
setTimeout(() => setSuccessMessage(null), 3000)
} catch (error) {
logger.error('Error removing member:', error)
const errorMsg =
Expand Down Expand Up @@ -385,9 +380,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
setPendingInvitations((prev) =>
prev.filter((inv) => inv.invitationId !== invitationToRemove.invitationId)
)

setSuccessMessage(`Invitation for ${invitationToRemove.email} has been cancelled`)
setTimeout(() => setSuccessMessage(null), 3000)
} catch (error) {
logger.error('Error cancelling invitation:', error)
const errorMsg =
Expand Down Expand Up @@ -427,9 +419,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
throw new Error(data.error || 'Failed to resend invitation')
}

setSuccessMessage(`Invitation resent to ${email}`)
setTimeout(() => setSuccessMessage(null), 3000)

setResentInvitationIds((prev) => ({ ...prev, [invitationId]: true }))
setTimeout(() => {
setResentInvitationIds((prev) => {
Expand All @@ -450,6 +439,12 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
return next
})
setResendCooldowns((prev) => ({ ...prev, [invitationId]: 60 }))

const existingInterval = cooldownIntervalsRef.current.get(invitationId)
if (existingInterval) {
clearInterval(existingInterval)
}

const interval = setInterval(() => {
setResendCooldowns((prev) => {
const current = prev[invitationId]
Expand All @@ -458,11 +453,14 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
const next = { ...prev }
delete next[invitationId]
clearInterval(interval)
cooldownIntervalsRef.current.delete(invitationId)
return next
}
return { ...prev, [invitationId]: current - 1 }
})
}, 1000)

cooldownIntervalsRef.current.set(invitationId, interval)
}
},
[workspaceId, userPerms.canAdmin, resendCooldowns]
Expand All @@ -473,7 +471,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
e.preventDefault()

setErrorMessage(null)
setSuccessMessage(null)

if (validEmails.length === 0 || !workspaceId) {
return
Expand Down Expand Up @@ -562,11 +559,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
setEmailItems([])
setUserPermissions([])
}
setShowSent(true)

setTimeout(() => {
setShowSent(false)
}, 4000)
}
} catch (err) {
logger.error('Error inviting members:', err)
Expand All @@ -588,13 +580,16 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
setExistingUserPermissionChanges({})
setIsSubmitting(false)
setIsSaving(false)
setShowSent(false)
setErrorMessage(null)
setSuccessMessage(null)
setMemberToRemove(null)
setIsRemovingMember(false)
setInvitationToRemove(null)
setIsRemovingInvitation(false)
setResendCooldowns({})
setResentInvitationIds({})

cooldownIntervalsRef.current.forEach((interval) => clearInterval(interval))
cooldownIntervalsRef.current.clear()
}, [])

return (
Expand Down Expand Up @@ -703,7 +698,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
variant='default'
disabled={isSaving || isSubmitting}
onClick={handleRestoreChanges}
className='h-[32px] gap-[8px] px-[12px] font-medium'
>
Restore Changes
</Button>
Expand All @@ -712,7 +706,6 @@ export function InviteModal({ open, onOpenChange, workspaceName }: InviteModalPr
variant='tertiary'
disabled={isSaving || isSubmitting}
onClick={handleSaveChanges}
className='h-[32px] gap-[8px] px-[12px] font-medium'
>
{isSaving ? 'Saving...' : 'Save Changes'}
</Button>
Expand Down