Skip to content

Commit 02c0d75

Browse files
saltcodjoshenlim
andauthored
Add comboboxes to the index side panel dropdowns (supabase#25821)
* Add comboboxes to the index side panel dropdowns * Add loading state for create index panel select a table field * Add placehholder for columns field in create index side panel --------- Co-authored-by: Joshen Lim <[email protected]>
1 parent c7678d1 commit 02c0d75

File tree

2 files changed

+140
-44
lines changed

2 files changed

+140
-44
lines changed

apps/studio/components/interfaces/Database/Indexes/CreateIndexSidePanel.tsx

Lines changed: 139 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import Link from 'next/link'
22
import { useEffect, useMemo, useState } from 'react'
33
import toast from 'react-hot-toast'
44

5-
import { SelectValue } from '@ui/components/shadcn/ui/select'
65
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
76
import { CodeEditor } from 'components/ui/CodeEditor'
87
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
@@ -11,18 +10,30 @@ import { useSchemasQuery } from 'data/database/schemas-query'
1110
import { useTableColumnsQuery } from 'data/database/table-columns-query'
1211
import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query'
1312
import { useExecuteSqlMutation } from 'data/sql/execute-sql-mutation'
13+
import { Check, ChevronsUpDown } from 'lucide-react'
1414
import {
1515
Button,
16-
Input,
16+
CommandEmpty_Shadcn_,
17+
CommandGroup_Shadcn_,
18+
CommandInput_Shadcn_,
19+
CommandItem_Shadcn_,
20+
CommandList_Shadcn_,
21+
Command_Shadcn_,
22+
PopoverContent_Shadcn_,
23+
PopoverTrigger_Shadcn_,
24+
Popover_Shadcn_,
25+
ScrollArea,
1726
SelectContent_Shadcn_,
1827
SelectItem_Shadcn_,
1928
SelectSeparator_Shadcn_,
2029
SelectTrigger_Shadcn_,
2130
SelectValue_Shadcn_,
2231
Select_Shadcn_,
2332
SidePanel,
33+
cn,
2434
} from 'ui'
25-
import MultiSelect, { MultiSelectOption } from 'ui-patterns/MultiSelect'
35+
import { MultiSelectOption } from 'ui-patterns/MultiSelect'
36+
import { MultiSelectV2 } from 'ui-patterns/MultiSelect/MultiSelectV2'
2637
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
2738
import { INDEX_TYPES } from './Indexes.constants'
2839

@@ -37,6 +48,8 @@ const CreateIndexSidePanel = ({ visible, onClose }: CreateIndexSidePanelProps) =
3748
const [selectedEntity, setSelectedEntity] = useState<string | undefined>(undefined)
3849
const [selectedColumns, setSelectedColumns] = useState<string[]>([])
3950
const [selectedIndexType, setSelectedIndexType] = useState<string>(INDEX_TYPES[0].value)
51+
const [schemaDropdownOpen, setSchemaDropdownOpen] = useState(false)
52+
const [tableDropdownOpen, setTableDropdownOpen] = useState(false)
4053

4154
const { refetch: refetchIndexes } = useIndexesQuery({
4255
schema: selectedSchema,
@@ -47,7 +60,7 @@ const CreateIndexSidePanel = ({ visible, onClose }: CreateIndexSidePanelProps) =
4760
projectRef: project?.ref,
4861
connectionString: project?.connectionString,
4962
})
50-
const { data: entities } = useEntityTypesQuery({
63+
const { data: entities, isLoading } = useEntityTypesQuery({
5164
schema: selectedSchema,
5265
sort: 'alphabetical',
5366
search: undefined,
@@ -136,65 +149,148 @@ CREATE INDEX ON "${selectedSchema}"."${selectedEntity}" USING ${selectedIndexTyp
136149
<div className="py-6 space-y-6">
137150
<SidePanel.Content className="space-y-6">
138151
<FormItemLayout label="Select a schema" name="select-schema" isReactForm={false}>
139-
<Select_Shadcn_
140-
value={selectedSchema}
141-
onValueChange={setSelectedSchema}
142-
name="select-schema"
152+
<Popover_Shadcn_
153+
modal={false}
154+
open={schemaDropdownOpen}
155+
onOpenChange={setSchemaDropdownOpen}
143156
>
144-
<SelectTrigger_Shadcn_ size="small">
145-
<SelectValue_Shadcn_>{selectedSchema}</SelectValue_Shadcn_>
146-
</SelectTrigger_Shadcn_>
147-
<SelectContent_Shadcn_>
148-
{(schemas ?? []).map((schema) => (
149-
<SelectItem_Shadcn_ key={schema.name} value={schema.name}>
150-
{schema.name}
151-
</SelectItem_Shadcn_>
152-
))}
153-
</SelectContent_Shadcn_>
154-
</Select_Shadcn_>
157+
<PopoverTrigger_Shadcn_ asChild>
158+
<Button
159+
type="default"
160+
size={'medium'}
161+
className={`w-full [&>span]:w-full text-left`}
162+
iconRight={
163+
<ChevronsUpDown className="text-foreground-muted" strokeWidth={2} size={14} />
164+
}
165+
>
166+
{selectedSchema !== undefined && selectedSchema !== ''
167+
? selectedSchema
168+
: 'Choose a schema'}
169+
</Button>
170+
</PopoverTrigger_Shadcn_>
171+
<PopoverContent_Shadcn_
172+
className="p-0"
173+
side="bottom"
174+
align="start"
175+
sameWidthAsTrigger
176+
>
177+
<Command_Shadcn_>
178+
<CommandInput_Shadcn_ placeholder="Find schema..." />
179+
<CommandList_Shadcn_>
180+
<CommandEmpty_Shadcn_>No schemas found</CommandEmpty_Shadcn_>
181+
<CommandGroup_Shadcn_>
182+
<ScrollArea className={(schemas || []).length > 7 ? 'h-[210px]' : ''}>
183+
{(schemas ?? []).map((schema) => (
184+
<CommandItem_Shadcn_
185+
key={schema.name}
186+
className="cursor-pointer flex items-center justify-between space-x-2 w-full"
187+
onSelect={() => {
188+
setSelectedSchema(schema.name)
189+
setSchemaDropdownOpen(false)
190+
}}
191+
onClick={() => {
192+
setSelectedSchema(schema.name)
193+
setSchemaDropdownOpen(false)
194+
}}
195+
>
196+
<span>{schema.name}</span>
197+
{selectedEntity === schema.name && (
198+
<Check className="text-brand" strokeWidth={2} size={16} />
199+
)}
200+
</CommandItem_Shadcn_>
201+
))}
202+
</ScrollArea>
203+
</CommandGroup_Shadcn_>
204+
</CommandList_Shadcn_>
205+
</Command_Shadcn_>
206+
</PopoverContent_Shadcn_>
207+
</Popover_Shadcn_>
155208
</FormItemLayout>
156209

157210
<FormItemLayout
158211
label="Select a table"
159212
name="select-table"
160213
description={
161214
isSelectEntityDisabled &&
215+
!isLoading &&
162216
'Create a table in this schema via the Table or SQL editor first'
163217
}
164218
isReactForm={false}
165219
>
166-
<Select_Shadcn_
167-
disabled={isSelectEntityDisabled}
168-
value={selectedEntity}
169-
onValueChange={setSelectedEntity}
170-
name="select-table"
220+
<Popover_Shadcn_
221+
modal={false}
222+
open={tableDropdownOpen}
223+
onOpenChange={setTableDropdownOpen}
171224
>
172-
<SelectTrigger_Shadcn_ size="small">
173-
<SelectValue
174-
placeholder={
175-
isSelectEntityDisabled ? 'No tables available in schema' : 'Choose a table'
176-
}
177-
>
178-
{selectedEntity}
179-
</SelectValue>
180-
</SelectTrigger_Shadcn_>
181-
<SelectContent_Shadcn_>
182-
{(entityTypes ?? []).map((entity) => (
183-
<SelectItem_Shadcn_ key={entity.name} value={entity.name}>
184-
{entity.name}
185-
</SelectItem_Shadcn_>
186-
))}
187-
</SelectContent_Shadcn_>
188-
</Select_Shadcn_>
225+
<PopoverTrigger_Shadcn_ asChild disabled={isSelectEntityDisabled || isLoading}>
226+
{isLoading ? (
227+
<ShimmeringLoader className="h-[38px]" />
228+
) : (
229+
<Button
230+
type="default"
231+
size="medium"
232+
className={cn(
233+
'w-full [&>span]:w-full text-left',
234+
selectedEntity === '' && 'text-foreground-lighter'
235+
)}
236+
iconRight={
237+
<ChevronsUpDown className="text-foreground-muted" strokeWidth={2} size={14} />
238+
}
239+
>
240+
{selectedEntity !== undefined && selectedEntity !== ''
241+
? selectedEntity
242+
: isSelectEntityDisabled
243+
? 'No tables available in schema'
244+
: 'Choose a table'}
245+
</Button>
246+
)}
247+
</PopoverTrigger_Shadcn_>
248+
<PopoverContent_Shadcn_
249+
className="p-0"
250+
side="bottom"
251+
align="start"
252+
sameWidthAsTrigger
253+
>
254+
<Command_Shadcn_>
255+
<CommandInput_Shadcn_ placeholder="Find table..." />
256+
<CommandList_Shadcn_>
257+
<CommandEmpty_Shadcn_>No tables found</CommandEmpty_Shadcn_>
258+
<CommandGroup_Shadcn_>
259+
<ScrollArea className={(entityTypes || []).length > 7 ? 'h-[210px]' : ''}>
260+
{(entityTypes ?? []).map((entity) => (
261+
<CommandItem_Shadcn_
262+
key={entity.name}
263+
className="cursor-pointer flex items-center justify-between space-x-2 w-full"
264+
onSelect={() => {
265+
setSelectedEntity(entity.name)
266+
setTableDropdownOpen(false)
267+
}}
268+
onClick={() => {
269+
setSelectedEntity(entity.name)
270+
setTableDropdownOpen(false)
271+
}}
272+
>
273+
<span>{entity.name}</span>
274+
{selectedEntity === entity.name && (
275+
<Check className="text-brand" strokeWidth={2} size={16} />
276+
)}
277+
</CommandItem_Shadcn_>
278+
))}
279+
</ScrollArea>
280+
</CommandGroup_Shadcn_>
281+
</CommandList_Shadcn_>
282+
</Command_Shadcn_>
283+
</PopoverContent_Shadcn_>
284+
</Popover_Shadcn_>
189285
</FormItemLayout>
190286

191287
{selectedEntity && (
192288
<FormItemLayout label="Select up to 32 columns" isReactForm={false}>
193289
{isLoadingTableColumns && <ShimmeringLoader className="py-4" />}
194290
{isSuccessTableColumns && (
195-
<MultiSelect
291+
<MultiSelectV2
196292
options={columnOptions}
197-
placeholder=""
293+
placeholder="Choose which columns to create an index on"
198294
searchPlaceholder="Search for a column"
199295
value={selectedColumns}
200296
onChange={setSelectedColumns}

packages/ui-patterns/MultiSelect/MultiSelectV2.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export const MultiSelectV2 = ({
116116
<CommandList_Shadcn_>
117117
<CommandEmpty_Shadcn_>No options found</CommandEmpty_Shadcn_>
118118
<CommandGroup_Shadcn_>
119-
<ScrollArea className={cn(formattedOptions.length > 5 ? 'h-[225px]' : '')}>
119+
<ScrollArea className={cn(formattedOptions.length > 7 ? 'h-[210px]' : '')}>
120120
{formattedOptions?.map((option) => {
121121
const active =
122122
selectedOptions &&

0 commit comments

Comments
 (0)