From f811528fb9e07a0490835cbe68497e8612bb2113 Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Wed, 5 Aug 2026 16:52:36 +0200 Subject: [PATCH 1/6] dbeaver/pro#9981 adds export button for admin users page --- .../core-blocks/src/Export/ExportButton.tsx | 81 ++++++++++++++ .../src/Export/ExportButtonLazy.ts | 12 ++ .../src/Export/ExportConfirmationDialog.tsx | 104 ++++++++++++++++++ .../src/Export/GridAction.module.css | 18 +++ .../core-blocks/src/Export/GridAction.tsx | 23 ++++ .../src/Export/IExportFilterEntry.ts | 17 +++ webapp/packages/core-blocks/src/index.ts | 4 + webapp/packages/core-blocks/src/locales/en.ts | 5 + webapp/packages/core-blocks/src/locales/fr.ts | 5 + webapp/packages/core-blocks/src/locales/it.ts | 5 + webapp/packages/core-blocks/src/locales/ru.ts | 5 + webapp/packages/core-blocks/src/locales/vi.ts | 5 + webapp/packages/core-blocks/src/locales/zh.ts | 5 + .../Filters/UsersTableFilters.module.css | 10 ++ .../UsersTable/Filters/UsersTableFilters.tsx | 53 ++++++++- .../src/locales/en.ts | 5 + .../src/locales/fr.ts | 5 + .../src/locales/it.ts | 5 + .../src/locales/ru.ts | 5 + .../src/locales/vi.ts | 5 + .../src/locales/zh.ts | 5 + 21 files changed, 377 insertions(+), 5 deletions(-) create mode 100644 webapp/packages/core-blocks/src/Export/ExportButton.tsx create mode 100644 webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts create mode 100644 webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx create mode 100644 webapp/packages/core-blocks/src/Export/GridAction.module.css create mode 100644 webapp/packages/core-blocks/src/Export/GridAction.tsx create mode 100644 webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts diff --git a/webapp/packages/core-blocks/src/Export/ExportButton.tsx b/webapp/packages/core-blocks/src/Export/ExportButton.tsx new file mode 100644 index 00000000000..f5bf77297d2 --- /dev/null +++ b/webapp/packages/core-blocks/src/Export/ExportButton.tsx @@ -0,0 +1,81 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observable } from 'mobx'; +import { observer } from 'mobx-react-lite'; + +import { useService } from '@cloudbeaver/core-di'; +import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs'; +import type { TLocalizationToken } from '@cloudbeaver/core-localization'; + +import { Icon } from '../Icon.js'; +import { useTranslate } from '../localization/useTranslate.js'; +import { useObservableRef } from '../useObservableRef.js'; +import { ExportConfirmationDialog, type IExportConfirmationDialogState } from './ExportConfirmationDialog.js'; +import { GridAction } from './GridAction.js'; +import type { IExportFilterEntry } from './IExportFilterEntry.js'; + +export interface IExportButtonProps { + filters?: IExportFilterEntry[]; + title?: TLocalizationToken; + confirmTitle?: TLocalizationToken; + descriptionWithFilters?: TLocalizationToken; + descriptionDefault?: TLocalizationToken; + /** Hint shown in the info box when `showHint` is enabled */ + hint?: TLocalizationToken; + openOptionsLabel?: TLocalizationToken; + showHint?: boolean; + exportHandler: () => void; + onOpenOptions?: () => void; +} + +export const ExportButton = observer(function ExportButton({ + filters, + title = 'core_blocks_export_title', + confirmTitle = 'core_blocks_export_confirm_title', + descriptionWithFilters = 'core_blocks_export_confirm_with_filters', + descriptionDefault = 'core_blocks_export_confirm_default', + hint = 'core_blocks_export_confirm_default', + openOptionsLabel = 'core_blocks_export_change_filters', + showHint, + exportHandler, + onOpenOptions, +}) { + const translate = useTranslate(); + const commonDialogService = useService(CommonDialogService); + + const dialogState = useObservableRef( + () => ({ filters: filters ?? [] }), + { filters: observable.ref }, + { filters: filters ?? [] }, + ); + + async function handleExport() { + const { status } = await commonDialogService.open(ExportConfirmationDialog, { + state: dialogState, + confirmTitle, + descriptionWithFilters, + descriptionDefault, + hint, + openOptionsLabel, + showHint, + onOpenOptions, + }); + + if (status !== DialogueStateResult.Resolved) { + return; + } + + exportHandler(); + } + + return ( + + + + ); +}); diff --git a/webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts b/webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts new file mode 100644 index 00000000000..c330b74ee97 --- /dev/null +++ b/webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts @@ -0,0 +1,12 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { importLazyComponent } from '../importLazyComponent.js'; + +export const ExportButton = importLazyComponent(() => import('./ExportButton.js').then(m => m.ExportButton)); + +export type { IExportButtonProps } from './ExportButton.js'; diff --git a/webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx b/webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx new file mode 100644 index 00000000000..d0f59d20c43 --- /dev/null +++ b/webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx @@ -0,0 +1,104 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; + +import type { DialogComponentProps } from '@cloudbeaver/core-dialogs'; +import type { TLocalizationToken } from '@cloudbeaver/core-localization'; + +import { Button } from '../Button.js'; +import { CommonDialogBody } from '../CommonDialog/CommonDialog/CommonDialogBody.js'; +import { CommonDialogFooter } from '../CommonDialog/CommonDialog/CommonDialogFooter.js'; +import { CommonDialogHeader } from '../CommonDialog/CommonDialog/CommonDialogHeader.js'; +import { CommonDialogWrapper } from '../CommonDialog/CommonDialog/CommonDialogWrapper.js'; +import { Container } from '../Containers/Container.js'; +import { Fill } from '../Fill.js'; +import { IconOrImage } from '../IconOrImage.js'; +import { Translate } from '../localization/Translate.js'; +import { useTranslate } from '../localization/useTranslate.js'; +import { Tag } from '../Tags/Tag.js'; +import { Tags } from '../Tags/Tags.js'; +import type { IExportFilterEntry } from './IExportFilterEntry.js'; + +export interface IExportConfirmationDialogState { + filters: IExportFilterEntry[]; +} + +export interface IExportConfirmationDialogPayload { + state: IExportConfirmationDialogState; + confirmTitle: TLocalizationToken; + descriptionWithFilters: TLocalizationToken; + descriptionDefault: TLocalizationToken; + hint: TLocalizationToken; + openOptionsLabel: TLocalizationToken; + showHint?: boolean; + onOpenOptions?: () => void; +} + +export const ExportConfirmationDialog = observer>(function ExportConfirmationDialog({ + payload, + resolveDialog, + rejectDialog, + className, +}) { + const translate = useTranslate(); + const { state, confirmTitle, descriptionWithFilters, descriptionDefault, hint, openOptionsLabel, showHint, onOpenOptions } = payload; + const hasFilters = state.filters.length > 0; + + return ( + + rejectDialog()} /> + + <> +
+ +
+ {hasFilters && ( +
    + {state.filters.map(f => ( +
  • + {translate(f.label)}:{' '} + {f.items ? ( + + {f.items.map(item => ( + + ))} + + ) : ( + f.value + )} +
  • + ))} +
+ )} + {hasFilters && showHint && ( +
+ + {translate(hint)} +
+ )} + +
+ + {onOpenOptions && ( + + + + )} + + + + + + +
+ ); +}); diff --git a/webapp/packages/core-blocks/src/Export/GridAction.module.css b/webapp/packages/core-blocks/src/Export/GridAction.module.css new file mode 100644 index 00000000000..d04fb4daf25 --- /dev/null +++ b/webapp/packages/core-blocks/src/Export/GridAction.module.css @@ -0,0 +1,18 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ + +.gridAction { + composes: theme-ripple from global; + position: relative; + box-sizing: border-box; + background: inherit; + cursor: pointer; + width: 28px; + height: 100%; + padding: 4px; +} diff --git a/webapp/packages/core-blocks/src/Export/GridAction.tsx b/webapp/packages/core-blocks/src/Export/GridAction.tsx new file mode 100644 index 00000000000..b5c55e1d7a8 --- /dev/null +++ b/webapp/packages/core-blocks/src/Export/GridAction.tsx @@ -0,0 +1,23 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; + +import { s } from '../s.js'; +import { useS } from '../useS.js'; +import styles from './GridAction.module.css'; + +type Props = React.PropsWithChildren & React.DetailedHTMLProps, HTMLButtonElement>; + +export const GridAction = observer(function GridAction({ children, className, ...rest }: Props) { + const style = useS(styles); + return ( + + ); +}); diff --git a/webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts b/webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts new file mode 100644 index 00000000000..076162fb4fe --- /dev/null +++ b/webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts @@ -0,0 +1,17 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import type { TLocalizationToken } from '@cloudbeaver/core-localization'; + +import type { ITag } from '../Tags/Tag.js'; + +export interface IExportFilterEntry { + key: T; + label: TLocalizationToken; + value?: string; + items?: ITag[]; +} diff --git a/webapp/packages/core-blocks/src/index.ts b/webapp/packages/core-blocks/src/index.ts index 9122fbd62f6..b2c5698dda1 100644 --- a/webapp/packages/core-blocks/src/index.ts +++ b/webapp/packages/core-blocks/src/index.ts @@ -25,6 +25,10 @@ export * from './CommonDialog/DialogsPortal.js'; export * from './ExportImageDialog/ExportImageDialogLazy.js'; export * from './ExportImageDialog/ExportImageFormats.js'; +export * from './Export/ExportButtonLazy.js'; +export * from './Export/GridAction.js'; +export * from './Export/IExportFilterEntry.js'; + export * from './ErrorDetailsDialog/ErrorDetailsDialog.js'; export * from './ComponentsRegistry/CRegistryLoader.js'; diff --git a/webapp/packages/core-blocks/src/locales/en.ts b/webapp/packages/core-blocks/src/locales/en.ts index fe98dd2c2c0..e13209105b9 100644 --- a/webapp/packages/core-blocks/src/locales/en.ts +++ b/webapp/packages/core-blocks/src/locales/en.ts @@ -16,5 +16,10 @@ export default [ ['core_blocks_export_image_dialog_title', 'Export as Image'], ['core_blocks_export_image_dialog_format', 'File Format'], ['core_blocks_export_image_dialog_transparent_background', 'Transparent background'], + ['core_blocks_export_title', 'Export to CSV'], + ['core_blocks_export_confirm_title', 'Export'], + ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], + ['core_blocks_export_confirm_default', 'All data will be exported.'], + ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Close panel'], ]; diff --git a/webapp/packages/core-blocks/src/locales/fr.ts b/webapp/packages/core-blocks/src/locales/fr.ts index 84dd464f37e..d05abfe3b7a 100644 --- a/webapp/packages/core-blocks/src/locales/fr.ts +++ b/webapp/packages/core-blocks/src/locales/fr.ts @@ -15,5 +15,10 @@ export default [ ['core_blocks_export_image_dialog_title', "Exporter en tant qu'image"], ['core_blocks_export_image_dialog_format', 'Format de fichier'], ['core_blocks_export_image_dialog_transparent_background', 'Fond transparent'], + ['core_blocks_export_title', 'Export to CSV'], + ['core_blocks_export_confirm_title', 'Export'], + ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], + ['core_blocks_export_confirm_default', 'All data will be exported.'], + ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Fermer le panneau'], ]; diff --git a/webapp/packages/core-blocks/src/locales/it.ts b/webapp/packages/core-blocks/src/locales/it.ts index 3bbca948354..91ca030f200 100644 --- a/webapp/packages/core-blocks/src/locales/it.ts +++ b/webapp/packages/core-blocks/src/locales/it.ts @@ -10,5 +10,10 @@ export default [ ['core_blocks_export_image_dialog_title', 'Esporta come immagine'], ['core_blocks_export_image_dialog_format', 'Formato file'], ['core_blocks_export_image_dialog_transparent_background', 'Sfondo trasparente'], + ['core_blocks_export_title', 'Export to CSV'], + ['core_blocks_export_confirm_title', 'Export'], + ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], + ['core_blocks_export_confirm_default', 'All data will be exported.'], + ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Chiudi pannello'], ]; diff --git a/webapp/packages/core-blocks/src/locales/ru.ts b/webapp/packages/core-blocks/src/locales/ru.ts index e86ad99e8b9..b6490208528 100644 --- a/webapp/packages/core-blocks/src/locales/ru.ts +++ b/webapp/packages/core-blocks/src/locales/ru.ts @@ -13,5 +13,10 @@ export default [ ['core_blocks_export_image_dialog_title', 'Экспортировать как изображение'], ['core_blocks_export_image_dialog_format', 'Формат файла'], ['core_blocks_export_image_dialog_transparent_background', 'Прозрачный фон'], + ['core_blocks_export_title', 'Экспорт в CSV'], + ['core_blocks_export_confirm_title', 'Экспорт'], + ['core_blocks_export_confirm_with_filters', 'Экспорт будет включать данные со следующими фильтрами:'], + ['core_blocks_export_confirm_default', 'Будут экспортированы все данные.'], + ['core_blocks_export_change_filters', 'Изменить фильтры'], ['core_blocks_dialog_element_close_tooltip', 'Закрыть панель'], ]; diff --git a/webapp/packages/core-blocks/src/locales/vi.ts b/webapp/packages/core-blocks/src/locales/vi.ts index aa6a8f995cb..1df23f45774 100644 --- a/webapp/packages/core-blocks/src/locales/vi.ts +++ b/webapp/packages/core-blocks/src/locales/vi.ts @@ -16,5 +16,10 @@ export default [ ['core_blocks_export_image_dialog_title', 'Xuất dưới dạng hình ảnh'], ['core_blocks_export_image_dialog_format', 'Định dạng tệp'], ['core_blocks_export_image_dialog_transparent_background', 'Nền trong suốt'], + ['core_blocks_export_title', 'Export to CSV'], + ['core_blocks_export_confirm_title', 'Export'], + ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], + ['core_blocks_export_confirm_default', 'All data will be exported.'], + ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Đóng bảng điều khiển'], ]; diff --git a/webapp/packages/core-blocks/src/locales/zh.ts b/webapp/packages/core-blocks/src/locales/zh.ts index 20b008fcbb5..57393025a5e 100644 --- a/webapp/packages/core-blocks/src/locales/zh.ts +++ b/webapp/packages/core-blocks/src/locales/zh.ts @@ -16,5 +16,10 @@ export default [ ['core_blocks_export_image_dialog_title', '导出为图片'], ['core_blocks_export_image_dialog_format', '文件格式'], ['core_blocks_export_image_dialog_transparent_background', '透明背景'], + ['core_blocks_export_title', '导出为 CSV'], + ['core_blocks_export_confirm_title', '导出'], + ['core_blocks_export_confirm_with_filters', '导出将包含带有以下筛选条件的数据:'], + ['core_blocks_export_confirm_default', '将导出所有数据。'], + ['core_blocks_export_change_filters', '更改筛选条件'], ['core_blocks_dialog_element_close_tooltip', '关闭面板'], ]; diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css index 220e53fea68..507a347629c 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css @@ -16,10 +16,20 @@ } .actions { + display: flex; + align-items: center; + gap: 8px; +} + +.buttonBox { composes: theme-form-element-radius theme-background-surface theme-text-on-surface theme theme-border-color-background from global; + display: flex; + align-items: center; + justify-content: center; box-sizing: border-box; border: 2px solid; height: 32px; + overflow: hidden; } .button { diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx index de91f234699..2adf36e42f6 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -8,11 +8,12 @@ import { observer } from 'mobx-react-lite'; import { useState } from 'react'; -import { Filter, Group, IconOrImage, Loader, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import { ExportButton, Filter, Group, IconOrImage, type IExportFilterEntry, Loader, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import { GlobalConstants, objectToFormFields, submitForm } from '@cloudbeaver/core-utils'; import styles from './UsersTableFilters.module.css'; import { UsersTableFiltersDetails } from './UsersTableFiltersDetails.js'; -import { type IUserFilters } from './useUsersTableFilters.js'; +import { type IUserFilters, USER_ROLE_ALL, USER_STATUSES } from './useUsersTableFilters.js'; interface Props { filters: IUserFilters; @@ -24,6 +25,36 @@ export const UsersTableFilters = observer(function UsersTableFilters({ fi const [open, setOpen] = useState(false); + const exportFilters: IExportFilterEntry[] = []; + const search = filters.search.trim(); + if (search) { + exportFilters.push({ key: 'search', label: 'authentication_administration_users_export_filter_search', value: search }); + } + if (filters.status !== 'all') { + const status = USER_STATUSES.find(item => item.value === filters.status); + exportFilters.push({ key: 'status', label: 'authentication_user_status', value: status ? translate(status.label) : filters.status }); + } + if (filters.role !== USER_ROLE_ALL) { + exportFilters.push({ key: 'role', label: 'authentication_user_role', value: filters.role }); + } + + function exportUsers() { + const options: Record = {}; + const userIdMask = filters.search.trim(); + + if (userIdMask) { + options['userIdMask'] = userIdMask; + } + if (filters.status !== 'all') { + options['status'] = filters.status === 'true'; + } + if (filters.role !== USER_ROLE_ALL) { + options['authRole'] = filters.role; + } + + submitForm(GlobalConstants.absoluteServiceUrl('admin', 'export-users-csv'), objectToFormFields(options)); + } + return (
@@ -34,8 +65,20 @@ export const UsersTableFilters = observer(function UsersTableFilters({ fi onChange={filters.setSearch} />
-
setOpen(!open)}> - +
+
setOpen(!open)}> + +
+
+
+
diff --git a/webapp/packages/plugin-authentication-administration/src/locales/en.ts b/webapp/packages/plugin-authentication-administration/src/locales/en.ts index cf4efd51491..84e0792dc37 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/en.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/en.ts @@ -35,6 +35,11 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ENABLED'], ['authentication_administration_users_filters_status_disabled', 'DISABLED'], ['authentication_administration_users_filters_status_all', 'ALL'], + ['authentication_administration_users_export_title', 'Export to CSV'], + ['authentication_administration_users_export_confirm_title', 'Export users'], + ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], + ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], + ['authentication_administration_users_export_filter_search', 'Search'], ['authentication_administration_users_empty', 'There are no users'], ['authentication_administration_users_delete_user', 'Delete user'], ['authentication_administration_users_delete_user_fail', 'Failed to delete user'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/fr.ts b/webapp/packages/plugin-authentication-administration/src/locales/fr.ts index acda50ea608..8ab6cd0e667 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/fr.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/fr.ts @@ -35,6 +35,11 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ACTIVÉ'], ['authentication_administration_users_filters_status_disabled', 'DÉSACTIVÉ'], ['authentication_administration_users_filters_status_all', 'TOUS'], + ['authentication_administration_users_export_title', 'Export to CSV'], + ['authentication_administration_users_export_confirm_title', 'Export users'], + ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], + ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], + ['authentication_administration_users_export_filter_search', 'Search'], ['authentication_administration_users_empty', "Il n'y a pas d'utilisateurs"], ['authentication_administration_users_delete_user', "Supprimer l'utilisateur"], ['authentication_administration_users_delete_user_fail', "Échec de la suppression de l'utilisateur"], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/it.ts b/webapp/packages/plugin-authentication-administration/src/locales/it.ts index 67b4ba1bf97..9b22327b145 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/it.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/it.ts @@ -31,6 +31,11 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ENABLED'], ['authentication_administration_users_filters_status_disabled', 'DISABLED'], ['authentication_administration_users_filters_status_all', 'ALL'], + ['authentication_administration_users_export_title', 'Export to CSV'], + ['authentication_administration_users_export_confirm_title', 'Export users'], + ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], + ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], + ['authentication_administration_users_export_filter_search', 'Search'], ['authentication_administration_users_empty', 'There are no users'], ['authentication_administration_users_delete_user', 'Delete user'], ['authentication_administration_users_delete_user_fail', 'Failed to delete user'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts index 92f273d3da0..7ff5c59e23e 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts @@ -35,6 +35,11 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ВКЛЮЧЕН'], ['authentication_administration_users_filters_status_disabled', 'ВЫКЛЮЧЕН'], ['authentication_administration_users_filters_status_all', 'ВСЕ'], + ['authentication_administration_users_export_title', 'Экспорт в CSV'], + ['authentication_administration_users_export_confirm_title', 'Экспорт пользователей'], + ['authentication_administration_users_export_confirm_with_filters', 'Экспорт будет включать пользователей, соответствующих следующим фильтрам:'], + ['authentication_administration_users_export_confirm_default', 'Будут экспортированы все пользователи.'], + ['authentication_administration_users_export_filter_search', 'Поиск'], ['authentication_administration_users_empty', 'Нет пользователей'], ['authentication_administration_users_delete_user', 'Удалить пользователя'], ['authentication_administration_users_delete_user_fail', 'Не удалось удалить пользователя'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/vi.ts b/webapp/packages/plugin-authentication-administration/src/locales/vi.ts index b9330130b15..f36284e2e73 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/vi.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/vi.ts @@ -35,6 +35,11 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'BẬT'], ['authentication_administration_users_filters_status_disabled', 'TẮT'], ['authentication_administration_users_filters_status_all', 'TẤT CẢ'], + ['authentication_administration_users_export_title', 'Export to CSV'], + ['authentication_administration_users_export_confirm_title', 'Export users'], + ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], + ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], + ['authentication_administration_users_export_filter_search', 'Search'], ['authentication_administration_users_empty', 'Không có người dùng nào'], ['authentication_administration_users_delete_user', 'Xóa người dùng'], ['authentication_administration_users_delete_user_fail', 'Xóa người dùng thất bại'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts index 3d16b472093..02ddbe372be 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts @@ -34,6 +34,11 @@ export default [ ['authentication_administration_users_filters_status_enabled', '启用'], ['authentication_administration_users_filters_status_disabled', '禁用'], ['authentication_administration_users_filters_status_all', '全部'], + ['authentication_administration_users_export_title', '导出为 CSV'], + ['authentication_administration_users_export_confirm_title', '导出用户'], + ['authentication_administration_users_export_confirm_with_filters', '导出将包含符合以下筛选条件的用户:'], + ['authentication_administration_users_export_confirm_default', '将导出所有用户。'], + ['authentication_administration_users_export_filter_search', '搜索'], ['authentication_administration_users_empty', '无用户'], ['authentication_administration_users_delete_user', '删除用户'], ['authentication_administration_users_delete_user_fail', '删除用户失败'], From c005cc347329c01896d483584775e78d5e01d59c Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Thu, 6 Aug 2026 16:23:31 +0200 Subject: [PATCH 2/6] dbeaver/pro#9981 uses fetch to download csv instead of submitForm approach (backend issue) --- .../UsersTable/Filters/UsersTableFilters.tsx | 57 ++++++++++++++----- .../src/locales/en.ts | 2 + .../src/locales/fr.ts | 2 + .../src/locales/it.ts | 2 + .../src/locales/ru.ts | 2 + .../src/locales/vi.ts | 2 + .../src/locales/zh.ts | 2 + 7 files changed, 55 insertions(+), 14 deletions(-) diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx index 2adf36e42f6..580f6c1afbf 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx @@ -9,7 +9,9 @@ import { observer } from 'mobx-react-lite'; import { useState } from 'react'; import { ExportButton, Filter, Group, IconOrImage, type IExportFilterEntry, Loader, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; -import { GlobalConstants, objectToFormFields, submitForm } from '@cloudbeaver/core-utils'; +import { NotificationService } from '@cloudbeaver/core-events'; +import { useService } from '@cloudbeaver/core-di'; +import { download, GlobalConstants } from '@cloudbeaver/core-utils'; import styles from './UsersTableFilters.module.css'; import { UsersTableFiltersDetails } from './UsersTableFiltersDetails.js'; @@ -22,6 +24,7 @@ interface Props { export const UsersTableFilters = observer(function UsersTableFilters({ filters }) { const translate = useTranslate(); const style = useS(styles); + const notificationService = useService(NotificationService); const [open, setOpen] = useState(false); @@ -38,21 +41,47 @@ export const UsersTableFilters = observer(function UsersTableFilters({ fi exportFilters.push({ key: 'role', label: 'authentication_user_role', value: filters.role }); } - function exportUsers() { - const options: Record = {}; - const userIdMask = filters.search.trim(); + async function exportUsers() { + try { + const options: Record = {}; + const userIdMask = filters.search.trim(); - if (userIdMask) { - options['userIdMask'] = userIdMask; - } - if (filters.status !== 'all') { - options['status'] = filters.status === 'true'; - } - if (filters.role !== USER_ROLE_ALL) { - options['authRole'] = filters.role; - } + if (userIdMask) { + options['userIdMask'] = userIdMask; + } + + if (filters.status !== 'all') { + options['status'] = String(filters.status === 'true'); + } + + if (filters.role !== USER_ROLE_ALL) { + options['authRole'] = filters.role; + } - submitForm(GlobalConstants.absoluteServiceUrl('admin', 'export-users-csv'), objectToFormFields(options)); + const response = await fetch(GlobalConstants.absoluteServiceUrl('admin', 'export-users-csv'), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(options), + }); + + if (!response.ok) { + notificationService.logError({ + title: 'authentication_administration_users_export_fail', + message: translate('authentication_administration_users_export_fail_status', undefined, { status: response.status }), + }); + return; + } + + const contentDisposition = response.headers.get('Content-Disposition'); + const fileName = contentDisposition?.match(/filename="?([^"]+)"?/)?.[1] ?? 'users.csv'; + + const blob = await response.blob(); + download(blob, fileName); + } catch (exception: any) { + notificationService.logException(exception, 'authentication_administration_users_export_fail'); + } } return ( diff --git a/webapp/packages/plugin-authentication-administration/src/locales/en.ts b/webapp/packages/plugin-authentication-administration/src/locales/en.ts index 84e0792dc37..8a774cfce14 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/en.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/en.ts @@ -40,6 +40,8 @@ export default [ ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], ['authentication_administration_users_export_filter_search', 'Search'], + ['authentication_administration_users_export_fail', 'Users export failed'], + ['authentication_administration_users_export_fail_status', 'Failed to export users, status: {arg:status}'], ['authentication_administration_users_empty', 'There are no users'], ['authentication_administration_users_delete_user', 'Delete user'], ['authentication_administration_users_delete_user_fail', 'Failed to delete user'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/fr.ts b/webapp/packages/plugin-authentication-administration/src/locales/fr.ts index 8ab6cd0e667..39e46a3f736 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/fr.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/fr.ts @@ -40,6 +40,8 @@ export default [ ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], ['authentication_administration_users_export_filter_search', 'Search'], + ['authentication_administration_users_export_fail', "Échec de l'exportation des utilisateurs"], + ['authentication_administration_users_export_fail_status', "Échec de l'exportation des utilisateurs, statut : {arg:status}"], ['authentication_administration_users_empty', "Il n'y a pas d'utilisateurs"], ['authentication_administration_users_delete_user', "Supprimer l'utilisateur"], ['authentication_administration_users_delete_user_fail', "Échec de la suppression de l'utilisateur"], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/it.ts b/webapp/packages/plugin-authentication-administration/src/locales/it.ts index 9b22327b145..967d18b7880 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/it.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/it.ts @@ -36,6 +36,8 @@ export default [ ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], ['authentication_administration_users_export_filter_search', 'Search'], + ['authentication_administration_users_export_fail', 'Users export failed'], + ['authentication_administration_users_export_fail_status', 'Failed to export users, status: {arg:status}'], ['authentication_administration_users_empty', 'There are no users'], ['authentication_administration_users_delete_user', 'Delete user'], ['authentication_administration_users_delete_user_fail', 'Failed to delete user'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts index 7ff5c59e23e..ea21ba8cc8f 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts @@ -40,6 +40,8 @@ export default [ ['authentication_administration_users_export_confirm_with_filters', 'Экспорт будет включать пользователей, соответствующих следующим фильтрам:'], ['authentication_administration_users_export_confirm_default', 'Будут экспортированы все пользователи.'], ['authentication_administration_users_export_filter_search', 'Поиск'], + ['authentication_administration_users_export_fail', 'Не удалось экспортировать пользователей'], + ['authentication_administration_users_export_fail_status', 'Не удалось экспортировать пользователей, статус: {arg:status}'], ['authentication_administration_users_empty', 'Нет пользователей'], ['authentication_administration_users_delete_user', 'Удалить пользователя'], ['authentication_administration_users_delete_user_fail', 'Не удалось удалить пользователя'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/vi.ts b/webapp/packages/plugin-authentication-administration/src/locales/vi.ts index f36284e2e73..c00a03410bc 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/vi.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/vi.ts @@ -40,6 +40,8 @@ export default [ ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], ['authentication_administration_users_export_filter_search', 'Search'], + ['authentication_administration_users_export_fail', 'Xuất người dùng thất bại'], + ['authentication_administration_users_export_fail_status', 'Xuất người dùng thất bại, trạng thái: {arg:status}'], ['authentication_administration_users_empty', 'Không có người dùng nào'], ['authentication_administration_users_delete_user', 'Xóa người dùng'], ['authentication_administration_users_delete_user_fail', 'Xóa người dùng thất bại'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts index 02ddbe372be..5a98eeb96ea 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts @@ -39,6 +39,8 @@ export default [ ['authentication_administration_users_export_confirm_with_filters', '导出将包含符合以下筛选条件的用户:'], ['authentication_administration_users_export_confirm_default', '将导出所有用户。'], ['authentication_administration_users_export_filter_search', '搜索'], + ['authentication_administration_users_export_fail', '用户导出失败'], + ['authentication_administration_users_export_fail_status', '用户导出失败,状态:{arg:status}'], ['authentication_administration_users_empty', '无用户'], ['authentication_administration_users_delete_user', '删除用户'], ['authentication_administration_users_delete_user_fail', '删除用户失败'], From 13d174a3469bd126cfa21de6ba9780b0c34fa64d Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Thu, 6 Aug 2026 16:47:15 +0200 Subject: [PATCH 3/6] dbeaver/pro#9981 makes users export to be available only for PRO products --- .../Users/UsersAdministrationService.ts | 7 ++ .../UsersTable/Filters/UsersTableFilters.tsx | 80 +++---------------- .../src/index.ts | 1 + .../src/locales/en.ts | 7 -- .../src/locales/fr.ts | 7 -- .../src/locales/it.ts | 7 -- .../src/locales/ru.ts | 7 -- .../src/locales/vi.ts | 7 -- .../src/locales/zh.ts | 7 -- 9 files changed, 17 insertions(+), 113 deletions(-) diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts index 1d4c373e2a0..a62838d3c5e 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts @@ -17,6 +17,7 @@ import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dial import { CreateTeamService } from './Teams/TeamsTable/CreateTeamService.js'; import { EUsersAdministrationSub, UsersAdministrationNavigationService } from './UsersAdministrationNavigationService.js'; import { CreateUserService } from './UsersTable/CreateUserService.js'; +import type { IUserFilters } from './UsersTable/Filters/useUsersTableFilters.js'; const UserCredentialsList = React.lazy(async () => { const { UserCredentialsList } = await import('./UsersTable/UserCredentialsList.js'); @@ -37,11 +38,16 @@ export interface IUserDetailsInfoProps { user: AdminUser; } +export interface IUsersExportProps { + filters: IUserFilters; +} + @injectable(() => [AdministrationItemService, CreateUserService, TeamsResource, CreateTeamService, UsersResource, CommonDialogService]) export class UsersAdministrationService extends Bootstrap { readonly tabsContainer: TabsContainer; readonly userDetailsInfoPlaceholder: PlaceholderContainer; readonly informationPlaceholder: PlaceholderContainer; + readonly exportPlaceholder: PlaceholderContainer; administrationItem!: IAdministrationItem; constructor( @@ -56,6 +62,7 @@ export class UsersAdministrationService extends Bootstrap { this.userDetailsInfoPlaceholder = new PlaceholderContainer(); this.tabsContainer = new TabsContainer('Access Control'); this.informationPlaceholder = new PlaceholderContainer(); + this.exportPlaceholder = new PlaceholderContainer(); } override register(): void { diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx index 580f6c1afbf..0fcf3e94d86 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx @@ -8,14 +8,13 @@ import { observer } from 'mobx-react-lite'; import { useState } from 'react'; -import { ExportButton, Filter, Group, IconOrImage, type IExportFilterEntry, Loader, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; -import { NotificationService } from '@cloudbeaver/core-events'; +import { Filter, Group, IconOrImage, Loader, Placeholder, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; -import { download, GlobalConstants } from '@cloudbeaver/core-utils'; +import { UsersAdministrationService } from '../../UsersAdministrationService.js'; import styles from './UsersTableFilters.module.css'; import { UsersTableFiltersDetails } from './UsersTableFiltersDetails.js'; -import { type IUserFilters, USER_ROLE_ALL, USER_STATUSES } from './useUsersTableFilters.js'; +import type { IUserFilters } from './useUsersTableFilters.js'; interface Props { filters: IUserFilters; @@ -24,66 +23,10 @@ interface Props { export const UsersTableFilters = observer(function UsersTableFilters({ filters }) { const translate = useTranslate(); const style = useS(styles); - const notificationService = useService(NotificationService); + const usersAdministrationService = useService(UsersAdministrationService); const [open, setOpen] = useState(false); - const exportFilters: IExportFilterEntry[] = []; - const search = filters.search.trim(); - if (search) { - exportFilters.push({ key: 'search', label: 'authentication_administration_users_export_filter_search', value: search }); - } - if (filters.status !== 'all') { - const status = USER_STATUSES.find(item => item.value === filters.status); - exportFilters.push({ key: 'status', label: 'authentication_user_status', value: status ? translate(status.label) : filters.status }); - } - if (filters.role !== USER_ROLE_ALL) { - exportFilters.push({ key: 'role', label: 'authentication_user_role', value: filters.role }); - } - - async function exportUsers() { - try { - const options: Record = {}; - const userIdMask = filters.search.trim(); - - if (userIdMask) { - options['userIdMask'] = userIdMask; - } - - if (filters.status !== 'all') { - options['status'] = String(filters.status === 'true'); - } - - if (filters.role !== USER_ROLE_ALL) { - options['authRole'] = filters.role; - } - - const response = await fetch(GlobalConstants.absoluteServiceUrl('admin', 'export-users-csv'), { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(options), - }); - - if (!response.ok) { - notificationService.logError({ - title: 'authentication_administration_users_export_fail', - message: translate('authentication_administration_users_export_fail_status', undefined, { status: response.status }), - }); - return; - } - - const contentDisposition = response.headers.get('Content-Disposition'); - const fileName = contentDisposition?.match(/filename="?([^"]+)"?/)?.[1] ?? 'users.csv'; - - const blob = await response.blob(); - download(blob, fileName); - } catch (exception: any) { - notificationService.logException(exception, 'authentication_administration_users_export_fail'); - } - } - return (
@@ -99,16 +42,11 @@ export const UsersTableFilters = observer(function UsersTableFilters({ fi
-
- -
+ {usersAdministrationService.exportPlaceholder.getDisplayed({ filters }).length > 0 && ( +
+ +
+ )} diff --git a/webapp/packages/plugin-authentication-administration/src/index.ts b/webapp/packages/plugin-authentication-administration/src/index.ts index 4441479b122..12f1c6ca12a 100644 --- a/webapp/packages/plugin-authentication-administration/src/index.ts +++ b/webapp/packages/plugin-authentication-administration/src/index.ts @@ -22,3 +22,4 @@ export * from './AdministrationUsersManagementService.js'; export * from './externalUserProviderStatusContext.js'; export * from './Administration/Users/Teams/TeamsForm/Options/getTeamOptionsFormPart.js'; export * from './Administration/Users/UsersTable/UsersTableOptionsPanelService.js'; +export * from './Administration/Users/UsersTable/Filters/useUsersTableFilters.js'; diff --git a/webapp/packages/plugin-authentication-administration/src/locales/en.ts b/webapp/packages/plugin-authentication-administration/src/locales/en.ts index 8a774cfce14..cf4efd51491 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/en.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/en.ts @@ -35,13 +35,6 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ENABLED'], ['authentication_administration_users_filters_status_disabled', 'DISABLED'], ['authentication_administration_users_filters_status_all', 'ALL'], - ['authentication_administration_users_export_title', 'Export to CSV'], - ['authentication_administration_users_export_confirm_title', 'Export users'], - ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], - ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], - ['authentication_administration_users_export_filter_search', 'Search'], - ['authentication_administration_users_export_fail', 'Users export failed'], - ['authentication_administration_users_export_fail_status', 'Failed to export users, status: {arg:status}'], ['authentication_administration_users_empty', 'There are no users'], ['authentication_administration_users_delete_user', 'Delete user'], ['authentication_administration_users_delete_user_fail', 'Failed to delete user'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/fr.ts b/webapp/packages/plugin-authentication-administration/src/locales/fr.ts index 39e46a3f736..acda50ea608 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/fr.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/fr.ts @@ -35,13 +35,6 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ACTIVÉ'], ['authentication_administration_users_filters_status_disabled', 'DÉSACTIVÉ'], ['authentication_administration_users_filters_status_all', 'TOUS'], - ['authentication_administration_users_export_title', 'Export to CSV'], - ['authentication_administration_users_export_confirm_title', 'Export users'], - ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], - ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], - ['authentication_administration_users_export_filter_search', 'Search'], - ['authentication_administration_users_export_fail', "Échec de l'exportation des utilisateurs"], - ['authentication_administration_users_export_fail_status', "Échec de l'exportation des utilisateurs, statut : {arg:status}"], ['authentication_administration_users_empty', "Il n'y a pas d'utilisateurs"], ['authentication_administration_users_delete_user', "Supprimer l'utilisateur"], ['authentication_administration_users_delete_user_fail', "Échec de la suppression de l'utilisateur"], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/it.ts b/webapp/packages/plugin-authentication-administration/src/locales/it.ts index 967d18b7880..67b4ba1bf97 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/it.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/it.ts @@ -31,13 +31,6 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ENABLED'], ['authentication_administration_users_filters_status_disabled', 'DISABLED'], ['authentication_administration_users_filters_status_all', 'ALL'], - ['authentication_administration_users_export_title', 'Export to CSV'], - ['authentication_administration_users_export_confirm_title', 'Export users'], - ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], - ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], - ['authentication_administration_users_export_filter_search', 'Search'], - ['authentication_administration_users_export_fail', 'Users export failed'], - ['authentication_administration_users_export_fail_status', 'Failed to export users, status: {arg:status}'], ['authentication_administration_users_empty', 'There are no users'], ['authentication_administration_users_delete_user', 'Delete user'], ['authentication_administration_users_delete_user_fail', 'Failed to delete user'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts index ea21ba8cc8f..92f273d3da0 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/ru.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/ru.ts @@ -35,13 +35,6 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'ВКЛЮЧЕН'], ['authentication_administration_users_filters_status_disabled', 'ВЫКЛЮЧЕН'], ['authentication_administration_users_filters_status_all', 'ВСЕ'], - ['authentication_administration_users_export_title', 'Экспорт в CSV'], - ['authentication_administration_users_export_confirm_title', 'Экспорт пользователей'], - ['authentication_administration_users_export_confirm_with_filters', 'Экспорт будет включать пользователей, соответствующих следующим фильтрам:'], - ['authentication_administration_users_export_confirm_default', 'Будут экспортированы все пользователи.'], - ['authentication_administration_users_export_filter_search', 'Поиск'], - ['authentication_administration_users_export_fail', 'Не удалось экспортировать пользователей'], - ['authentication_administration_users_export_fail_status', 'Не удалось экспортировать пользователей, статус: {arg:status}'], ['authentication_administration_users_empty', 'Нет пользователей'], ['authentication_administration_users_delete_user', 'Удалить пользователя'], ['authentication_administration_users_delete_user_fail', 'Не удалось удалить пользователя'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/vi.ts b/webapp/packages/plugin-authentication-administration/src/locales/vi.ts index c00a03410bc..b9330130b15 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/vi.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/vi.ts @@ -35,13 +35,6 @@ export default [ ['authentication_administration_users_filters_status_enabled', 'BẬT'], ['authentication_administration_users_filters_status_disabled', 'TẮT'], ['authentication_administration_users_filters_status_all', 'TẤT CẢ'], - ['authentication_administration_users_export_title', 'Export to CSV'], - ['authentication_administration_users_export_confirm_title', 'Export users'], - ['authentication_administration_users_export_confirm_with_filters', 'The export will include users matching the following filters:'], - ['authentication_administration_users_export_confirm_default', 'All users will be exported.'], - ['authentication_administration_users_export_filter_search', 'Search'], - ['authentication_administration_users_export_fail', 'Xuất người dùng thất bại'], - ['authentication_administration_users_export_fail_status', 'Xuất người dùng thất bại, trạng thái: {arg:status}'], ['authentication_administration_users_empty', 'Không có người dùng nào'], ['authentication_administration_users_delete_user', 'Xóa người dùng'], ['authentication_administration_users_delete_user_fail', 'Xóa người dùng thất bại'], diff --git a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts index 5a98eeb96ea..3d16b472093 100644 --- a/webapp/packages/plugin-authentication-administration/src/locales/zh.ts +++ b/webapp/packages/plugin-authentication-administration/src/locales/zh.ts @@ -34,13 +34,6 @@ export default [ ['authentication_administration_users_filters_status_enabled', '启用'], ['authentication_administration_users_filters_status_disabled', '禁用'], ['authentication_administration_users_filters_status_all', '全部'], - ['authentication_administration_users_export_title', '导出为 CSV'], - ['authentication_administration_users_export_confirm_title', '导出用户'], - ['authentication_administration_users_export_confirm_with_filters', '导出将包含符合以下筛选条件的用户:'], - ['authentication_administration_users_export_confirm_default', '将导出所有用户。'], - ['authentication_administration_users_export_filter_search', '搜索'], - ['authentication_administration_users_export_fail', '用户导出失败'], - ['authentication_administration_users_export_fail_status', '用户导出失败,状态:{arg:status}'], ['authentication_administration_users_empty', '无用户'], ['authentication_administration_users_delete_user', '删除用户'], ['authentication_administration_users_delete_user_fail', '删除用户失败'], From a3fb3336263be8b4de10db0e656f60c191688fd8 Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Fri, 7 Aug 2026 16:32:07 +0200 Subject: [PATCH 4/6] dbeaver/pro#9981 reverts export logic --- .../core-blocks/src/Export/ExportButton.tsx | 81 -------------- .../src/Export/ExportButtonLazy.ts | 12 -- .../src/Export/ExportConfirmationDialog.tsx | 104 ------------------ .../src/Export/GridAction.module.css | 18 --- .../core-blocks/src/Export/GridAction.tsx | 23 ---- .../src/Export/IExportFilterEntry.ts | 17 --- webapp/packages/core-blocks/src/index.ts | 4 - webapp/packages/core-blocks/src/locales/en.ts | 5 - webapp/packages/core-blocks/src/locales/fr.ts | 5 - webapp/packages/core-blocks/src/locales/it.ts | 5 - webapp/packages/core-blocks/src/locales/ru.ts | 5 - webapp/packages/core-blocks/src/locales/vi.ts | 5 - webapp/packages/core-blocks/src/locales/zh.ts | 5 - 13 files changed, 289 deletions(-) delete mode 100644 webapp/packages/core-blocks/src/Export/ExportButton.tsx delete mode 100644 webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts delete mode 100644 webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx delete mode 100644 webapp/packages/core-blocks/src/Export/GridAction.module.css delete mode 100644 webapp/packages/core-blocks/src/Export/GridAction.tsx delete mode 100644 webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts diff --git a/webapp/packages/core-blocks/src/Export/ExportButton.tsx b/webapp/packages/core-blocks/src/Export/ExportButton.tsx deleted file mode 100644 index f5bf77297d2..00000000000 --- a/webapp/packages/core-blocks/src/Export/ExportButton.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2026 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { observable } from 'mobx'; -import { observer } from 'mobx-react-lite'; - -import { useService } from '@cloudbeaver/core-di'; -import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs'; -import type { TLocalizationToken } from '@cloudbeaver/core-localization'; - -import { Icon } from '../Icon.js'; -import { useTranslate } from '../localization/useTranslate.js'; -import { useObservableRef } from '../useObservableRef.js'; -import { ExportConfirmationDialog, type IExportConfirmationDialogState } from './ExportConfirmationDialog.js'; -import { GridAction } from './GridAction.js'; -import type { IExportFilterEntry } from './IExportFilterEntry.js'; - -export interface IExportButtonProps { - filters?: IExportFilterEntry[]; - title?: TLocalizationToken; - confirmTitle?: TLocalizationToken; - descriptionWithFilters?: TLocalizationToken; - descriptionDefault?: TLocalizationToken; - /** Hint shown in the info box when `showHint` is enabled */ - hint?: TLocalizationToken; - openOptionsLabel?: TLocalizationToken; - showHint?: boolean; - exportHandler: () => void; - onOpenOptions?: () => void; -} - -export const ExportButton = observer(function ExportButton({ - filters, - title = 'core_blocks_export_title', - confirmTitle = 'core_blocks_export_confirm_title', - descriptionWithFilters = 'core_blocks_export_confirm_with_filters', - descriptionDefault = 'core_blocks_export_confirm_default', - hint = 'core_blocks_export_confirm_default', - openOptionsLabel = 'core_blocks_export_change_filters', - showHint, - exportHandler, - onOpenOptions, -}) { - const translate = useTranslate(); - const commonDialogService = useService(CommonDialogService); - - const dialogState = useObservableRef( - () => ({ filters: filters ?? [] }), - { filters: observable.ref }, - { filters: filters ?? [] }, - ); - - async function handleExport() { - const { status } = await commonDialogService.open(ExportConfirmationDialog, { - state: dialogState, - confirmTitle, - descriptionWithFilters, - descriptionDefault, - hint, - openOptionsLabel, - showHint, - onOpenOptions, - }); - - if (status !== DialogueStateResult.Resolved) { - return; - } - - exportHandler(); - } - - return ( - - - - ); -}); diff --git a/webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts b/webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts deleted file mode 100644 index c330b74ee97..00000000000 --- a/webapp/packages/core-blocks/src/Export/ExportButtonLazy.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2026 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { importLazyComponent } from '../importLazyComponent.js'; - -export const ExportButton = importLazyComponent(() => import('./ExportButton.js').then(m => m.ExportButton)); - -export type { IExportButtonProps } from './ExportButton.js'; diff --git a/webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx b/webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx deleted file mode 100644 index d0f59d20c43..00000000000 --- a/webapp/packages/core-blocks/src/Export/ExportConfirmationDialog.tsx +++ /dev/null @@ -1,104 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2026 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { observer } from 'mobx-react-lite'; - -import type { DialogComponentProps } from '@cloudbeaver/core-dialogs'; -import type { TLocalizationToken } from '@cloudbeaver/core-localization'; - -import { Button } from '../Button.js'; -import { CommonDialogBody } from '../CommonDialog/CommonDialog/CommonDialogBody.js'; -import { CommonDialogFooter } from '../CommonDialog/CommonDialog/CommonDialogFooter.js'; -import { CommonDialogHeader } from '../CommonDialog/CommonDialog/CommonDialogHeader.js'; -import { CommonDialogWrapper } from '../CommonDialog/CommonDialog/CommonDialogWrapper.js'; -import { Container } from '../Containers/Container.js'; -import { Fill } from '../Fill.js'; -import { IconOrImage } from '../IconOrImage.js'; -import { Translate } from '../localization/Translate.js'; -import { useTranslate } from '../localization/useTranslate.js'; -import { Tag } from '../Tags/Tag.js'; -import { Tags } from '../Tags/Tags.js'; -import type { IExportFilterEntry } from './IExportFilterEntry.js'; - -export interface IExportConfirmationDialogState { - filters: IExportFilterEntry[]; -} - -export interface IExportConfirmationDialogPayload { - state: IExportConfirmationDialogState; - confirmTitle: TLocalizationToken; - descriptionWithFilters: TLocalizationToken; - descriptionDefault: TLocalizationToken; - hint: TLocalizationToken; - openOptionsLabel: TLocalizationToken; - showHint?: boolean; - onOpenOptions?: () => void; -} - -export const ExportConfirmationDialog = observer>(function ExportConfirmationDialog({ - payload, - resolveDialog, - rejectDialog, - className, -}) { - const translate = useTranslate(); - const { state, confirmTitle, descriptionWithFilters, descriptionDefault, hint, openOptionsLabel, showHint, onOpenOptions } = payload; - const hasFilters = state.filters.length > 0; - - return ( - - rejectDialog()} /> - - <> -
- -
- {hasFilters && ( -
    - {state.filters.map(f => ( -
  • - {translate(f.label)}:{' '} - {f.items ? ( - - {f.items.map(item => ( - - ))} - - ) : ( - f.value - )} -
  • - ))} -
- )} - {hasFilters && showHint && ( -
- - {translate(hint)} -
- )} - -
- - {onOpenOptions && ( - - - - )} - - - - - - -
- ); -}); diff --git a/webapp/packages/core-blocks/src/Export/GridAction.module.css b/webapp/packages/core-blocks/src/Export/GridAction.module.css deleted file mode 100644 index d04fb4daf25..00000000000 --- a/webapp/packages/core-blocks/src/Export/GridAction.module.css +++ /dev/null @@ -1,18 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2026 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ - -.gridAction { - composes: theme-ripple from global; - position: relative; - box-sizing: border-box; - background: inherit; - cursor: pointer; - width: 28px; - height: 100%; - padding: 4px; -} diff --git a/webapp/packages/core-blocks/src/Export/GridAction.tsx b/webapp/packages/core-blocks/src/Export/GridAction.tsx deleted file mode 100644 index b5c55e1d7a8..00000000000 --- a/webapp/packages/core-blocks/src/Export/GridAction.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2026 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import { observer } from 'mobx-react-lite'; - -import { s } from '../s.js'; -import { useS } from '../useS.js'; -import styles from './GridAction.module.css'; - -type Props = React.PropsWithChildren & React.DetailedHTMLProps, HTMLButtonElement>; - -export const GridAction = observer(function GridAction({ children, className, ...rest }: Props) { - const style = useS(styles); - return ( - - ); -}); diff --git a/webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts b/webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts deleted file mode 100644 index 076162fb4fe..00000000000 --- a/webapp/packages/core-blocks/src/Export/IExportFilterEntry.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2026 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ -import type { TLocalizationToken } from '@cloudbeaver/core-localization'; - -import type { ITag } from '../Tags/Tag.js'; - -export interface IExportFilterEntry { - key: T; - label: TLocalizationToken; - value?: string; - items?: ITag[]; -} diff --git a/webapp/packages/core-blocks/src/index.ts b/webapp/packages/core-blocks/src/index.ts index b2c5698dda1..9122fbd62f6 100644 --- a/webapp/packages/core-blocks/src/index.ts +++ b/webapp/packages/core-blocks/src/index.ts @@ -25,10 +25,6 @@ export * from './CommonDialog/DialogsPortal.js'; export * from './ExportImageDialog/ExportImageDialogLazy.js'; export * from './ExportImageDialog/ExportImageFormats.js'; -export * from './Export/ExportButtonLazy.js'; -export * from './Export/GridAction.js'; -export * from './Export/IExportFilterEntry.js'; - export * from './ErrorDetailsDialog/ErrorDetailsDialog.js'; export * from './ComponentsRegistry/CRegistryLoader.js'; diff --git a/webapp/packages/core-blocks/src/locales/en.ts b/webapp/packages/core-blocks/src/locales/en.ts index e13209105b9..fe98dd2c2c0 100644 --- a/webapp/packages/core-blocks/src/locales/en.ts +++ b/webapp/packages/core-blocks/src/locales/en.ts @@ -16,10 +16,5 @@ export default [ ['core_blocks_export_image_dialog_title', 'Export as Image'], ['core_blocks_export_image_dialog_format', 'File Format'], ['core_blocks_export_image_dialog_transparent_background', 'Transparent background'], - ['core_blocks_export_title', 'Export to CSV'], - ['core_blocks_export_confirm_title', 'Export'], - ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], - ['core_blocks_export_confirm_default', 'All data will be exported.'], - ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Close panel'], ]; diff --git a/webapp/packages/core-blocks/src/locales/fr.ts b/webapp/packages/core-blocks/src/locales/fr.ts index d05abfe3b7a..84dd464f37e 100644 --- a/webapp/packages/core-blocks/src/locales/fr.ts +++ b/webapp/packages/core-blocks/src/locales/fr.ts @@ -15,10 +15,5 @@ export default [ ['core_blocks_export_image_dialog_title', "Exporter en tant qu'image"], ['core_blocks_export_image_dialog_format', 'Format de fichier'], ['core_blocks_export_image_dialog_transparent_background', 'Fond transparent'], - ['core_blocks_export_title', 'Export to CSV'], - ['core_blocks_export_confirm_title', 'Export'], - ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], - ['core_blocks_export_confirm_default', 'All data will be exported.'], - ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Fermer le panneau'], ]; diff --git a/webapp/packages/core-blocks/src/locales/it.ts b/webapp/packages/core-blocks/src/locales/it.ts index 91ca030f200..3bbca948354 100644 --- a/webapp/packages/core-blocks/src/locales/it.ts +++ b/webapp/packages/core-blocks/src/locales/it.ts @@ -10,10 +10,5 @@ export default [ ['core_blocks_export_image_dialog_title', 'Esporta come immagine'], ['core_blocks_export_image_dialog_format', 'Formato file'], ['core_blocks_export_image_dialog_transparent_background', 'Sfondo trasparente'], - ['core_blocks_export_title', 'Export to CSV'], - ['core_blocks_export_confirm_title', 'Export'], - ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], - ['core_blocks_export_confirm_default', 'All data will be exported.'], - ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Chiudi pannello'], ]; diff --git a/webapp/packages/core-blocks/src/locales/ru.ts b/webapp/packages/core-blocks/src/locales/ru.ts index b6490208528..e86ad99e8b9 100644 --- a/webapp/packages/core-blocks/src/locales/ru.ts +++ b/webapp/packages/core-blocks/src/locales/ru.ts @@ -13,10 +13,5 @@ export default [ ['core_blocks_export_image_dialog_title', 'Экспортировать как изображение'], ['core_blocks_export_image_dialog_format', 'Формат файла'], ['core_blocks_export_image_dialog_transparent_background', 'Прозрачный фон'], - ['core_blocks_export_title', 'Экспорт в CSV'], - ['core_blocks_export_confirm_title', 'Экспорт'], - ['core_blocks_export_confirm_with_filters', 'Экспорт будет включать данные со следующими фильтрами:'], - ['core_blocks_export_confirm_default', 'Будут экспортированы все данные.'], - ['core_blocks_export_change_filters', 'Изменить фильтры'], ['core_blocks_dialog_element_close_tooltip', 'Закрыть панель'], ]; diff --git a/webapp/packages/core-blocks/src/locales/vi.ts b/webapp/packages/core-blocks/src/locales/vi.ts index 1df23f45774..aa6a8f995cb 100644 --- a/webapp/packages/core-blocks/src/locales/vi.ts +++ b/webapp/packages/core-blocks/src/locales/vi.ts @@ -16,10 +16,5 @@ export default [ ['core_blocks_export_image_dialog_title', 'Xuất dưới dạng hình ảnh'], ['core_blocks_export_image_dialog_format', 'Định dạng tệp'], ['core_blocks_export_image_dialog_transparent_background', 'Nền trong suốt'], - ['core_blocks_export_title', 'Export to CSV'], - ['core_blocks_export_confirm_title', 'Export'], - ['core_blocks_export_confirm_with_filters', 'The export will include data with the following filters:'], - ['core_blocks_export_confirm_default', 'All data will be exported.'], - ['core_blocks_export_change_filters', 'Change Filters'], ['core_blocks_dialog_element_close_tooltip', 'Đóng bảng điều khiển'], ]; diff --git a/webapp/packages/core-blocks/src/locales/zh.ts b/webapp/packages/core-blocks/src/locales/zh.ts index 57393025a5e..20b008fcbb5 100644 --- a/webapp/packages/core-blocks/src/locales/zh.ts +++ b/webapp/packages/core-blocks/src/locales/zh.ts @@ -16,10 +16,5 @@ export default [ ['core_blocks_export_image_dialog_title', '导出为图片'], ['core_blocks_export_image_dialog_format', '文件格式'], ['core_blocks_export_image_dialog_transparent_background', '透明背景'], - ['core_blocks_export_title', '导出为 CSV'], - ['core_blocks_export_confirm_title', '导出'], - ['core_blocks_export_confirm_with_filters', '导出将包含带有以下筛选条件的数据:'], - ['core_blocks_export_confirm_default', '将导出所有数据。'], - ['core_blocks_export_change_filters', '更改筛选条件'], ['core_blocks_dialog_element_close_tooltip', '关闭面板'], ]; From da7a3b08a87a00da98d45301839969f9f9450940 Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Fri, 7 Aug 2026 17:27:48 +0200 Subject: [PATCH 5/6] dbeaver/pro#9981 add actionButtonsPlaceholder --- .../Users/UsersAdministrationService.ts | 10 ++++- .../Filters/FiltersActionButton.tsx | 29 +++++++++++++ .../Filters/UsersTableFilterButton.tsx | 32 ++++++++++++++ .../Filters/UsersTableFilters.module.css | 42 ------------------- .../UsersTable/Filters/UsersTableFilters.tsx | 26 ++++-------- .../Filters/UsersTableFiltersOpenContext.ts | 15 +++++++ .../src/index.ts | 1 + 7 files changed, 93 insertions(+), 62 deletions(-) create mode 100644 webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/FiltersActionButton.tsx create mode 100644 webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilterButton.tsx create mode 100644 webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFiltersOpenContext.ts diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts index a62838d3c5e..bd17b1a61b2 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts @@ -17,6 +17,7 @@ import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dial import { CreateTeamService } from './Teams/TeamsTable/CreateTeamService.js'; import { EUsersAdministrationSub, UsersAdministrationNavigationService } from './UsersAdministrationNavigationService.js'; import { CreateUserService } from './UsersTable/CreateUserService.js'; +import { UsersTableFilterButton } from './UsersTable/Filters/UsersTableFilterButton.js'; import type { IUserFilters } from './UsersTable/Filters/useUsersTableFilters.js'; const UserCredentialsList = React.lazy(async () => { @@ -42,12 +43,16 @@ export interface IUsersExportProps { filters: IUserFilters; } +export interface IUsersActionButtonProps { + filters: IUserFilters; +} + @injectable(() => [AdministrationItemService, CreateUserService, TeamsResource, CreateTeamService, UsersResource, CommonDialogService]) export class UsersAdministrationService extends Bootstrap { readonly tabsContainer: TabsContainer; readonly userDetailsInfoPlaceholder: PlaceholderContainer; readonly informationPlaceholder: PlaceholderContainer; - readonly exportPlaceholder: PlaceholderContainer; + readonly actionButtonsPlaceholder: PlaceholderContainer; administrationItem!: IAdministrationItem; constructor( @@ -62,7 +67,7 @@ export class UsersAdministrationService extends Bootstrap { this.userDetailsInfoPlaceholder = new PlaceholderContainer(); this.tabsContainer = new TabsContainer('Access Control'); this.informationPlaceholder = new PlaceholderContainer(); - this.exportPlaceholder = new PlaceholderContainer(); + this.actionButtonsPlaceholder = new PlaceholderContainer(); } override register(): void { @@ -90,6 +95,7 @@ export class UsersAdministrationService extends Bootstrap { getDrawerComponent: () => UsersDrawerItem, }); this.userDetailsInfoPlaceholder.add(UserCredentialsList, 0); + this.actionButtonsPlaceholder.add(UsersTableFilterButton, 0); } private async handleDeactivate(sub: EUsersAdministrationSub) { diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/FiltersActionButton.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/FiltersActionButton.tsx new file mode 100644 index 00000000000..129f013b98d --- /dev/null +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/FiltersActionButton.tsx @@ -0,0 +1,29 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; + +import { clsx, IconButton, type IconButtonProps } from '@dbeaver/ui-kit'; + +const BUTTON_BOX_CLASS_NAME = clsx( + 'theme-form-element-radius theme-background-surface theme-text-on-surface theme theme-border-color-background', + 'tw:flex tw:items-center tw:justify-center tw:box-border tw:h-8 tw:border-2', +); + +const BUTTON_CLASS_NAME = 'tw:relative! tw:box-border! tw:bg-inherit! tw:cursor-pointer! tw:w-[28px]! tw:h-full! tw:p-1! tw:hover:opacity-80!'; + +export interface IFiltersActionButtonProps extends IconButtonProps { + active?: boolean; +} + +export const FiltersActionButton = observer(function FiltersActionButton({ active, className, size = 'small', ...rest }) { + return ( +
+ +
+ ); +}); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilterButton.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilterButton.tsx new file mode 100644 index 00000000000..c47fd02c09a --- /dev/null +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilterButton.tsx @@ -0,0 +1,32 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { observer } from 'mobx-react-lite'; +import { useContext } from 'react'; + +import { IconOrImage, useTranslate } from '@cloudbeaver/core-blocks'; + +import type { IUsersActionButtonProps } from '../../UsersAdministrationService.js'; +import { FiltersActionButton } from './FiltersActionButton.js'; +import { UsersTableFiltersOpenContext } from './UsersTableFiltersOpenContext.js'; + +export const UsersTableFilterButton = observer(function UsersTableFilterButton() { + const translate = useTranslate(); + const openContext = useContext(UsersTableFiltersOpenContext); + + if (!openContext) { + throw new Error('UsersTableFilterButton must be rendered within UsersTableFiltersOpenContext'); + } + + const label = translate('authentication_administration_users_filters_filter_label'); + + return ( + + + + ); +}); diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css index 507a347629c..45b82c0f3af 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.module.css @@ -1,11 +1,3 @@ -/* - * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2024 DBeaver Corp and others - * - * Licensed under the Apache License, Version 2.0. - * you may not use this file except in compliance with the License. - */ - .filterContainer { display: flex; gap: 12px; @@ -20,37 +12,3 @@ align-items: center; gap: 8px; } - -.buttonBox { - composes: theme-form-element-radius theme-background-surface theme-text-on-surface theme theme-border-color-background from global; - display: flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - border: 2px solid; - height: 32px; - overflow: hidden; -} - -.button { - position: relative; - box-sizing: border-box; - background: inherit; - cursor: pointer; - width: 28px; - height: 100%; - padding: 4px; - - &:hover { - opacity: 0.8; - } -} - -.buttonActive { - background: var(--theme-secondary); -} - -.iconOrImage { - width: 100%; - height: 100%; -} diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx index fc5d9f1c447..3aeca27f1e4 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFilters.tsx @@ -6,16 +6,16 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import { useState } from 'react'; +import { useCallback, useMemo, useState } from 'react'; -import { Filter, Group, IconOrImage, Loader, Placeholder, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; +import { Filter, Group, Loader, Placeholder, s, useS, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { UsersAdministrationService } from '../../UsersAdministrationService.js'; import styles from './UsersTableFilters.module.css'; import { UsersTableFiltersDetails } from './UsersTableFiltersDetails.js'; +import { UsersTableFiltersOpenContext } from './UsersTableFiltersOpenContext.js'; import { type IUserFilters } from './useUsersTableFilters.js'; -import { IconButton } from '@dbeaver/ui-kit'; interface Props { filters: IUserFilters; @@ -27,6 +27,8 @@ export const UsersTableFilters = observer(function UsersTableFilters({ fi const usersAdministrationService = useService(UsersAdministrationService); const [open, setOpen] = useState(false); + const onToggle = useCallback(() => setOpen(open => !open), []); + const openContext = useMemo(() => ({ open, onToggle }), [open, onToggle]); return ( @@ -38,21 +40,9 @@ export const UsersTableFilters = observer(function UsersTableFilters({ fi onChange={filters.setSearch} />
-
- setOpen(!open)} - > - - -
- {usersAdministrationService.exportPlaceholder.getDisplayed({ filters }).length > 0 && ( -
- -
- )} + + +
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFiltersOpenContext.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFiltersOpenContext.ts new file mode 100644 index 00000000000..3745d6cf1fd --- /dev/null +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/Filters/UsersTableFiltersOpenContext.ts @@ -0,0 +1,15 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2026 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0. + * you may not use this file except in compliance with the License. + */ +import { createContext } from 'react'; + +export interface IUsersTableFiltersOpenContext { + open: boolean; + onToggle: () => void; +} + +export const UsersTableFiltersOpenContext = createContext(null); diff --git a/webapp/packages/plugin-authentication-administration/src/index.ts b/webapp/packages/plugin-authentication-administration/src/index.ts index 12f1c6ca12a..3b8803e2356 100644 --- a/webapp/packages/plugin-authentication-administration/src/index.ts +++ b/webapp/packages/plugin-authentication-administration/src/index.ts @@ -23,3 +23,4 @@ export * from './externalUserProviderStatusContext.js'; export * from './Administration/Users/Teams/TeamsForm/Options/getTeamOptionsFormPart.js'; export * from './Administration/Users/UsersTable/UsersTableOptionsPanelService.js'; export * from './Administration/Users/UsersTable/Filters/useUsersTableFilters.js'; +export * from './Administration/Users/UsersTable/Filters/FiltersActionButton.js'; From d7cc6f7e7a5d45f1a0656343f537f927df301ec1 Mon Sep 17 00:00:00 2001 From: sergeyteleshev Date: Fri, 7 Aug 2026 17:33:00 +0200 Subject: [PATCH 6/6] dbeaver/pro#9981 cleanup --- .../Users/UsersAdministrationService.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts index bd17b1a61b2..eae553f07fc 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersAdministrationService.ts @@ -1,6 +1,6 @@ /* * CloudBeaver - Cloud Database Manager - * Copyright (C) 2020-2025 DBeaver Corp and others + * Copyright (C) 2020-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dial import { CreateTeamService } from './Teams/TeamsTable/CreateTeamService.js'; import { EUsersAdministrationSub, UsersAdministrationNavigationService } from './UsersAdministrationNavigationService.js'; import { CreateUserService } from './UsersTable/CreateUserService.js'; -import { UsersTableFilterButton } from './UsersTable/Filters/UsersTableFilterButton.js'; import type { IUserFilters } from './UsersTable/Filters/useUsersTableFilters.js'; const UserCredentialsList = React.lazy(async () => { @@ -35,14 +34,15 @@ const UsersAdministration = React.lazy(async () => { return { default: UsersAdministration }; }); +const UsersTableFilterButton = React.lazy(async () => { + const { UsersTableFilterButton } = await import('./UsersTable/Filters/UsersTableFilterButton.js'); + return { default: UsersTableFilterButton }; +}); + export interface IUserDetailsInfoProps { user: AdminUser; } -export interface IUsersExportProps { - filters: IUserFilters; -} - export interface IUsersActionButtonProps { filters: IUserFilters; }