Skip to content

Commit 016d353

Browse files
committed
improvement: icon, resource header options
1 parent d9c1a53 commit 016d353

File tree

6 files changed

+147
-17
lines changed

6 files changed

+147
-17
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export { ownerCell } from './resource/components/owner-cell/owner-cell'
33
export type {
44
BreadcrumbItem,
55
CreateAction,
6+
DropdownOption,
67
HeaderAction,
78
} from './resource/components/resource-header'
89
export { ResourceHeader } from './resource/components/resource-header'
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
export type { BreadcrumbItem, CreateAction, HeaderAction } from './resource-header'
1+
export type { BreadcrumbItem, CreateAction, DropdownOption, HeaderAction } from './resource-header'
22
export { ResourceHeader } from './resource-header'

apps/sim/app/workspace/[workspaceId]/components/resource/components/resource-header/resource-header.tsx

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
11
import { Fragment } from 'react'
2-
import { Button, Plus } from '@/components/emcn'
2+
import {
3+
Button,
4+
ChevronDown,
5+
DropdownMenu,
6+
DropdownMenuContent,
7+
DropdownMenuItem,
8+
DropdownMenuTrigger,
9+
Plus,
10+
} from '@/components/emcn'
311
import { cn } from '@/lib/core/utils/cn'
412

13+
export interface DropdownOption {
14+
label: string
15+
icon?: React.ElementType
16+
onClick: () => void
17+
disabled?: boolean
18+
}
19+
520
export interface BreadcrumbItem {
621
label: string
722
onClick?: () => void
23+
dropdownItems?: DropdownOption[]
824
}
925

1026
export interface HeaderAction {
1127
label: string
1228
icon?: React.ElementType
1329
onClick: () => void
30+
disabled?: boolean
1431
}
1532

