diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java index af94e9a4e9..69c203f7c8 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java @@ -33,6 +33,7 @@ import io.cloudbeaver.service.DBWServiceServerConfigurator; import io.cloudbeaver.service.admin.*; import io.cloudbeaver.service.security.SMUtils; +import io.cloudbeaver.utils.WebAppUtils; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; @@ -257,7 +258,9 @@ public boolean grantUserTeam(@NotNull WebSession webSession, String user, String if (grantor == null) { throw new DBWebException("Cannot grant team in anonymous mode"); } - if (CommonUtils.equalObjects(user, webSession.getUser().getUserId())) { + if (!WebAppUtils.getWebApplication().isDistributed() + && CommonUtils.equalObjects(user, webSession.getUser().getUserId()) + ) { throw new DBWebException("You cannot edit your own permissions"); } try { @@ -281,7 +284,9 @@ public boolean revokeUserTeam(@NotNull WebSession webSession, String user, Strin if (grantor == null) { throw new DBWebException("Cannot revoke team in anonymous mode"); } - if (CommonUtils.equalObjects(user, webSession.getUser().getUserId())) { + if (!WebAppUtils.getWebApplication().isDistributed() && + CommonUtils.equalObjects(user, webSession.getUser().getUserId()) + ) { throw new DBWebException("You cannot edit your own permissions"); } try { diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java index c1dcf52b53..073cbc38a8 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java @@ -34,6 +34,7 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Map; public class WebDataTransferServlet extends WebServiceServletBase { @@ -67,7 +68,7 @@ protected void processServiceRequest(WebSession session, HttpServletRequest requ } String fileName = taskInfo.getExportFileName(); if (!CommonUtils.isEmpty(fileName)) { - fileName += "." + WebDataTransferUtils.getProcessorFileExtension(processor); + fileName += "." + WebDataTransferUtils.getProcessorFileExtension(processor, taskInfo.getParameters().getProcessorProperties()); } else { fileName = taskInfo.getDataFileId(); } diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java index b0ac4d45fd..d05129736a 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java @@ -23,9 +23,12 @@ import org.jkiss.dbeaver.tools.transfer.registry.DataTransferProcessorDescriptor; import org.jkiss.utils.CommonUtils; +import java.util.Map; + class WebDataTransferUtils { private static final Log log = Log.getLog(WebDataTransferUtils.class); + public static final String EXTENSION = "extension"; public static String getProcessorFileExtension(DataTransferProcessorDescriptor processor) { @@ -34,6 +37,14 @@ public static String getProcessorFileExtension(DataTransferProcessorDescriptor p return CommonUtils.isEmpty(ext) ? "data" : ext; } + public static String getProcessorFileExtension(DataTransferProcessorDescriptor processor, Map processorProperties) { + if (processorProperties != null && processorProperties.get(EXTENSION) != null) { + return CommonUtils.toString(processorProperties.get(EXTENSION), "data"); + } + + return getProcessorFileExtension(processor); + } + public static String normalizeFileName( @NotNull String fileName, @NotNull WebDataTransferOutputSettings outputSettings diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java index f503fc3dfb..d76d32034f 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java @@ -107,7 +107,15 @@ public WebAsyncTaskInfo dataTransferExportDataFromContainer( } @NotNull - private String makeUniqueFileName(WebSQLProcessor sqlProcessor, DataTransferProcessorDescriptor processor) { + private String makeUniqueFileName( + WebSQLProcessor sqlProcessor, + DataTransferProcessorDescriptor processor, + Map processorProperties + ) { + if (processorProperties != null && processorProperties.get(StreamConsumerSettings.PROP_FILE_EXTENSION) != null) { + return sqlProcessor.getWebSession().getSessionId() + "_" + UUID.randomUUID() + + "." + processorProperties.get(StreamConsumerSettings.PROP_FILE_EXTENSION); + } return sqlProcessor.getWebSession().getSessionId() + "_" + UUID.randomUUID() + "." + WebDataTransferUtils.getProcessorFileExtension(processor); } @@ -157,7 +165,8 @@ public void run(DBRProgressMonitor monitor) throws InvocationTargetException { monitor.beginTask("Export data", 1); try { monitor.subTask("Export data using " + processor.getName()); - Path exportFile = dataExportFolder.resolve(makeUniqueFileName(sqlProcessor, processor)); + Path exportFile = dataExportFolder.resolve( + makeUniqueFileName(sqlProcessor, processor, parameters.getProcessorProperties())); try { exportData(monitor, processor, dataContainer, parameters, resultsInfo, exportFile); } catch (Exception e) { diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/FieldCheckbox.tsx b/webapp/packages/core-blocks/src/FormControls/Checkboxes/FieldCheckbox.tsx index 8b1da1d6c7..24f64a2d30 100644 --- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/FieldCheckbox.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/FieldCheckbox.tsx @@ -12,7 +12,6 @@ import type { ILayoutSizeProps } from '../../Containers/ILayoutSizeProps'; import { s } from '../../s'; import { useS } from '../../useS'; import { Field } from '../Field'; -import { FieldDescription } from '../FieldDescription'; import { FieldLabel } from '../FieldLabel'; import { isControlPresented } from '../isControlPresented'; import { Checkbox, CheckboxBaseProps, CheckboxType, ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox'; diff --git a/webapp/packages/core-blocks/src/FormControls/Filter.tsx b/webapp/packages/core-blocks/src/FormControls/Filter.tsx index 1b7486377c..735f9fc2f1 100644 --- a/webapp/packages/core-blocks/src/FormControls/Filter.tsx +++ b/webapp/packages/core-blocks/src/FormControls/Filter.tsx @@ -103,6 +103,7 @@ export const Filter = observer>(functio
, TKey extends keyof TState> { name: TKey; state: TState; - defaultState?: TState; + defaultState?: Readonly>; autoHide?: boolean; mapState?: (value: TState[TKey]) => string; mapValue?: (value: string) => TState[TKey]; diff --git a/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldBase.tsx b/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldBase.tsx index 471fa5e102..b133221fab 100644 --- a/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldBase.tsx +++ b/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldBase.tsx @@ -61,6 +61,7 @@ export const InputFieldBase = observer( }, ref, ) { + const [uncontrolledInputValue, setUncontrolledInputValue] = useState(value); const inputRef = useRef(null); const mergedRef = useCombinedRef(inputRef, ref); const capsLock = useCapsLockTracker(); @@ -81,6 +82,7 @@ export const InputFieldBase = observer( const handleChange = useCallback( (event: React.ChangeEvent) => { + setUncontrolledInputValue(event.target.value); onChange?.(event.target.value, name); }, [name, onChange], @@ -97,16 +99,21 @@ export const InputFieldBase = observer( } uncontrolled ||= value === undefined; - if (!value) { - canShowPassword = false; - } useLayoutEffect(() => { if (uncontrolled && isNotNullDefined(value) && inputRef.current) { inputRef.current.value = value; + + if (uncontrolledInputValue !== value) { + setUncontrolledInputValue(value); + } } }); + if (!uncontrolledInputValue) { + canShowPassword = false; + } + return ( diff --git a/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldState.tsx b/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldState.tsx index 2fae8ebdeb..9b8dc1b263 100644 --- a/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldState.tsx +++ b/webapp/packages/core-blocks/src/FormControls/InputField/InputFieldState.tsx @@ -31,7 +31,7 @@ export const InputFieldState: InputFieldType = observer diff --git a/webapp/packages/core-blocks/src/FormControls/isControlPresented.ts b/webapp/packages/core-blocks/src/FormControls/isControlPresented.ts index 705867b36b..1eef41a532 100644 --- a/webapp/packages/core-blocks/src/FormControls/isControlPresented.ts +++ b/webapp/packages/core-blocks/src/FormControls/isControlPresented.ts @@ -5,12 +5,12 @@ * Licensed under the Apache License, Version 2.0. * you may not use this file except in compliance with the License. */ -import { isNotNullDefined } from '@cloudbeaver/core-utils'; +import { isNotNullDefined, isObject } from '@cloudbeaver/core-utils'; -export function isControlPresented(name: string | undefined, state: any, defaultValue?: any): boolean { - if (isNotNullDefined(state) && isNotNullDefined(name)) { - if (typeof state === 'object' && name in state) { - return isNotNullDefined(state[name]); +export function isControlPresented(name: string | number | symbol | undefined, state: any, defaultValue?: any): boolean { + if (isObject(state) && isNotNullDefined(state) && isNotNullDefined(name)) { + if (name in state) { + return isNotNullDefined((state as Record)[name]); } return defaultValue !== undefined; } diff --git a/webapp/packages/core-blocks/src/FormControls/useFormStateControl.ts b/webapp/packages/core-blocks/src/FormControls/useFormStateControl.ts index 25edf26c81..7d7febcf41 100644 --- a/webapp/packages/core-blocks/src/FormControls/useFormStateControl.ts +++ b/webapp/packages/core-blocks/src/FormControls/useFormStateControl.ts @@ -34,11 +34,16 @@ export function useFormStateControl, TKey ext onChange(inputValue as any, name as any); } }); + + let presented: boolean | undefined; + if (isNotNullDefined(defaultValue) && isObject(defaultValue)) { + presented = isControlPresented(name, defaultValue); defaultValue = defaultValue[name]; } if (isNotNullDefined(value) && isObject(value)) { + presented = presented || isControlPresented(name, value, defaultValue); value = value[name]; } @@ -48,11 +53,11 @@ export function useFormStateControl, TKey ext stringValue = mapToString(value as any); defaultStringValue = mapToString(defaultValue as any); } else { - stringValue = value; - defaultStringValue = defaultValue; + stringValue = isNotNullDefined(value) ? String(value) : ''; + defaultStringValue = isNotNullDefined(defaultValue) ? String(defaultValue) : ''; } - const hide = 'autoHide' in rest && !!rest.autoHide && !isControlPresented(String(name), stringValue, defaultStringValue); + const hide = 'autoHide' in rest && !!rest.autoHide && presented === false; return { name, value, stringValue, defaultValue, defaultStringValue, hide, onChange: handleChange }; } diff --git a/webapp/packages/core-blocks/src/ItemList/ItemListSearch.tsx b/webapp/packages/core-blocks/src/ItemList/ItemListSearch.tsx index 3a2187c3c2..fba9d2d56f 100644 --- a/webapp/packages/core-blocks/src/ItemList/ItemListSearch.tsx +++ b/webapp/packages/core-blocks/src/ItemList/ItemListSearch.tsx @@ -60,6 +60,7 @@ export const ItemListSearch: React.FC = function ItemListSearch({ value, boolean; geLayoutSize?: (property: ObjectPropertyInfo) => ILayoutSizeProps; onFocus?: (name: string) => void; @@ -44,6 +45,7 @@ export const ObjectPropertyInfoForm = observer(function state, defaultState, category, + disableAutoCompleteForPasswords = false, editable = true, className, autofillToken = '', @@ -90,7 +92,7 @@ export const ObjectPropertyInfoForm = observer(function state={state} defaultState={defaultState} editable={editable} - autofillToken={autofillToken} + autofillToken={property.features.includes('password') && disableAutoCompleteForPasswords ? 'new-password' : autofillToken} disabled={disabled} readOnly={readOnly} autoHide={autoHide} diff --git a/webapp/packages/core-blocks/src/ObjectPropertyInfo/ObjectPropertyInfoForm/RenderField.tsx b/webapp/packages/core-blocks/src/ObjectPropertyInfo/ObjectPropertyInfoForm/RenderField.tsx index 9d74b04052..d7f5fccdf4 100644 --- a/webapp/packages/core-blocks/src/ObjectPropertyInfo/ObjectPropertyInfoForm/RenderField.tsx +++ b/webapp/packages/core-blocks/src/ObjectPropertyInfo/ObjectPropertyInfoForm/RenderField.tsx @@ -88,7 +88,7 @@ export const RenderField = observer(function RenderField({ } if (!editable) { - if (autoHide && !isControlPresented(property.id!, state)) { + if (autoHide && !isControlPresented(property.id, state)) { return null; } return ( @@ -239,9 +239,8 @@ export const RenderField = observer(function RenderField({ labelTooltip={property.description || property.displayName} name={property.id!} state={state} - defaultState={defaultState} + defaultState={defaultState || { [property.id!]: defaultValue }} autoHide={autoHide} - defaultValue={defaultValue} description={property.hint} placeholder={passwordSavedMessage} disabled={disabled} diff --git a/webapp/packages/core-localization/src/locales/en.ts b/webapp/packages/core-localization/src/locales/en.ts index 7460c1e17c..fb8e36b3c3 100644 --- a/webapp/packages/core-localization/src/locales/en.ts +++ b/webapp/packages/core-localization/src/locales/en.ts @@ -114,6 +114,7 @@ export default [ ['ui_readonly', 'Read-only'], ['ui_test', 'Test'], ['ui_export', 'Export'], + ['ui_you', 'You'], ['root_permission_denied', "You don't have permissions"], ['root_permission_no_permission', "You don't have permission for this action"], diff --git a/webapp/packages/core-localization/src/locales/it.ts b/webapp/packages/core-localization/src/locales/it.ts index 973a53da48..f98cbff0c7 100644 --- a/webapp/packages/core-localization/src/locales/it.ts +++ b/webapp/packages/core-localization/src/locales/it.ts @@ -104,6 +104,7 @@ export default [ ['ui_readonly', 'In sola lettura'], ['ui_test', 'Test'], ['ui_export', 'Export'], + ['ui_you', 'You'], ['root_permission_denied', 'Non hai i permessi'], ['app_root_session_expire_warning_title', 'La sessione sta per scadere'], diff --git a/webapp/packages/core-localization/src/locales/ru.ts b/webapp/packages/core-localization/src/locales/ru.ts index dbe87c9686..a479779496 100644 --- a/webapp/packages/core-localization/src/locales/ru.ts +++ b/webapp/packages/core-localization/src/locales/ru.ts @@ -110,6 +110,7 @@ export default [ ['ui_readonly', 'Доступно только для чтения'], ['ui_test', 'Проверить'], ['ui_export', 'Экспорт'], + ['ui_you', 'Вы'], ['root_permission_denied', 'Отказано в доступе'], ['root_permission_no_permission', 'У вас нет разрешения на это действие'], diff --git a/webapp/packages/core-localization/src/locales/zh.ts b/webapp/packages/core-localization/src/locales/zh.ts index ecf73a1a19..cee7130839 100644 --- a/webapp/packages/core-localization/src/locales/zh.ts +++ b/webapp/packages/core-localization/src/locales/zh.ts @@ -111,6 +111,7 @@ export default [ ['ui_readonly', '只读'], ['ui_test', 'Test'], ['ui_export', 'Export'], + ['ui_you', 'You'], ['root_permission_denied', '您没有权限'], ['root_permission_no_permission', '您没有权限执行此操作'], diff --git a/webapp/packages/core-theming/src/styles/_form-controls.scss b/webapp/packages/core-theming/src/styles/_form-controls.scss index 6e7be79893..a029b59cf6 100644 --- a/webapp/packages/core-theming/src/styles/_form-controls.scss +++ b/webapp/packages/core-theming/src/styles/_form-controls.scss @@ -26,6 +26,23 @@ overflow: hidden; text-overflow: ellipsis; min-height: 24px; + &[type='search']::-ms-clear { + display: none; + width: 0; + height: 0; + } + &[type='search']::-ms-reveal { + display: none; + width: 0; + height: 0; + } + /* clears the ‘X’ from Chrome */ + &[type='search']::-webkit-search-decoration, + &[type='search']::-webkit-search-cancel-button, + &[type='search']::-webkit-search-results-button, + &[type='search']::-webkit-search-results-decoration { + display: none; + } } input, diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUserList.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUserList.tsx index 6f36938940..af186ae5e1 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUserList.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/GrantedUserList.tsx @@ -26,6 +26,7 @@ import { } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import type { TLocalizationToken } from '@cloudbeaver/core-localization'; +import { ServerConfigResource } from '@cloudbeaver/core-root'; import type { AdminUserInfoFragment } from '@cloudbeaver/core-sdk'; import { getFilteredUsers } from './getFilteredUsers'; @@ -47,6 +48,7 @@ export const GrantedUserList = observer(function GrantedUserList({ grante const translate = useTranslate(); const usersResource = useService(UsersResource); + const serverConfigResource = useService(ServerConfigResource); const [selectedSubjects] = useState>(() => observable(new Map())); const [filterState] = useState(() => observable({ filterValue: '' })); @@ -70,6 +72,14 @@ export const GrantedUserList = observer(function GrantedUserList({ grante } } + function isEditable(userId: string) { + if (serverConfigResource.distributed) { + return true; + } + + return !usersResource.isActiveUser(userId); + } + return (
@@ -82,12 +92,7 @@ export const GrantedUserList = observer(function GrantedUserList({ grante
- !usersResource.isActiveUser(item)} - > +
isEditable(item)}> {tableInfoText && ( @@ -95,20 +100,17 @@ export const GrantedUserList = observer(function GrantedUserList({ grante {translate(tableInfoText)} )} - {users.map(user => { - const activeUser = usersResource.isActiveUser(user.userId); - return ( - - ); - })} + {users.map(user => ( + + ))}
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/UserList.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/UserList.tsx index fdf08fc0da..21cb1e9bbf 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/UserList.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/GrantedUsers/UserList.tsx @@ -25,6 +25,7 @@ import { useTranslate, } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; +import { ServerConfigResource } from '@cloudbeaver/core-root'; import type { AdminUserInfoFragment } from '@cloudbeaver/core-sdk'; import { getFilteredUsers } from './getFilteredUsers'; @@ -46,6 +47,7 @@ export const UserList = observer(function UserList({ userList, grantedUse const translate = useTranslate(); const usersResource = useService(UsersResource); + const serverConfigResource = useService(ServerConfigResource); const [selectedSubjects] = useState>(() => observable(new Map())); const [filterState] = useState(() => observable({ filterValue: '' })); @@ -60,6 +62,14 @@ export const UserList = observer(function UserList({ userList, grantedUse selectedSubjects.clear(); }, []); + function isEditable(userId: string) { + if (serverConfigResource.distributed) { + return true; + } + + return !usersResource.isActiveUser(userId); + } + return (
@@ -73,7 +83,7 @@ export const UserList = observer(function UserList({ userList, grantedUse className={s(styles, { table: true })} keys={keys} selectedItems={selectedSubjects} - isItemSelectable={item => !(usersResource.isActiveUser(item) || grantedUsers.includes(item))} + isItemSelectable={item => isEditable(item) && !grantedUsers.includes(item)} > @@ -82,20 +92,17 @@ export const UserList = observer(function UserList({ userList, grantedUse {translate('ui_search_no_result_placeholder')} )} - {users.map(user => { - const activeUser = usersResource.isActiveUser(user.userId); - return ( - - ); - })} + {users.map(user => ( + + ))}
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx index ec997bd6e7..e813c5b928 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/User.tsx @@ -36,7 +36,6 @@ interface Props { export const User = observer(function User({ user, displayAuthRole, selectable }) { const usersAdministrationService = useService(UsersAdministrationService); - const teams = user.grantedTeams.join(', '); const usersService = useService(UsersResource); const notificationService = useService(NotificationService); const administrationUsersManagementService = useService(AdministrationUsersManagementService); @@ -57,6 +56,7 @@ export const User = observer(function User({ user, displayAuthRole, selec : undefined; const userManagementDisabled = administrationUsersManagementService.externalUserProviderEnabled; + const teams = user.grantedTeams.join(', '); return ( diff --git a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ProviderPropertiesForm.tsx b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ProviderPropertiesForm.tsx index 24125b1345..5b612dc04d 100644 --- a/webapp/packages/plugin-connections/src/ConnectionForm/Options/ProviderPropertiesForm.tsx +++ b/webapp/packages/plugin-connections/src/ConnectionForm/Options/ProviderPropertiesForm.tsx @@ -15,7 +15,6 @@ import { GroupTitle, InputField, ObjectPropertyInfoForm, - useCustomInputValidation, useObjectPropertyCategories, useTranslate, } from '@cloudbeaver/core-blocks'; @@ -31,6 +30,9 @@ interface Props { } const MAX_KEEP_ALIVE_INTERVAL_IN_SECONDS = 32767; +const DEFAULT_CONFIG: ConnectionConfig = { + keepAliveInterval: 0, +}; export const ProviderPropertiesForm = observer(function ProviderPropertiesForm({ config, properties, disabled, readonly }) { const translate = useTranslate(); @@ -85,9 +87,9 @@ export const ProviderPropertiesForm = observer(function ProviderPropertie name="keepAliveInterval" disabled={disabled} readOnly={readonly} - defaultValue={config?.keepAliveInterval ?? 0} title={translate('connections_connection_keep_alive_tooltip')} state={config} + defaultState={DEFAULT_CONFIG} > {translate('connections_connection_keep_alive')} diff --git a/webapp/packages/plugin-devtools/package.json b/webapp/packages/plugin-devtools/package.json index 6473e7b519..024ae52605 100644 --- a/webapp/packages/plugin-devtools/package.json +++ b/webapp/packages/plugin-devtools/package.json @@ -29,12 +29,12 @@ "@cloudbeaver/plugin-user-profile": "~0.1.0", "mobx": "^6.12.0", "mobx-react-lite": "^4.0.5", - "react": "^18.2.0", - "reshadow": "^0.0.1" + "react": "^18.2.0" }, "peerDependencies": {}, "devDependencies": { "@types/react": "^18.2.42", - "typescript": "^5.3.2" + "typescript": "^5.3.2", + "typescript-plugin-css-modules": "^5.0.2" } } diff --git a/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.m.css b/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.m.css new file mode 100644 index 0000000000..1fad1e69ee --- /dev/null +++ b/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.m.css @@ -0,0 +1,3 @@ +.searchBox { + padding: 8px 12px; +} diff --git a/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.tsx b/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.tsx index 93947cf69e..6c76a8351a 100644 --- a/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.tsx +++ b/webapp/packages/plugin-devtools/src/ContextMenu/SearchResourceMenuItemComponent.tsx @@ -6,41 +6,36 @@ * you may not use this file except in compliance with the License. */ import { observer } from 'mobx-react-lite'; -import styled, { css } from 'reshadow'; -import { useStyles } from '@cloudbeaver/core-blocks'; +import { s, useS } from '@cloudbeaver/core-blocks'; import type { IContextMenuItemProps } from '@cloudbeaver/core-ui'; import type { ICustomMenuItemComponent } from '@cloudbeaver/core-view'; import { DATA_CONTEXT_MENU_SEARCH } from './DATA_CONTEXT_MENU_SEARCH'; - -const styles = css` - search-box { - padding: 8px 12px; - } -`; +import styles from './SearchResourceMenuItemComponent.m.css'; export const SearchResourceMenuItemComponent: ICustomMenuItemComponent = observer(function SearchResourceMenuItemComponent({ item, onClick, menuData, className, - style, }) { + const style = useS(styles); const value = menuData.context.tryGet(DATA_CONTEXT_MENU_SEARCH) ?? ''; function handleChange(value: string) { menuData.context.set(DATA_CONTEXT_MENU_SEARCH, value); } - return styled(useStyles(style, styles))( - + return ( +
handleChange(event.target.value)} /> - , +
); }); diff --git a/webapp/packages/product-default/package.json b/webapp/packages/product-default/package.json index 2a870dd88a..aad94b1489 100644 --- a/webapp/packages/product-default/package.json +++ b/webapp/packages/product-default/package.json @@ -5,7 +5,7 @@ "src/**/*.scss", "public/**/*" ], - "version": "23.3.5", + "version": "24.0.0", "description": "CloudBeaver Community", "license": "Apache-2.0", "main": "dist/index.js",