Skip to content

Commit e6c511a

Browse files
waleedlatif1claude
andcommitted
feat: add task multi-select, context menu, and subscription UI updates
Add shift-click range selection, cmd/ctrl-click toggle, and right-click context menu for tasks in sidebar matching workflow/folder patterns. Update subscription settings tab UI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a1f917d commit e6c511a

File tree

12 files changed

+419
-155
lines changed

12 files changed

+419
-155
lines changed

apps/sim/app/workspace/[workspaceId]/settings/components/subscription/components/credit-balance/credit-balance.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export function CreditBalance({
103103
{canPurchase && (
104104
<Modal open={isOpen} onOpenChange={handleOpenChange}>
105105
<ModalTrigger asChild>
106-
<Button variant='active' className='h-[32px] rounded-[6px] text-[13px]'>
106+
<Button variant='default' className='h-[32px] text-[13px]'>
107107
Add Credits
108108
</Button>
109109
</ModalTrigger>

apps/sim/app/workspace/[workspaceId]/settings/components/subscription/components/plan-card/plan-card.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ export function PlanCard({
131131
</ul>
132132
<Button
133133
onClick={onButtonClick}
134-
className={cn(!inlineButton && 'w-full')}
134+
className={cn(inlineButton ? 'shrink-0 whitespace-nowrap' : 'w-full')}
135135
variant={isError ? 'outline' : 'tertiary'}
136136
aria-label={`${buttonText} ${name} plan`}
137137
>

apps/sim/app/workspace/[workspaceId]/settings/components/subscription/components/referral-code/referral-code.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export function ReferralCode({ onRedeemComplete }: ReferralCodeProps) {
4444
}
4545

4646
return (
47-
<div className='flex flex-col'>
47+
<div className='flex flex-col gap-[4px]'>
4848
<div className='flex items-center justify-between gap-[12px]'>
4949
<Label className='shrink-0'>Referral Code</Label>
5050
<div className='flex items-center gap-[8px]'>
@@ -59,24 +59,24 @@ export function ReferralCode({ onRedeemComplete }: ReferralCodeProps) {
5959
if (e.key === 'Enter') handleRedeem()
6060
}}
6161
placeholder='Enter code'
62-
className='h-[32px] w-[140px] text-[13px]'
62+
className='h-[32px] w-[140px] bg-[var(--surface-4)] text-[13px]'
6363
disabled={redeemCode.isPending}
6464
/>
6565
<Button
66-
variant='active'
67-
className='h-[32px] shrink-0 rounded-[6px] text-[13px]'
66+
variant='default'
67+
className='h-[32px] shrink-0 text-[13px]'
6868
onClick={handleRedeem}
6969
disabled={redeemCode.isPending || !code.trim()}
7070
>
7171
{redeemCode.isPending ? 'Redeeming...' : 'Redeem'}
7272
</Button>
7373
</div>
7474
</div>
75-
<div className='mt-[4px] min-h-[18px] text-right'>
76-
{redeemCode.error && (
77-
<span className='text-[11px] text-[var(--text-error)]'>{redeemCode.error.message}</span>
78-
)}
79-
</div>
75+
{redeemCode.error && (
76+
<span className='text-right text-[11px] text-[var(--text-error)]'>
77+
{redeemCode.error.message}
78+
</span>
79+
)}
8080
</div>
8181
)
8282
}

apps/sim/app/workspace/[workspaceId]/settings/components/subscription/plan-configs.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
HeadphonesIcon,
55
Server,
66
ShieldCheck,
7+
Table2,
78
Timer,
89
Users,
910
Zap,
@@ -16,19 +17,22 @@ export const PRO_PLAN_FEATURES: PlanFeature[] = [
1617
{ icon: Clock, text: '1,000 runs/min (async)' },
1718
{ icon: Timer, text: '50 min sync execution limit' },
1819
{ icon: HardDrive, text: '50GB file storage' },
20+
{ icon: Table2, text: '25 tables · 5,000 rows each' },
1921
]
2022

2123
export const MAX_PLAN_FEATURES: PlanFeature[] = [
2224
{ icon: Zap, text: '300 runs/min (sync)' },
2325
{ icon: Clock, text: '2,500 runs/min (async)' },
2426
{ icon: Timer, text: '50 min sync execution limit' },
2527
{ icon: HardDrive, text: '500GB file storage' },
28+
{ icon: Table2, text: '25 tables · 5,000 rows each' },
2629
]
2730

2831
export const TEAM_INLINE_FEATURES: PlanFeature[] = [
2932
{ icon: Users, text: 'Shared credit pool' },
3033
{ icon: Zap, text: 'Max plan rate limits' },
3134
{ icon: HardDrive, text: 'Max plan file storage' },
35+
{ icon: Table2, text: '100 tables · 10,000 rows each' },
3236
{ icon: ShieldCheck, text: 'Access controls' },
3337
{ icon: SlackMonoIcon, text: 'Dedicated Slack channel' },
3438
]

apps/sim/app/workspace/[workspaceId]/settings/components/subscription/subscription.tsx

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -912,80 +912,82 @@ export function Subscription() {
912912
/>
913913

914914
{/* Billing details section */}
915-
<div className='flex flex-col gap-[14px] rounded-[6px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[14px] py-[12px]'>
916-
{subscription.isPaid && permissions.canViewUsageInfo && (
917-
<CreditBalance
918-
balance={subscriptionData?.data?.creditBalance ?? 0}
919-
canPurchase={permissions.canEditUsageLimit}
920-
entityType={subscription.isTeam || subscription.isEnterprise ? 'organization' : 'user'}
921-
isLoading={isLoading}
922-
onPurchaseComplete={() => refetchSubscription()}
923-
/>
924-
)}
915+
{(subscription.isPaid || (!isLoading && isTeamAdmin)) && (
916+
<div className='flex flex-col gap-[14px] rounded-[6px] border border-[var(--border-1)] bg-[var(--surface-5)] px-[14px] py-[12px]'>
917+
{subscription.isPaid && permissions.canViewUsageInfo && (
918+
<CreditBalance
919+
balance={subscriptionData?.data?.creditBalance ?? 0}
920+
canPurchase={permissions.canEditUsageLimit}
921+
entityType={
922+
subscription.isTeam || subscription.isEnterprise ? 'organization' : 'user'
923+
}
924+
isLoading={isLoading}
925+
onPurchaseComplete={() => refetchSubscription()}
926+
/>
927+
)}
925928

926-
{!subscription.isEnterprise && (
927-
<ReferralCode onRedeemComplete={() => refetchSubscription()} />
928-
)}
929+
{subscription.isPaid &&
930+
subscriptionData?.data?.periodEnd &&
931+
!permissions.showTeamMemberView &&
932+
!permissions.isEnterpriseMember && (
933+
<div className='flex items-center justify-between'>
934+
<Label>{isCancelledAtPeriodEnd ? 'Access Until' : 'Next Billing Date'}</Label>
935+
<span className='text-[13px] text-[var(--text-secondary)]'>
936+
{new Date(subscriptionData.data.periodEnd).toLocaleDateString()}
937+
</span>
938+
</div>
939+
)}
929940

930-
{subscription.isPaid &&
931-
subscriptionData?.data?.periodEnd &&
932-
!permissions.showTeamMemberView &&
933-
!permissions.isEnterpriseMember && (
934-
<div className='flex items-center justify-between'>
935-
<Label>{isCancelledAtPeriodEnd ? 'Access Until' : 'Next Billing Date'}</Label>
936-
<span className='text-[13px] text-[var(--text-secondary)]'>
937-
{new Date(subscriptionData.data.periodEnd).toLocaleDateString()}
938-
</span>
939-
</div>
941+
{subscription.isPaid && permissions.canViewUsageInfo && (
942+
<BillingUsageNotificationsToggle />
940943
)}
941944

942-
{subscription.isPaid && permissions.canViewUsageInfo && <BillingUsageNotificationsToggle />}
943-
944-
{!isLoading && isTeamAdmin && (
945-
<div className='flex items-center justify-between'>
946-
<div className='flex items-center gap-[6px]'>
947-
<Label htmlFor='billed-account'>Billed Account</Label>
948-
<Tooltip.Root>
949-
<Tooltip.Trigger asChild>
950-
<Info className='h-[12px] w-[12px] text-[var(--text-secondary)]' />
951-
</Tooltip.Trigger>
952-
<Tooltip.Content>
953-
<span>Usage from this workspace will be billed to this account</span>
954-
</Tooltip.Content>
955-
</Tooltip.Root>
956-
</div>
957-
{workspaceAdmins.length === 0 ? (
958-
<div className='rounded-[6px] border border-[var(--border)] border-dashed px-[12px] py-[6px] text-[13px] text-[var(--text-muted)]'>
959-
No admins available
945+
{!isLoading && isTeamAdmin && (
946+
<div className='flex items-center justify-between'>
947+
<div className='flex items-center gap-[6px]'>
948+
<Label htmlFor='billed-account'>Billed Account</Label>
949+
<Tooltip.Root>
950+
<Tooltip.Trigger asChild>
951+
<Info className='h-[12px] w-[12px] text-[var(--text-secondary)]' />
952+
</Tooltip.Trigger>
953+
<Tooltip.Content>
954+
<span>Usage from this workspace will be billed to this account</span>
955+
</Tooltip.Content>
956+
</Tooltip.Root>
960957
</div>
961-
) : (
962-
<div className='w-[200px]'>
963-
<Combobox
964-
size='sm'
965-
align='end'
966-
dropdownWidth={200}
967-
value={billedAccountUserId || ''}
968-
onChange={async (value: string) => {
969-
if (value && value !== billedAccountUserId) {
970-
try {
971-
await updateWorkspaceSettings({ billedAccountUserId: value })
972-
} catch {
973-
/* logged above */
958+
{workspaceAdmins.length === 0 ? (
959+
<div className='rounded-[6px] border border-[var(--border)] border-dashed px-[12px] py-[6px] text-[13px] text-[var(--text-muted)]'>
960+
No admins available
961+
</div>
962+
) : (
963+
<div className='w-[200px]'>
964+
<Combobox
965+
size='sm'
966+
align='end'
967+
dropdownWidth={200}
968+
value={billedAccountUserId || ''}
969+
onChange={async (value: string) => {
970+
if (value && value !== billedAccountUserId) {
971+
try {
972+
await updateWorkspaceSettings({ billedAccountUserId: value })
973+
} catch {
974+
/* logged above */
975+
}
974976
}
975-
}
976-
}}
977-
disabled={!canManageWorkspaceKeys || updateWorkspaceMutation.isPending}
978-
placeholder='Select admin'
979-
options={workspaceAdmins.map((admin) => ({
980-
label: admin.email,
981-
value: admin.userId,
982-
}))}
983-
/>
984-
</div>
985-
)}
986-
</div>
987-
)}
988-
</div>
977+
}}
978+
disabled={!canManageWorkspaceKeys || updateWorkspaceMutation.isPending}
979+
placeholder='Select admin'
980+
options={workspaceAdmins.map((admin) => ({
981+
label: admin.email,
982+
value: admin.userId,
983+
}))}
984+
/>
985+
</div>
986+
)}
987+
</div>
988+
)}
989+
</div>
990+
)}
989991

990992
{/* Enterprise */}
991993
{hasEnterprise && (
@@ -998,6 +1000,11 @@ export function Subscription() {
9981000
inlineButton
9991001
/>
10001002
)}
1003+
1004+
{/* Referral Code */}
1005+
{!subscription.isEnterprise && (
1006+
<ReferralCode onRedeemComplete={() => refetchSubscription()} />
1007+
)}
10011008
</div>
10021009
)
10031010
}

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/nav-item-context-menu/nav-item-context-menu.tsx

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ interface NavItemContextMenuProps {
99
onClose: () => void
1010
onOpenInNewTab: () => void
1111
onCopyLink: () => void
12-
onRename?: () => void
13-
onDelete?: () => void
14-
disableRename?: boolean
15-
disableDelete?: boolean
1612
}
1713

1814
export function NavItemContextMenu({
@@ -22,10 +18,6 @@ export function NavItemContextMenu({
2218
onClose,
2319
onOpenInNewTab,
2420
onCopyLink,
25-
onRename,
26-
onDelete,
27-
disableRename = false,
28-
disableDelete = false,
2921
}: NavItemContextMenuProps) {
3022
return (
3123
<Popover
@@ -61,29 +53,6 @@ export function NavItemContextMenu({
6153
>
6254
Copy link
6355
</PopoverItem>
64-
{onRename && (
65-
<PopoverItem
66-
onClick={() => {
67-
onRename()
68-
onClose()
69-
}}
70-
disabled={disableRename}
71-
>
72-
Rename
73-
</PopoverItem>
74-
)}
75-
{onDelete && (
76-
<PopoverItem
77-
onClick={() => {
78-
onDelete()
79-
onClose()
80-
}}
81-
disabled={disableDelete}
82-
className='text-[var(--color-error)]'
83-
>
84-
Delete
85-
</PopoverItem>
86-
)}
8756
</PopoverContent>
8857
</Popover>
8958
)

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/components/workflow-list/components/delete-modal/delete-modal.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface DeleteModalProps {
2323
* Type of item being deleted
2424
* - 'mixed' is used when both workflows and folders are selected
2525
*/
26-
itemType: 'workflow' | 'folder' | 'workspace' | 'mixed'
26+
itemType: 'workflow' | 'folder' | 'workspace' | 'mixed' | 'task'
2727
/**
2828
* Name(s) of the item(s) being deleted (optional, for display)
2929
* Can be a single name or an array of names for multiple items
@@ -56,6 +56,8 @@ export function DeleteModal({
5656
title = isMultiple ? 'Delete Workflows' : 'Delete Workflow'
5757
} else if (itemType === 'folder') {
5858
title = isMultiple ? 'Delete Folders' : 'Delete Folder'
59+
} else if (itemType === 'task') {
60+
title = isMultiple ? 'Delete Tasks' : 'Delete Task'
5961
} else if (itemType === 'mixed') {
6062
title = 'Delete Items'
6163
} else {
@@ -112,6 +114,30 @@ export function DeleteModal({
112114
return 'Are you sure you want to delete this folder? This will permanently remove all associated workflows, logs, and knowledge bases.'
113115
}
114116

117+
if (itemType === 'task') {
118+
if (isMultiple) {
119+
return (
120+
<>
121+
Are you sure you want to delete{' '}
122+
<span className='font-medium text-[var(--text-primary)]'>
123+
{displayNames.length} tasks
124+
</span>
125+
? This will permanently remove all conversation history.
126+
</>
127+
)
128+
}
129+
if (isSingle && displayNames.length > 0) {
130+
return (
131+
<>
132+
Are you sure you want to delete{' '}
133+
<span className='font-medium text-[var(--text-primary)]'>{displayNames[0]}</span>? This
134+
will permanently remove all conversation history.
135+
</>
136+
)
137+
}
138+
return 'Are you sure you want to delete this task? This will permanently remove all conversation history.'
139+
}
140+
115141
if (itemType === 'mixed') {
116142
if (displayNames.length > 0) {
117143
return (

apps/sim/app/workspace/[workspaceId]/w/components/sidebar/hooks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export {
1212
useSidebarDragContextValue,
1313
} from './use-sidebar-drag-context'
1414
export { useSidebarResize } from './use-sidebar-resize'
15+
export { useTaskSelection } from './use-task-selection'
1516
export { useWorkflowOperations } from './use-workflow-operations'
1617
export { useWorkflowSelection } from './use-workflow-selection'
1718
export { useWorkspaceManagement, type Workspace } from './use-workspace-management'

0 commit comments

Comments
 (0)