1633
export interface CreateAction {
@@ -55,6 +72,7 @@ export function ResourceHeader({
5572
icon={i === 0 ? Icon : undefined}
5673
label={crumb.label}
5774
onClick={crumb.onClick}
75+
dropdownItems={crumb.dropdownItems}
5876
/>
5977
</Fragment>
6078
))
@@ -74,6 +92,7 @@ export function ResourceHeader({
7492
<Button
7593
key={action.label}
7694
onClick={action.onClick}
95+
disabled={action.disabled}
7796
variant='subtle'
7897
className='px-[8px] py-[4px] text-[12px]'
7998
>
@@ -103,10 +122,12 @@ function BreadcrumbSegment({
103122
icon: Icon,
104123
label,
105124
onClick,
125+
dropdownItems,
106126
}: {
107127
icon?: React.ElementType
108128
label: string
109129
onClick?: () => void
130+
dropdownItems?: DropdownOption[]
110131
}) {
111132
const content = (
112133
<>
@@ -115,6 +136,30 @@ function BreadcrumbSegment({
115136
</>
116137
)
117138

139+
if (dropdownItems && dropdownItems.length > 0) {
140+
return (
141+
<DropdownMenu>
142+
<DropdownMenuTrigger asChild>
143+
<Button variant='subtle' className='px-[8px] py-[4px] font-medium text-[14px]'>
144+
{content}
145+
<ChevronDown className='ml-[8px] h-[7px] w-[9px] shrink-0 text-[var(--text-muted)]' />
146+
</Button>
147+
</DropdownMenuTrigger>
148+
<DropdownMenuContent align='start'>
149+
{dropdownItems.map((item) => {
150+
const ItemIcon = item.icon
151+
return (
152+
<DropdownMenuItem key={item.label} onClick={item.onClick} disabled={item.disabled}>
153+
{ItemIcon && <ItemIcon className='h-[14px] w-[14px]' />}
154+
{item.label}
155+
</DropdownMenuItem>
156+
)
157+
})}
158+
</DropdownMenuContent>
159+
</DropdownMenu>
160+
)
161+
}
162+
118163
if (onClick) {
119164
return (
120165
<Button

apps/sim/app/workspace/[workspaceId]/files/files.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ import {
1212
ModalContent,
1313
ModalFooter,
1414
ModalHeader,
15+
Pencil,
1516
Popover,
1617
PopoverAnchor,
1718
PopoverContent,
1819
PopoverDivider,
1920
PopoverItem,
2021
Skeleton,
21-
Trash2,
22+
Trash,
2223
Upload,
2324
} from '@/components/emcn'
2425
import { getDocumentIcon } from '@/components/icons/document-icons'
@@ -425,6 +426,10 @@ export function Files() {
425426
{
426427
label: saveLabel,
427428
onClick: handleSave,
429+
disabled:
430+
(!isDirty && saveStatus === 'idle') ||
431+
saveStatus === 'saving' ||
432+
saveStatus === 'saved',
428433
},
429434
]
430435
: []),
@@ -435,7 +440,7 @@ export function Files() {
435440
},
436441
{
437442
label: 'Delete',
438-
icon: Trash2,
443+
icon: Trash,
439444
onClick: () => {
440445
setDeleteTargetFile(selectedFile)
441446
setShowDeleteConfirm(true)
@@ -450,7 +455,25 @@ export function Files() {
450455
icon={FilesIcon}
451456
breadcrumbs={[
452457
{ label: 'Files', onClick: handleBackAttempt },
453-
{ label: selectedFile.name },
458+
{
459+
label: selectedFile.name,
460+
dropdownItems: [
461+
{ label: 'Rename', icon: Pencil, onClick: () => {} },
462+
{
463+
label: 'Download',
464+
icon: Download,
465+
onClick: () => handleDownload(selectedFile),
466+
},
467+
{
468+
label: 'Delete',
469+
icon: Trash,
470+
onClick: () => {
471+
setDeleteTargetFile(selectedFile)
472+
setShowDeleteConfirm(true)
473+
},
474+
},
475+
],
476+
},
454477
]}
455478
actions={fileActions}
456479
/>

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table/table.tsx

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ import {
1313
DropdownMenuSubContent,
1414
DropdownMenuSubTrigger,
1515
DropdownMenuTrigger,
16+
Modal,
17+
ModalBody,
18+
ModalContent,
19+
ModalFooter,
20+
ModalHeader,
1621
Skeleton,
1722
} from '@/components/emcn'
1823
import {
@@ -38,7 +43,12 @@ import type {
3843
ColumnOption,
3944
SortConfig,
4045
} from '@/app/workspace/[workspaceId]/components/resource/components/resource-options-bar'
41-
import { useAddTableColumn, useCreateTableRow, useUpdateTableRow } from '@/hooks/queries/tables'
46+
import {
47+
useAddTableColumn,
48+
useCreateTableRow,
49+
useDeleteTable,
50+
useUpdateTableRow,
51+
} from '@/hooks/queries/tables'
4252
import { useContextMenu, useRowSelection, useTableData } from '../../hooks'
4353
import type { EditingCell, QueryOptions } from '../../types'
4454
import { cleanCellValue, formatValueForInput } from '../../utils'
@@ -138,6 +148,7 @@ export function Table() {
138148
rowIndex: number
139149
columnName: string
140150
} | null>(null)
151+
const [showDeleteTableConfirm, setShowDeleteTableConfirm] = useState(false)
141152

142153
const isDraggingRef = useRef(false)
143154

@@ -217,10 +228,22 @@ export function Table() {
217228
selectionFocusRef.current = selectionFocus
218229
}, [selectionFocus])
219230

231+
const deleteTableMutation = useDeleteTable(workspaceId)
232+
220233
const handleNavigateBack = useCallback(() => {
221234
router.push(`/workspace/${workspaceId}/tables`)
222235
}, [router, workspaceId])
223236

237+
const handleDeleteTable = useCallback(async () => {
238+
try {
239+
await deleteTableMutation.mutateAsync(tableId)
240+
setShowDeleteTableConfirm(false)
241+
router.push(`/workspace/${workspaceId}/tables`)
242+
} catch {
243+
setShowDeleteTableConfirm(false)
244+
}
245+
}, [deleteTableMutation, tableId, router, workspaceId])
246+
224247
const handleAddRow = useCallback(() => {
225248
setShowAddModal(true)
226249
}, [])
@@ -603,7 +626,21 @@ export function Table() {
603626
icon={TableIcon}
604627
breadcrumbs={[
605628
{ label: 'Tables', onClick: handleNavigateBack },
606-
...(tableData ? [{ label: tableData.name }] : []),
629+
...(tableData
630+
? [
631+
{
632+
label: tableData.name,
633+
dropdownItems: [
634+
{ label: 'Rename', icon: Pencil, onClick: () => {} },
635+
{
636+
label: 'Delete',
637+
icon: Trash,
638+
onClick: () => setShowDeleteTableConfirm(true),
639+
},
640+
],
641+
},
642+
]
643+
: []),
607644
]}
608645
/>
609646

@@ -786,6 +823,35 @@ export function Table() {
786823
onEdit={handleContextMenuEdit}
787824
onDelete={handleContextMenuDelete}
788825
/>
826+
827+
<Modal open={showDeleteTableConfirm} onOpenChange={setShowDeleteTableConfirm}>
828+
<ModalContent size='sm'>
829+
<ModalHeader>Delete Table</ModalHeader>
830+
<ModalBody>
831+
<p className='text-[13px] text-[var(--text-secondary)]'>
832+
Are you sure you want to delete{' '}
833+
<span className='font-medium text-[var(--text-primary)]'>{tableData?.name}</span>?{' '}
834+
<span className='text-[var(--text-error)]'>This action cannot be undone.</span>
835+
</p>
836+
</ModalBody>
837+
<ModalFooter>
838+
<Button
839+
variant='default'
840+
onClick={() => setShowDeleteTableConfirm(false)}
841+
disabled={deleteTableMutation.isPending}
842+
>
843+
Cancel
844+
</Button>
845+
<Button
846+
variant='destructive'
847+
onClick={handleDeleteTable}
848+
disabled={deleteTableMutation.isPending}
849+
>
850+
{deleteTableMutation.isPending ? 'Deleting...' : 'Delete'}
851+
</Button>
852+
</ModalFooter>
853+
</ModalContent>
854+
</Modal>
789855
</div>
790856
)
791857
}

apps/sim/public/icon.svg

Lines changed: 5 additions & 10 deletions
Loading

0 commit comments

Comments
 (0)