Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5a90238
dbeaver/pro#9522 integrate profile selector to connection form
sergeyteleshev Jun 30, 2026
c9c9029
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 1, 2026
f5f1fcb
dbeaver/pro#9522 handles edge cases
sergeyteleshev Jul 1, 2026
602fa49
dbeaver/pro#9522 uses rest instead of default getter
sergeyteleshev Jul 1, 2026
2122b08
dbeaver/pro#9522 adds preprocessing to handle null/undefined differen…
sergeyteleshev Jul 1, 2026
dbbb1ee
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 1, 2026
c02175d
dbeaver/pro#9522 eslint fix
sergeyteleshev Jul 1, 2026
cecfe28
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 2, 2026
40a9e72
dbeaver/pro#9522 refactors profiles
sergeyteleshev Jul 2, 2026
c43512c
dbeaver/pro#9522 removes preprocess
sergeyteleshev Jul 2, 2026
8c279c5
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 6, 2026
b7a3e9b
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 7, 2026
ebdd022
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 8, 2026
a9a596c
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
EvgeniaBzzz Jul 8, 2026
c334149
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 9, 2026
0be4844
dbeaver/pro#9522 adds header & footer items
sergeyteleshev Jul 9, 2026
aaec613
dbeaver/pro#9522 truncates items values
sergeyteleshev Jul 9, 2026
1aee6dc
dbeaver/pro#9522 fix retrieving creds from profiles
yagudin10 Jul 10, 2026
057ca95
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
sergeyteleshev Jul 12, 2026
7c8f6a9
Merge branch 'devel' into 9522-cb-network-profiles---add-to-connectio…
EvgeniaBzzz Jul 13, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,13 @@ public DataSourceDescriptor getDataSourceContainerFromInput(@NotNull WebConnecti
return getInputConfigHandler(configInput).createDataSourceContainer();
}

public void updateDataSourceContainerFromInput(
@NotNull WebConnectionConfig configInput,
@NotNull DataSourceDescriptor dataSource
) throws DBWebException {
getInputConfigHandler(configInput).updateDataSource(dataSource);
}

