mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Merge branch 'devel' into 10205-fix-high-cve-in-nanoid-and-image-size-libraries
This commit is contained in:
+44
-1
@@ -17,7 +17,8 @@ import {
|
||||
getObjectPropertyValueType,
|
||||
type IObjectPropertyInfo,
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
import { EMPTY_ARRAY, removeMetadataFromDataURL } from '@cloudbeaver/core-utils';
|
||||
import { EMPTY_ARRAY, getTextFileReadingProcess, removeMetadataFromDataURL } from '@cloudbeaver/core-utils';
|
||||
import { clsx } from '@dbeaver/ui-kit';
|
||||
|
||||
import { FieldCheckbox } from '../../FormControls/Checkboxes/FieldCheckbox.js';
|
||||
import { Select } from '../../FormControls/Select.js';
|
||||
@@ -30,6 +31,8 @@ import { Link } from '../../Link.js';
|
||||
import { useTranslate } from '../../localization/useTranslate.js';
|
||||
import { evaluate } from '../evaluate.js';
|
||||
import { SAVED_VALUE_INDICATOR } from '../../SAVED_VALUE_INDICATOR.js';
|
||||
import { UploadArea } from '../../UploadArea.js';
|
||||
import { Button } from '../../Button.js';
|
||||
|
||||
interface RenderFieldProps {
|
||||
property: IObjectPropertyInfo;
|
||||
@@ -204,6 +207,46 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
);
|
||||
}
|
||||
|
||||
if (controlType === 'uploadable-textarea' && state && property.id) {
|
||||
async function handleFileUpload(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
const file = event.target.files?.[0];
|
||||
|
||||
if (!file) {
|
||||
throw new Error('File is not found');
|
||||
}
|
||||
|
||||
const process = getTextFileReadingProcess(file);
|
||||
const result = await process.promise;
|
||||
|
||||
if (state && property.id) {
|
||||
state[property.id] = result;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="tw:flex tw:flex-col tw:gap-2">
|
||||
<Textarea
|
||||
required={required}
|
||||
title={state[property.id]}
|
||||
labelTooltip={property.description || property.displayName}
|
||||
placeholder={placeholder}
|
||||
name={property.id}
|
||||
state={state}
|
||||
disabled={disabled}
|
||||
readOnly={readonly}
|
||||
className={clsx('tw:flex-0!', className)}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</Textarea>
|
||||
<UploadArea disabled={disabled || readonly} reset onChange={handleFileUpload}>
|
||||
<Button className="tw:w-max" tag="div" disabled={disabled || readonly} variant="secondary">
|
||||
{translate('ui_file')}
|
||||
</Button>
|
||||
</UploadArea>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (controlType === 'file' && state) {
|
||||
return (
|
||||
<InputFileTextContent
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
*/
|
||||
import type { IObjectPropertyInfo } from './IObjectPropertyInfo.js';
|
||||
|
||||
export type ObjectPropertyType = 'checkbox' | 'selector' | 'link' | 'textarea' | 'file' | 'input';
|
||||
export type ObjectPropertyType = 'checkbox' | 'selector' | 'link' | 'textarea' | 'file' | 'input' | 'uploadable-textarea';
|
||||
|
||||
export function getObjectPropertyType(property: IObjectPropertyInfo): ObjectPropertyType {
|
||||
const dataType = property.dataType?.toLowerCase();
|
||||
const isTextarea = dataType === 'string' && property.length === 'MULTILINE';
|
||||
const isFile = property.features.includes('file');
|
||||
|
||||
if (dataType === 'boolean') {
|
||||
return 'checkbox';
|
||||
@@ -18,9 +20,11 @@ export function getObjectPropertyType(property: IObjectPropertyInfo): ObjectProp
|
||||
return 'selector';
|
||||
} else if (property.features.includes('href')) {
|
||||
return 'link';
|
||||
} else if (dataType === 'string' && property.length === 'MULTILINE') {
|
||||
} else if (isTextarea && isFile) {
|
||||
return 'uploadable-textarea';
|
||||
} else if (isTextarea) {
|
||||
return 'textarea';
|
||||
} else if (property.features.includes('file')) {
|
||||
} else if (isFile) {
|
||||
return 'file';
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -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,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');
|
||||
@@ -33,15 +34,25 @@ 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 IUsersActionButtonProps {
|
||||
filters: IUserFilters;
|
||||
}
|
||||
|
||||
@injectable(() => [AdministrationItemService, CreateUserService, TeamsResource, CreateTeamService, UsersResource, CommonDialogService])
|
||||
export class UsersAdministrationService extends Bootstrap {
|
||||
readonly tabsContainer: TabsContainer;
|
||||
readonly userDetailsInfoPlaceholder: PlaceholderContainer<IUserDetailsInfoProps>;
|
||||
readonly informationPlaceholder: PlaceholderContainer;
|
||||
readonly actionButtonsPlaceholder: PlaceholderContainer<IUsersActionButtonProps>;
|
||||
administrationItem!: IAdministrationItem;
|
||||
|
||||
constructor(
|
||||
@@ -56,6 +67,7 @@ export class UsersAdministrationService extends Bootstrap {
|
||||
this.userDetailsInfoPlaceholder = new PlaceholderContainer();
|
||||
this.tabsContainer = new TabsContainer('Access Control');
|
||||
this.informationPlaceholder = new PlaceholderContainer();
|
||||
this.actionButtonsPlaceholder = new PlaceholderContainer();
|
||||
}
|
||||
|
||||
override register(): void {
|
||||
@@ -83,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) {
|
||||
|
||||
+29
@@ -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<IFiltersActionButtonProps>(function FiltersActionButton({ active, className, size = 'small', ...rest }) {
|
||||
return (
|
||||
<div className={BUTTON_BOX_CLASS_NAME}>
|
||||
<IconButton className={clsx(BUTTON_CLASS_NAME, active && 'tw:bg-(--theme-secondary)!', className)} size={size} {...rest} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
+32
@@ -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<IUsersActionButtonProps>(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 (
|
||||
<FiltersActionButton active={openContext.open} aria-label={label} title={label} onClick={openContext.onToggle}>
|
||||
<IconOrImage className="tw:w-full tw:h-full" icon="filter" />
|
||||
</FiltersActionButton>
|
||||
);
|
||||
});
|
||||
+3
-35
@@ -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;
|
||||
@@ -16,31 +8,7 @@
|
||||
}
|
||||
|
||||
.actions {
|
||||
composes: theme-form-element-radius theme-background-surface theme-text-on-surface theme theme-border-color-background from global;
|
||||
box-sizing: border-box;
|
||||
border: 2px solid;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.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%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
+11
-11
@@ -6,14 +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, 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;
|
||||
@@ -22,8 +24,11 @@ interface Props {
|
||||
export const UsersTableFilters = observer<Props>(function UsersTableFilters({ filters }) {
|
||||
const translate = useTranslate();
|
||||
const style = useS(styles);
|
||||
const usersAdministrationService = useService(UsersAdministrationService);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const onToggle = useCallback(() => setOpen(open => !open), []);
|
||||
const openContext = useMemo(() => ({ open, onToggle }), [open, onToggle]);
|
||||
|
||||
return (
|
||||
<Group parent compact gap>
|
||||
@@ -35,14 +40,9 @@ export const UsersTableFilters = observer<Props>(function UsersTableFilters({ fi
|
||||
onChange={filters.setSearch}
|
||||
/>
|
||||
<div className={s(style, { actions: true })}>
|
||||
<IconButton
|
||||
className={s(style, { button: true, buttonActive: open })}
|
||||
size="small"
|
||||
aria-label={translate('authentication_administration_users_filters_filter_label')}
|
||||
onClick={() => setOpen(!open)}
|
||||
>
|
||||
<IconOrImage className={s(style, { iconOrImage: true })} icon="filter" />
|
||||
</IconButton>
|
||||
<UsersTableFiltersOpenContext.Provider value={openContext}>
|
||||
<Placeholder container={usersAdministrationService.actionButtonsPlaceholder} filters={filters} />
|
||||
</UsersTableFiltersOpenContext.Provider>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+15
@@ -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<IUsersTableFiltersOpenContext | null>(null);
|
||||
@@ -22,3 +22,5 @@ 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';
|
||||
export * from './Administration/Users/UsersTable/Filters/FiltersActionButton.js';
|
||||
|
||||
Reference in New Issue
Block a user