@NotNull
public WebConnectionConfig getConnectionConfigInput(@Nullable Map<String, Object> configMap) {
return new WebConnectionConfig(configMap == null ? Map.of() : configMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,7 @@ private DataSourceDescriptor getDataSourceDescriptor(
}

testDataSource = (DataSourceDescriptor) dataSource.createCopy(dataSource.getRegistry());
WebDataSourceUtils.setConnectionConfiguration(
testDataSource.getDriver(),
testDataSource.getConnectionConfiguration(),
configInput
);
project.updateDataSourceContainerFromInput(configInput, testDataSource);
if (configInput.getSelectedSecretId() != null) {
try {
dataSource.listSharedCredentials()
Expand Down
27 changes: 25 additions & 2 deletions webapp/common-react/@dbeaver/ui-kit/src/Select/Select.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
z-index: 1000;
min-width: 100%;
max-height: var(--dbv-kit-select-popover-height);
overflow-y: auto;
overflow-y: hidden;
display: flex;
flex-direction: column;
background-color: var(--dbv-kit-select-popover-background);
color: var(--dbv-kit-select-popover-foreground);
border-color: var(--dbv-kit-select-border-color);
Expand All @@ -83,8 +85,29 @@
}
}

.dbv-kit-select__popover-items {
overflow-y: auto;
flex: 1;
min-height: 0;
}

.dbv-kit-select__popover-header {
border-bottom: 1px solid var(--dbv-kit-select-border-color);
flex-shrink: 0;
}

.dbv-kit-select__popover-footer {
border-top: 1px solid var(--dbv-kit-select-border-color);
flex-shrink: 0;
}

.dbv-kit-select__group {
border-top: 1px solid var(--dbv-kit-select-border-color);
}

.dbv-kit-select__item {
display: block;
display: flex;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you checked ellipsis after this fix?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all cool
Screenshot 2026-07-02 at 18 04 24

align-items: center;
width: 100%;
font-weight: var(--dbv-kit-select-font-weight);
font-size: var(--dbv-kit-select-font-size);
Expand Down
12 changes: 12 additions & 0 deletions webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
SelectLabel as AriaSelectLabel,
SelectValue as AriaSelectValue,
SelectArrow as AriaSelectArrow,
SelectGroup as AriaSelectGroup,
type SelectProviderProps,
type SelectProps,
type SelectLabelProps,
type SelectPopoverProps,
type SelectItemProps,
type SelectValueProps,
type SelectArrowProps,
type SelectGroupProps,
useSelectContext,
useSelectStore,
} from '@ariakit/react';
Expand All @@ -30,15 +32,15 @@
import { UiKitPopoverContext } from '../Popover/UiKitPopoverContext.js';
import { use } from 'react';

export function SelectProvider({ children, ...props }: SelectProviderProps) {

Check warning on line 35 in webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
return <AriaSelectProvider {...props}>{children}</AriaSelectProvider>;
}

export function Select({ className, ...props }: SelectProps) {

Check warning on line 39 in webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
return <AriaSelect className={clsx('dbv-kit-select', className)} {...props} />;
}

export function SelectPopover({ children, className, portal: portalProp, ...props }: SelectPopoverProps) {

Check warning on line 43 in webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
const popoverContext = use(UiKitPopoverContext);
const portal = (popoverContext.portal || portalProp) ?? false;

Expand All @@ -54,7 +56,7 @@
);
}

export function SelectItem({ children, className, ...props }: SelectItemProps) {

Check warning on line 59 in webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
return (
<AriaSelectItem className={clsx('dbv-kit-select__item', className)} {...props}>
{children}
Expand All @@ -62,7 +64,7 @@
);
}

export function SelectLabel({ children, className, ...props }: SelectLabelProps) {

Check warning on line 67 in webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
return (
<AriaSelectLabel className={clsx('dbv-kit-select__label', className)} {...props}>
{children}
Expand All @@ -70,6 +72,14 @@
);
}

export function SelectGroup({ children, className, ...props }: SelectGroupProps) {

Check warning on line 75 in webapp/common-react/@dbeaver/ui-kit/src/Select/Select.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
return (
<AriaSelectGroup className={clsx('dbv-kit-select__group', className)} {...props}>
{children}
</AriaSelectGroup>
);
}

export {
useSelectContext,
useSelectStore,
Expand All @@ -80,11 +90,13 @@
type SelectItemProps,
type SelectValueProps,
type SelectArrowProps,
type SelectGroupProps,
};

Select.Provider = SelectProvider;
Select.Popover = SelectPopover;
Select.Item = SelectItem;
Select.Label = SelectLabel;
Select.Group = SelectGroup;
Select.Value = AriaSelectValue;
Select.Arrow = AriaSelectArrow;
88 changes: 71 additions & 17 deletions webapp/common-react/@dbeaver/ui-kit/src/Select/SelectField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@

import { useState } from 'react';
import clsx from 'clsx';
import { SelectProvider, Select, SelectPopover, SelectItem, SelectLabel, type SelectProviderProps } from './Select.js';
import { SelectProvider, Select, SelectPopover, SelectItem, SelectLabel, SelectGroup, type SelectProviderProps } from './Select.js';
import './SelectField.css';

export interface SelectItem<T> {
export interface ISelectItem<T> {
value: T;
label: string;
disabled?: boolean;
}

type PropertyGetter<ItemType, ValueType> = (item: ItemType) => ValueType;

export interface SelectFieldProps<T, ItemType = SelectItem<T>> {
export interface ISelectFieldProps<T, ItemType = ISelectItem<T>> {
/** Options array - can be SelectOption objects or arbitrary objects */
items: ItemType[];

Expand Down Expand Up @@ -47,6 +47,12 @@
*/
itemDisabled?: PropertyGetter<ItemType, boolean>;

/**
* When true for an item, it acts as a group boundary — items are split into
* SelectGroup chunks separated by a CSS border. Separator items are not rendered.
*/
isSeparator?: PropertyGetter<ItemType, boolean>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use SelectSeparator as separator

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2026-07-02 at 17 53 19


value?: T;

onChange?: (value: T) => void;
Expand All @@ -65,6 +71,18 @@

noItemsPlaceholder?: React.ReactNode;

/**
* Items pinned above the scrollable list, always visible at the top of the popover.
* Uses the same item API (itemValue, itemRender, itemDisabled) as the main items list.
*/
headerItems?: ItemType[];

/**
* Items pinned below the scrollable list, always visible at the bottom of the popover.
* Uses the same item API (itemValue, itemRender, itemDisabled) as the main items list.
*/
footerItems?: ItemType[];

/**
* Custom renderer for the selected value, overrides itemRenderer for the selected state
* Only needed for special formatting of the selected value different from list items
Expand Down Expand Up @@ -94,16 +112,31 @@
return getter ? getter(item) : defaultGetter(item);
}

export function SelectField<T, ItemType extends {} = SelectItem<T>>({
function splitIntoGroups<ItemType>(items: ItemType[], isSeparator: PropertyGetter<ItemType, boolean>): ItemType[][] {
const groups: ItemType[][] = [[]];
for (const item of items) {
if (isSeparator(item)) {
groups.push([]);
} else {
groups[groups.length - 1]!.push(item);
}
}
return groups.filter(g => g.length > 0);
}

export function SelectField<T, ItemType extends {} = ISelectItem<T>>({

Check warning on line 127 in webapp/common-react/@dbeaver/ui-kit/src/Select/SelectField.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Missing return type on function
items,
value,
onChange,
itemValue,
itemValueSerialized,
itemRender,
itemDisabled,
isSeparator,
label,
noItemsPlaceholder = 'No items',
headerItems,
footerItems,
description,
disabled,
required,
Expand All @@ -115,18 +148,18 @@
autoFocusItemsOnShow,
name,
id,
}: SelectFieldProps<T, ItemType>) {
}: ISelectFieldProps<T, ItemType>) {
const getItemValue = (item: ItemType): T =>
getValueByPath<ItemType, T>(item, itemValue, i => ('value' in i ? (i as unknown as SelectItem<T>).value : (i as unknown as T)));
getValueByPath<ItemType, T>(item, itemValue, i => ('value' in i ? (i as unknown as ISelectItem<T>).value : (i as unknown as T)));

const getItemValueSerialized = (item: ItemType): string =>
getValueByPath<T, string>(getItemValue(item), itemValueSerialized, key => JSON.stringify(key));

const renderItem = (item: ItemType): React.ReactNode =>
getValueByPath<ItemType, React.ReactNode>(item, itemRender, i => ('label' in i ? (i as unknown as SelectItem<T>).label : String(i)));
getValueByPath<ItemType, React.ReactNode>(item, itemRender, i => ('label' in i ? (i as unknown as ISelectItem<T>).label : String(i)));

const isItemDisabled = (item: ItemType): boolean =>
getValueByPath<ItemType, boolean>(item, itemDisabled, i => ('disabled' in i ? Boolean((i as unknown as SelectItem<T>).disabled) : false));
getValueByPath<ItemType, boolean>(item, itemDisabled, i => ('disabled' in i ? Boolean((i as unknown as ISelectItem<T>).disabled) : false));

const [selectedValue, setSelectedValue] = useState<T | undefined>(() => {
if (value !== undefined) {
Expand All @@ -140,7 +173,8 @@
const handleChange = (newValue: string | readonly string[]) => {
// TODO: add support for multi-select

const newItem = items.find(item => getItemValueSerialized(item) === newValue);
const allItems = [...(headerItems ?? []), ...items, ...(footerItems ?? [])];
const newItem = allItems.find(item => getItemValueSerialized(item) === newValue);
if (!newItem) {
return;
}
Expand All @@ -157,8 +191,30 @@
}

const selectedItem = currentValue !== undefined ? items.find(item => getItemValueSerialized(item) === currentValueSerialized) : undefined;
const displayValue = selectedRender ? selectedRender(currentValue, selectedItem) : selectedItem ? renderItem(selectedItem) : '';

Check warning on line 194 in webapp/common-react/@dbeaver/ui-kit/src/Select/SelectField.tsx

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Do not nest ternary expressions

function renderSelectItem(item: ItemType) {
return (
<SelectItem key={getItemValueSerialized(item)} value={getItemValueSerialized(item)} disabled={isItemDisabled(item)}>
{renderItem(item)}
</SelectItem>
);
}

function renderItems(): React.ReactNode {
if (items.length === 0) {
return <div className="dbv-kit-select__empty">{noItemsPlaceholder}</div>;
}

if (isSeparator) {
return splitIntoGroups(items, isSeparator).map(group => (
<SelectGroup key={getItemValueSerialized(group[0]!)}>{group.map(renderSelectItem)}</SelectGroup>
));
}

return items.map(renderSelectItem);
}

return (
<div className={clsx('dbv-kit-select-field', className)}>
<SelectProvider value={currentValueSerialized} setValue={val => handleChange(val)} store={store}>
Expand All @@ -171,14 +227,12 @@
{description && <span className="dbv-kit-select__description">{description}</span>}

<SelectPopover autoFocusOnShow={autoFocusItemsOnShow} portal={portal} gutter={4} unmountOnHide>
{items.length === 0 ? (
<div className="dbv-kit-select__empty">{noItemsPlaceholder}</div>
) : (
items.map(item => (
<SelectItem key={getItemValueSerialized(item)} value={getItemValueSerialized(item)} disabled={isItemDisabled(item)}>
{renderItem(item)}
</SelectItem>
))
{headerItems && headerItems.length > 0 && (
<SelectGroup className="dbv-kit-select__popover-header">{headerItems.map(renderSelectItem)}</SelectGroup>
)}
<div className="dbv-kit-select__popover-items">{renderItems()}</div>
{footerItems && footerItems.length > 0 && (
<SelectGroup className="dbv-kit-select__popover-footer">{footerItems.map(renderSelectItem)}</SelectGroup>
)}
</SelectPopover>
</SelectProvider>
Expand Down
2 changes: 1 addition & 1 deletion webapp/common-react/@dbeaver/ui-kit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@
type FocusTrapRegionProps,
} from '@ariakit/react';

export { Button, ButtonBase, type ButtonProps, ButtonIcon, type ButtonIconProps, UnstyledButton, type UnstyledButtonProps } from './Button/Button.js';

Check failure on line 24 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export { IconButton, IconButtonBase, type IconButtonProps } from './IconButton/IconButton.js';

Check failure on line 25 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export { Checkbox, CheckboxBase, type CheckboxProps } from './Checkbox/Checkbox.js';

Check failure on line 26 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export { CheckboxIndicator, type ICheckboxIndicatorProps } from './Checkbox/CheckboxIndicator.js';

Check failure on line 27 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export { ColorPicker } from './ColorPicker/ColorPicker.js';

Check failure on line 28 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export { ColorPickerBase, type ColorPickerProps } from './ColorPicker/ColorPickerBase.js';

Check failure on line 29 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export { Input, InputBase, type InputProps } from './Input/Input.js';

Check failure on line 30 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export {
SearchPanel,
type SearchPanelProps,
type SearchPanelRef,
type SearchPanelQuery,
type SearchPanelStrings,
} from './SearchPanel/SearchPanel.js';

Check failure on line 37 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export {
Select,
useSelectContext,
Expand All @@ -44,11 +44,11 @@
type SelectLabelProps,
type SelectPopoverProps,
type SelectItemProps,
} from './Select/Select.js';

Check failure on line 47 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export * from './Combobox/Combobox.js';

Check failure on line 48 in webapp/common-react/@dbeaver/ui-kit/src/index.ts

View workflow job for this annotation

GitHub Actions / Frontend / Lint

Don't import/export .tsx files from .ts files directly, use React.lazy()
export * from './Command/Command.js';
export { Popover, usePopoverStore, type PopoverStore } from './Popover/Popover.js';
export { SelectField, type SelectFieldProps, type SelectItem } from './Select/SelectField.js';
export { SelectField, type ISelectFieldProps, type ISelectItem } from './Select/SelectField.js';
export { Spinner, type SpinnerProps } from './Spinner/Spinner.js';
export { Switch, useSwitchContext, type SwitchProps } from './Switch/Switch.js';
export { SwitchProvider, type SwitchProviderProps } from './Switch/SwitchProvider.js';
Expand Down
7 changes: 6 additions & 1 deletion webapp/packages/core-app/public/icons/preload/icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion webapp/packages/core-blocks/src/FormControls/Select.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@
}

.select__item {
display: inline-flex;
display: flex;
gap: 8px;
letter-spacing: normal;
align-items: center;
min-width: 0;
}

.select__item--placeholder {
Expand All @@ -94,6 +95,7 @@
}

.select__input-icon {
flex-shrink: 0;
width: 16px;

& .select__icon {
Expand Down
17 changes: 13 additions & 4 deletions webapp/packages/core-blocks/src/FormControls/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@ export type SelectBaseProps<TKey, TValue> = Omit<
titleSelector?: (item: TValue) => string | undefined;
iconSelector?: (item: TValue) => string | React.ReactElement | undefined;
isDisabled?: (item: TValue) => boolean;
isSeparator?: (item: TValue) => boolean;
onSwitch?: (state: boolean) => void;
inline?: boolean;
children?: string;
portal?: boolean;
headerItems?: TValue[];
footerItems?: TValue[];
};

type ControlledProps<TKey, TValue> = SelectBaseProps<TKey, TValue> & {
Expand All @@ -56,12 +59,12 @@ type ObjectProps<TValue, TKey extends keyof TState, TState> = SelectBaseProps<TS
value?: never;
};

export interface SelectType {
export interface ISelectType {
<TKey, TValue>(props: ControlledProps<TKey, TValue>): React.JSX.Element;
<TValue, TKey extends keyof TState, TState>(props: ObjectProps<TValue, TKey, TState>): React.JSX.Element;
}

export const Select: SelectType = observer(function Select({
export const Select: ISelectType = observer(function Select({
value: controlledValue,
defaultValue,
name,
Expand All @@ -77,13 +80,16 @@ export const Select: SelectType = observer(function Select({
inline,
description,
placeholder,
headerItems,
footerItems,
id,
keySelector = v => v,
valueSelector = v => v,
serializedKeySelector,
iconSelector,
titleSelector,
isDisabled,
isSeparator,
onSelect,
onSwitch,
...rest
Expand Down Expand Up @@ -150,9 +156,9 @@ export const Select: SelectType = observer(function Select({

function itemRender(item: (typeof items)[number]): React.ReactNode {
return (
<div className="select__item tw:truncate" title={item ? titleSelector?.(item) : undefined}>
<div className="select__item">
{renderIcon(item)}
{valueSelector(item)}
<span className="tw:truncate tw:min-w-0" title={titleSelector?.(item) ?? valueSelector(item)}>{valueSelector(item)}</span>
</div>
);
}
Expand Down Expand Up @@ -191,6 +197,9 @@ export const Select: SelectType = observer(function Select({
itemValueSerialized={serializedKeySelector}
itemRender={itemRender}
itemDisabled={itemDisabled}
isSeparator={isSeparator}
headerItems={headerItems}
footerItems={footerItems}
name={name}
disabled={disabled || readOnly}
noItemsPlaceholder={translate('combobox_no_results_placeholder')}
Expand Down
Loading
Loading