mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
Merge pull request #510 from dbeaver/fix/remove-html-sanitizer
fix(core-blocks): CB-218, CB-1321 remove html-sanitizer and old compo…
This commit is contained in:
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import { useCallback } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button, TextareaNew, useClipboard } from '@cloudbeaver/core-blocks';
|
||||
import { Button, Textarea, useClipboard } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
|
||||
import type { ILogEntry } from './ILogEntry';
|
||||
@@ -53,7 +53,7 @@ const styles = css`
|
||||
type, message {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
TextareaNew {
|
||||
Textarea {
|
||||
flex: 1;
|
||||
}
|
||||
`;
|
||||
@@ -91,7 +91,7 @@ export const LogViewerInfoPanel = observer<Props>(function LogViewerInfoPanel({
|
||||
<content-wrapper>
|
||||
<type as='h2'>{typeInfo}</type>
|
||||
<message title={selectedItem.message}>{selectedItem.message}</message>
|
||||
<TextareaNew
|
||||
<Textarea
|
||||
name="value"
|
||||
rows={3}
|
||||
value={selectedItem.stackTrace}
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
"lint-fix": "eslint ./src/ --ext .ts,.tsx --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"go-split": "^2.x.x",
|
||||
"sanitize-html": "^1.x.x",
|
||||
"react-sanitized-html": "^2.x.x"
|
||||
"go-split": "^2.x.x"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cloudbeaver/core-di": "^0.1.0",
|
||||
|
||||
@@ -121,17 +121,17 @@ export const CheckboxMarkup: React.FC<ICheckboxMarkupProps> = function CheckboxM
|
||||
style
|
||||
)
|
||||
)(
|
||||
<checkbox-container className={className} title={title} as='div'>
|
||||
<checkbox as='div'>
|
||||
<checkbox-container className={className} title={title}>
|
||||
<checkbox>
|
||||
<checkbox-input as='input' type='checkbox' {...rest} id={id || rest.name} />
|
||||
<checkbox-background as='div'>
|
||||
<checkbox-background>
|
||||
<checkbox-checkmark as='svg' viewBox='0 0 24 24'>
|
||||
<checkbox-checkmark-path as='path' fill='none' d='M1.73,12.91 8.1,19.28 22.79,4.59' />
|
||||
</checkbox-checkmark>
|
||||
<checkbox-mixedmark as='div' />
|
||||
<checkbox-mixedmark />
|
||||
</checkbox-background>
|
||||
{ripple && (
|
||||
<checkbox-ripple as='div' />
|
||||
<checkbox-ripple />
|
||||
)}
|
||||
</checkbox>
|
||||
{label && (id || rest.name) && <checkbox-label as='label' htmlFor={id || rest.name}>{label}</checkbox-label>}
|
||||
|
||||
@@ -14,10 +14,25 @@ import { baseFormControlStyles } from '../baseFormControlStyles';
|
||||
import { isControlPresented } from '../isControlPresented';
|
||||
import { Checkbox, CheckboxBaseProps, CheckboxType, ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox';
|
||||
|
||||
const fieldCheckboxStyles = css`
|
||||
const style = css`
|
||||
Checkbox {
|
||||
margin: -10px;
|
||||
}
|
||||
field {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
field-label {
|
||||
composes: theme-typography--body2 from global;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding-left: 10px;
|
||||
line-height: 16px;
|
||||
}
|
||||
Checkbox[disabled] + field-label {
|
||||
cursor: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FieldCheckbox: CheckboxType = function FieldCheckbox({
|
||||
@@ -25,16 +40,22 @@ export const FieldCheckbox: CheckboxType = function FieldCheckbox({
|
||||
className,
|
||||
...rest
|
||||
}: CheckboxBaseProps & (ICheckboxControlledProps | ICheckboxObjectProps<any>)) {
|
||||
const styles = useStyles(baseFormControlStyles, fieldCheckboxStyles);
|
||||
const styles = useStyles(baseFormControlStyles, style);
|
||||
|
||||
if (rest.autoHide && !isControlPresented(rest.name, rest.state)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return styled(styles)(
|
||||
<field className={className} as="div">
|
||||
<field-label as="div">{children}</field-label>
|
||||
<field className={className}>
|
||||
<Checkbox {...(rest as CheckboxBaseProps & ICheckboxControlledProps)} />
|
||||
<field-label
|
||||
htmlFor={rest.id || rest.name}
|
||||
title={rest.title}
|
||||
as="label"
|
||||
>
|
||||
{children}
|
||||
</field-label>
|
||||
</field>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 styled, { css } from 'reshadow';
|
||||
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { baseFormControlStylesNew } from '../baseFormControlStylesNew';
|
||||
import { isControlPresented } from '../isControlPresented';
|
||||
import { Checkbox, CheckboxBaseProps, CheckboxType, ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox';
|
||||
|
||||
const fieldCheckboxStyles = css`
|
||||
Checkbox {
|
||||
margin: -10px;
|
||||
}
|
||||
field {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
field-label {
|
||||
composes: theme-typography--body2 from global;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
padding-left: 10px;
|
||||
line-height: 16px;
|
||||
}
|
||||
Checkbox[disabled] + field-label {
|
||||
cursor: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FieldCheckboxNew: CheckboxType = function FieldCheckboxNew({
|
||||
children,
|
||||
className,
|
||||
...rest
|
||||
}: CheckboxBaseProps & (ICheckboxControlledProps | ICheckboxObjectProps<any>)) {
|
||||
const styles = useStyles(baseFormControlStylesNew, fieldCheckboxStyles);
|
||||
|
||||
if (rest.autoHide && !isControlPresented(rest.name, rest.state)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return styled(styles)(
|
||||
<field className={className}>
|
||||
<Checkbox {...(rest as CheckboxBaseProps & ICheckboxControlledProps)} />
|
||||
<field-label
|
||||
htmlFor={rest.id || rest.name}
|
||||
title={rest.title}
|
||||
as="label"
|
||||
>
|
||||
{children}
|
||||
</field-label>
|
||||
</field>
|
||||
);
|
||||
};
|
||||
@@ -11,6 +11,7 @@ import styled, { css } from 'reshadow';
|
||||
|
||||
import { useStyles, composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { filterLayoutFakeProps } from '../../Containers/filterLayoutFakeProps';
|
||||
import { baseFormControlStyles } from '../baseFormControlStyles';
|
||||
import { isControlPresented } from '../isControlPresented';
|
||||
import type { ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox';
|
||||
@@ -18,34 +19,39 @@ import { useCheckboxState } from './useCheckboxState';
|
||||
|
||||
const switchStyles = composes(
|
||||
css`
|
||||
switch-control {
|
||||
composes: theme-switch from global;
|
||||
}
|
||||
switch-control-track {
|
||||
composes: theme-switch__track from global;
|
||||
}
|
||||
switch-input {
|
||||
composes: theme-switch_native-control from global;
|
||||
}
|
||||
switch-control-underlay {
|
||||
composes: theme-switch__thumb-underlay from global;
|
||||
}
|
||||
switch-control-thumb {
|
||||
composes: theme-switch__thumb from global;
|
||||
}
|
||||
radio-ripple {
|
||||
composes: theme-radio_ripple from global;
|
||||
}
|
||||
switch-control {
|
||||
composes: theme-switch from global;
|
||||
}
|
||||
switch-control-track {
|
||||
composes: theme-switch__track from global;
|
||||
}
|
||||
switch-input {
|
||||
composes: theme-switch_native-control from global;
|
||||
}
|
||||
switch-control-underlay {
|
||||
composes: theme-switch__thumb-underlay from global;
|
||||
}
|
||||
switch-control-thumb {
|
||||
composes: theme-switch__thumb from global;
|
||||
}
|
||||
radio-ripple {
|
||||
composes: theme-radio_ripple from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
field {
|
||||
max-width: 450px;
|
||||
switch-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
field label {
|
||||
width: auto;
|
||||
}
|
||||
switch-control {
|
||||
margin-left: 2px;
|
||||
field-label {
|
||||
composes: theme-typography--body1 from global;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
display: block;
|
||||
padding-left: 18px;
|
||||
min-width: 50px;
|
||||
white-space: pre-wrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
`
|
||||
);
|
||||
@@ -79,7 +85,7 @@ const switchState = {
|
||||
|
||||
interface IBaseProps {
|
||||
mod?: Array<keyof typeof switchMod>;
|
||||
description?: string;
|
||||
description?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface SwitchType {
|
||||
@@ -91,7 +97,6 @@ export const Switch: SwitchType = observer(function Switch({
|
||||
name,
|
||||
value,
|
||||
defaultValue,
|
||||
label,
|
||||
description,
|
||||
state,
|
||||
checked,
|
||||
@@ -113,6 +118,7 @@ export const Switch: SwitchType = observer(function Switch({
|
||||
name,
|
||||
onChange,
|
||||
});
|
||||
rest = filterLayoutFakeProps(rest);
|
||||
const styles = useStyles(
|
||||
baseFormControlStyles,
|
||||
switchStyles,
|
||||
@@ -126,27 +132,28 @@ export const Switch: SwitchType = observer(function Switch({
|
||||
}
|
||||
|
||||
return styled(styles)(
|
||||
<field as="div" className={className}>
|
||||
<field-label as="div">{children}</field-label>
|
||||
<switch-control as='div'>
|
||||
<switch-control-track as='div' />
|
||||
<switch-control-underlay as='div'>
|
||||
<switch-control-thumb as='div' />
|
||||
<switch-input
|
||||
as='input'
|
||||
{...rest}
|
||||
type="checkbox"
|
||||
id={value || name}
|
||||
role="switch"
|
||||
aria-checked={checkboxState.checked}
|
||||
checked={checkboxState.checked}
|
||||
disabled={disabled}
|
||||
onChange={checkboxState.change}
|
||||
/>
|
||||
</switch-control-underlay>
|
||||
</switch-control>
|
||||
<label htmlFor={value || name}>{label}</label>
|
||||
<field-description as='div'>{description}</field-description>
|
||||
<field className={className}>
|
||||
<switch-body>
|
||||
<switch-control>
|
||||
<switch-control-track />
|
||||
<switch-control-underlay>
|
||||
<switch-control-thumb />
|
||||
<switch-input
|
||||
as='input'
|
||||
{...rest}
|
||||
type="checkbox"
|
||||
id={value || name}
|
||||
role="switch"
|
||||
aria-checked={checkboxState.checked}
|
||||
checked={checkboxState.checked}
|
||||
disabled={disabled}
|
||||
onChange={checkboxState.change}
|
||||
/>
|
||||
</switch-control-underlay>
|
||||
</switch-control>
|
||||
<field-label as="label" htmlFor={value || name}>{children}</field-label>
|
||||
</switch-body>
|
||||
<field-description>{description}</field-description>
|
||||
</field>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 styled, { css } from 'reshadow';
|
||||
|
||||
import { useStyles, composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { filterLayoutFakeProps } from '../../Containers/filterLayoutFakeProps';
|
||||
import { baseFormControlStylesNew } from '../baseFormControlStylesNew';
|
||||
import { isControlPresented } from '../isControlPresented';
|
||||
import type { ICheckboxControlledProps, ICheckboxObjectProps } from './Checkbox';
|
||||
import { useCheckboxState } from './useCheckboxState';
|
||||
|
||||
const switchStyles = composes(
|
||||
css`
|
||||
switch-control {
|
||||
composes: theme-switch from global;
|
||||
}
|
||||
switch-control-track {
|
||||
composes: theme-switch__track from global;
|
||||
}
|
||||
switch-input {
|
||||
composes: theme-switch_native-control from global;
|
||||
}
|
||||
switch-control-underlay {
|
||||
composes: theme-switch__thumb-underlay from global;
|
||||
}
|
||||
switch-control-thumb {
|
||||
composes: theme-switch__thumb from global;
|
||||
}
|
||||
radio-ripple {
|
||||
composes: theme-radio_ripple from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
switch-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
field-label {
|
||||
composes: theme-typography--body1 from global;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
display: block;
|
||||
padding-left: 18px;
|
||||
min-width: 50px;
|
||||
white-space: pre-wrap;
|
||||
font-weight: 500;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
const switchMod = {
|
||||
primary: composes(
|
||||
css`
|
||||
switch-control {
|
||||
composes: theme-switch_primary from global;
|
||||
}
|
||||
`
|
||||
),
|
||||
};
|
||||
|
||||
const switchState = {
|
||||
disabled: composes(
|
||||
css`
|
||||
switch-control {
|
||||
composes: theme-switch--disabled from global;
|
||||
}
|
||||
`
|
||||
),
|
||||
checked: composes(
|
||||
css`
|
||||
switch-control {
|
||||
composes: theme-switch--checked from global;
|
||||
}
|
||||
`
|
||||
),
|
||||
};
|
||||
|
||||
interface IBaseProps {
|
||||
mod?: Array<keyof typeof switchMod>;
|
||||
description?: React.ReactNode;
|
||||
}
|
||||
|
||||
interface SwitchType {
|
||||
(props: IBaseProps & ICheckboxControlledProps): React.ReactElement<any, any> | null;
|
||||
<TKey extends string>(props: IBaseProps & ICheckboxObjectProps<TKey>): React.ReactElement<any, any> | null;
|
||||
}
|
||||
|
||||
export const SwitchNew: SwitchType = observer(function SwitchNew({
|
||||
name,
|
||||
value,
|
||||
defaultValue,
|
||||
description,
|
||||
state,
|
||||
checked,
|
||||
defaultChecked,
|
||||
className,
|
||||
children,
|
||||
onChange,
|
||||
mod = [],
|
||||
autoHide,
|
||||
disabled,
|
||||
...rest
|
||||
}: IBaseProps & (ICheckboxControlledProps | ICheckboxObjectProps<any>)) {
|
||||
const checkboxState = useCheckboxState({
|
||||
value,
|
||||
defaultValue,
|
||||
checked,
|
||||
defaultChecked,
|
||||
state,
|
||||
name,
|
||||
onChange,
|
||||
});
|
||||
rest = filterLayoutFakeProps(rest);
|
||||
const styles = useStyles(
|
||||
baseFormControlStylesNew,
|
||||
switchStyles,
|
||||
...mod.map(mod => switchMod[mod]),
|
||||
disabled && switchState.disabled,
|
||||
checkboxState.checked && switchState.checked
|
||||
);
|
||||
|
||||
if (autoHide && !isControlPresented(name, state)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return styled(styles)(
|
||||
<field className={className}>
|
||||
<switch-body>
|
||||
<switch-control>
|
||||
<switch-control-track />
|
||||
<switch-control-underlay>
|
||||
<switch-control-thumb />
|
||||
<switch-input
|
||||
as='input'
|
||||
{...rest}
|
||||
type="checkbox"
|
||||
id={value || name}
|
||||
role="switch"
|
||||
aria-checked={checkboxState.checked}
|
||||
checked={checkboxState.checked}
|
||||
disabled={disabled}
|
||||
onChange={checkboxState.change}
|
||||
/>
|
||||
</switch-control-underlay>
|
||||
</switch-control>
|
||||
<field-label as="label" htmlFor={value || name}>{children}</field-label>
|
||||
</switch-body>
|
||||
<field-description>{description}</field-description>
|
||||
</field>
|
||||
);
|
||||
});
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import {
|
||||
useLayoutEffect, useCallback, useState, useRef, useContext
|
||||
useLayoutEffect, useCallback, useState, useRef, useContext, useEffect
|
||||
} from 'react';
|
||||
import {
|
||||
useMenuState,
|
||||
@@ -20,6 +20,8 @@ import styled, { css, use } from 'reshadow';
|
||||
|
||||
import { useStyles, composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { filterLayoutFakeProps } from '../Containers/filterLayoutFakeProps';
|
||||
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
|
||||
import { Icon } from '../Icon';
|
||||
import { IconButton } from '../IconButton';
|
||||
import { baseFormControlStyles } from './baseFormControlStyles';
|
||||
@@ -30,7 +32,7 @@ const styles = composes(
|
||||
Menu {
|
||||
composes: theme-text-on-surface theme-background-surface from global;
|
||||
}
|
||||
MenuItem, MenuButton {
|
||||
MenuItem {
|
||||
composes: theme-ripple from global;
|
||||
}
|
||||
`,
|
||||
@@ -38,11 +40,25 @@ const styles = composes(
|
||||
field input {
|
||||
margin: 0;
|
||||
}
|
||||
field-label {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
}
|
||||
input {
|
||||
padding-right: 12px !important;
|
||||
}
|
||||
MenuButton {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
@@ -59,7 +75,7 @@ const styles = composes(
|
||||
& MenuItem {
|
||||
background: transparent;
|
||||
display: block;
|
||||
padding: 4px 36px;
|
||||
padding: 4px 12px;
|
||||
text-align: left;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
@@ -82,12 +98,11 @@ const styles = composes(
|
||||
`
|
||||
);
|
||||
|
||||
type BaseProps<TKey, TValue> = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onSelect' | 'name' | 'value'> & {
|
||||
type BaseProps<TKey, TValue> = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onSelect' | 'name' | 'value' | 'defaultValue'> & ILayoutSizeProps & {
|
||||
propertyName?: string;
|
||||
items: TValue[];
|
||||
mod?: 'surface';
|
||||
long?: boolean;
|
||||
searchable?: boolean;
|
||||
defaultValue?: string;
|
||||
keySelector: (item: TValue) => TKey;
|
||||
valueSelector: (item: TValue) => string;
|
||||
onSwitch?: (state: boolean) => void;
|
||||
@@ -98,7 +113,6 @@ type ControlledProps<TKey, TValue> = BaseProps<TKey, TValue> & {
|
||||
value?: string;
|
||||
onSelect?: (value: TKey, name: string | undefined, prev: TKey) => void;
|
||||
onChange?: (value: string, name: string | undefined) => any;
|
||||
|
||||
state?: never;
|
||||
};
|
||||
|
||||
@@ -107,7 +121,6 @@ type ObjectProps<TValue, TKey extends keyof TState, TState> = BaseProps<TState[T
|
||||
state: TState;
|
||||
onSelect?: (value: TState[TKey], name: TKey | undefined, prev: TState[TKey]) => void;
|
||||
onChange?: (value: string, name: TKey | undefined) => any;
|
||||
|
||||
value?: never;
|
||||
};
|
||||
|
||||
@@ -118,6 +131,7 @@ interface ComboboxType {
|
||||
|
||||
export const Combobox: ComboboxType = observer(function Combobox({
|
||||
value: controlledValue,
|
||||
defaultValue,
|
||||
name,
|
||||
state,
|
||||
propertyName,
|
||||
@@ -125,10 +139,9 @@ export const Combobox: ComboboxType = observer(function Combobox({
|
||||
children,
|
||||
title,
|
||||
className,
|
||||
mod,
|
||||
long,
|
||||
searchable,
|
||||
readOnly,
|
||||
disabled,
|
||||
keySelector = v => v,
|
||||
valueSelector = v => v,
|
||||
onChange = () => {},
|
||||
@@ -136,6 +149,7 @@ export const Combobox: ComboboxType = observer(function Combobox({
|
||||
onSwitch,
|
||||
...rest
|
||||
}: ControlledProps<any, any> | ObjectProps<any, any, any>) {
|
||||
rest = filterLayoutFakeProps(rest);
|
||||
const context = useContext(FormContext);
|
||||
const ref = useRef<HTMLInputElement>(null);
|
||||
const menu = useMenuState({
|
||||
@@ -143,15 +157,19 @@ export const Combobox: ComboboxType = observer(function Combobox({
|
||||
currentId: null,
|
||||
gutter: 4,
|
||||
});
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
let value: string | number | readonly string[] | undefined = controlledValue;
|
||||
const [searchValue, setSearchValue] = useState<string | null>(null);
|
||||
let value: string | number | readonly string[] | undefined = controlledValue ?? defaultValue ?? undefined;
|
||||
|
||||
if (state) {
|
||||
if (name in state) {
|
||||
value = state[name];
|
||||
} else if (rest.defaultValue !== undefined) {
|
||||
value = rest.defaultValue;
|
||||
}
|
||||
if (state && name !== undefined && name in state) {
|
||||
value = state[name];
|
||||
}
|
||||
|
||||
const selectedItem = items.find(item => keySelector(item) === value);
|
||||
|
||||
let inputValue = (selectedItem ? valueSelector(selectedItem) : searchValue) ?? '';
|
||||
|
||||
if (searchValue !== null && selectedItem && valueSelector(selectedItem) !== searchValue) {
|
||||
inputValue = searchValue;
|
||||
}
|
||||
|
||||
const handleChange = useCallback(
|
||||
@@ -175,7 +193,7 @@ export const Combobox: ComboboxType = observer(function Combobox({
|
||||
if (context) {
|
||||
context.change(null, name);
|
||||
}
|
||||
setSearchValue('');
|
||||
setSearchValue(null);
|
||||
},
|
||||
[value, state, name, menu, context, onSelect]
|
||||
);
|
||||
@@ -193,55 +211,55 @@ export const Combobox: ComboboxType = observer(function Combobox({
|
||||
if (context) {
|
||||
context.change(id, name);
|
||||
}
|
||||
setSearchValue(null);
|
||||
},
|
||||
[value, state, name, menu, context, onSelect]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current === document.activeElement && inputValue === searchValue) {
|
||||
menu.show();
|
||||
}
|
||||
});
|
||||
|
||||
useLayoutEffect(() => onSwitch?.(menu.visible), [onSwitch, menu.visible]);
|
||||
|
||||
const selectedItem = items.find(item => keySelector(item) === value);
|
||||
const filteredItems = items.filter(
|
||||
item => selectedItem || !searchValue || valueSelector(item).toUpperCase().includes(searchValue.toUpperCase())
|
||||
item => !searchValue || valueSelector(item).toUpperCase().includes(searchValue.toUpperCase())
|
||||
);
|
||||
|
||||
if (ref.current === document.activeElement && !selectedItem && searchValue) {
|
||||
menu.show();
|
||||
}
|
||||
|
||||
return styled(useStyles(baseFormControlStyles, styles))(
|
||||
<field as="div" className={className} {...use({ long })}>
|
||||
<field-label title={title} as='label'>{children}</field-label>
|
||||
<input-box as="div">
|
||||
<field className={className}>
|
||||
<field-label title={title} as='label'>{children}{rest.required && ' *'}</field-label>
|
||||
<input-box>
|
||||
<input
|
||||
ref={ref}
|
||||
role='new'
|
||||
autoComplete="off"
|
||||
name={name}
|
||||
title={title}
|
||||
value={selectedItem ? valueSelector(selectedItem) : searchValue}
|
||||
readOnly={!!selectedItem || readOnly}
|
||||
value={inputValue}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
onChange={handleChange}
|
||||
{...use({ mod })}
|
||||
{...rest}
|
||||
/>
|
||||
{(selectedItem && !readOnly && searchable) && (
|
||||
<IconButton type="button" name="reject" viewBox="0 0 11 11" onClick={handleRemove} />
|
||||
)}
|
||||
{!readOnly && (
|
||||
<>
|
||||
<MenuButton {...menu}><Icon name="arrow" viewBox="0 0 16 16" {...use({ focus: menu.visible })} /></MenuButton>
|
||||
<Menu
|
||||
{...menu}
|
||||
aria-label={propertyName}
|
||||
unstable_initialFocusRef={ref}
|
||||
unstable_finalFocusRef={ref}
|
||||
>
|
||||
{filteredItems.map(item => (
|
||||
<MenuItem key={keySelector(item)} id={keySelector(item)} type='button' {...menu} onClick={handleMenuSelect}>
|
||||
{valueSelector(item)}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</>
|
||||
)}
|
||||
<MenuButton {...menu} disabled={readOnly || disabled}><Icon name="arrow" viewBox="0 0 16 16" {...use({ focus: menu.visible })} /></MenuButton>
|
||||
<Menu
|
||||
{...menu}
|
||||
aria-label={propertyName}
|
||||
unstable_initialFocusRef={ref}
|
||||
unstable_finalFocusRef={ref}
|
||||
>
|
||||
{filteredItems.map(item => (
|
||||
<MenuItem key={keySelector(item)} id={keySelector(item)} type='button' {...menu} onClick={handleMenuSelect}>
|
||||
{valueSelector(item)}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</input-box>
|
||||
</field>
|
||||
);
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 {
|
||||
useLayoutEffect, useCallback, useState, useRef, useContext, useEffect
|
||||
} from 'react';
|
||||
import {
|
||||
useMenuState,
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuButton
|
||||
} from 'reakit/Menu';
|
||||
import styled, { css, use } from 'reshadow';
|
||||
|
||||
import { useStyles, composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { filterLayoutFakeProps } from '../Containers/filterLayoutFakeProps';
|
||||
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
|
||||
import { Icon } from '../Icon';
|
||||
import { IconButton } from '../IconButton';
|
||||
import { baseFormControlStylesNew } from './baseFormControlStylesNew';
|
||||
import { FormContext } from './FormContext';
|
||||
|
||||
const styles = composes(
|
||||
css`
|
||||
Menu {
|
||||
composes: theme-text-on-surface theme-background-surface from global;
|
||||
}
|
||||
MenuItem {
|
||||
composes: theme-ripple from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
field input {
|
||||
margin: 0;
|
||||
}
|
||||
field-label {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
}
|
||||
input {
|
||||
padding-right: 12px !important;
|
||||
}
|
||||
MenuButton {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
composes: theme-typography--caption theme-elevation-z3 from global;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-height: 150px;
|
||||
overflow: auto;
|
||||
outline: none;
|
||||
padding: 4px 0;
|
||||
z-index: 999;
|
||||
|
||||
& MenuItem {
|
||||
background: transparent;
|
||||
display: block;
|
||||
padding: 4px 12px;
|
||||
text-align: left;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
Icon {
|
||||
height: 16px;
|
||||
display: block;
|
||||
}
|
||||
MenuButton Icon[|focus] {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
input-box {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
type BaseProps<TKey, TValue> = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onSelect' | 'name' | 'value' | 'defaultValue'> & ILayoutSizeProps & {
|
||||
propertyName?: string;
|
||||
items: TValue[];
|
||||
searchable?: boolean;
|
||||
defaultValue?: string;
|
||||
keySelector: (item: TValue) => TKey;
|
||||
valueSelector: (item: TValue) => string;
|
||||
onSwitch?: (state: boolean) => void;
|
||||
};
|
||||
|
||||
type ControlledProps<TKey, TValue> = BaseProps<TKey, TValue> & {
|
||||
name?: string;
|
||||
value?: string;
|
||||
onSelect?: (value: TKey, name: string | undefined, prev: TKey) => void;
|
||||
onChange?: (value: string, name: string | undefined) => any;
|
||||
state?: never;
|
||||
};
|
||||
|
||||
type ObjectProps<TValue, TKey extends keyof TState, TState> = BaseProps<TState[TKey], TValue> & {
|
||||
name: TKey;
|
||||
state: TState;
|
||||
onSelect?: (value: TState[TKey], name: TKey | undefined, prev: TState[TKey]) => void;
|
||||
onChange?: (value: string, name: TKey | undefined) => any;
|
||||
value?: never;
|
||||
};
|
||||
|
||||
interface ComboboxType {
|
||||
<TKey, TValue>(props: ControlledProps<TKey, TValue>): JSX.Element;
|
||||
<TValue, TKey extends keyof TState, TState>(props: ObjectProps<TValue, TKey, TState>): JSX.Element;
|
||||
}
|
||||
|
||||
export const ComboboxNew: ComboboxType = observer(function ComboboxNew({
|
||||
value: controlledValue,
|
||||
defaultValue,
|
||||
name,
|
||||
state,
|
||||
propertyName,
|
||||
items,
|
||||
children,
|
||||
title,
|
||||
className,
|
||||
searchable,
|
||||
readOnly,
|
||||
disabled,
|
||||
keySelector = v => v,
|
||||
valueSelector = v => v,
|
||||
onChange = () => {},
|
||||
onSelect,
|
||||
onSwitch,
|
||||
...rest
|
||||
}: ControlledProps<any, any> | ObjectProps<any, any, any>) {
|
||||
rest = filterLayoutFakeProps(rest);
|
||||
const context = useContext(FormContext);
|
||||
const ref = useRef<HTMLInputElement>(null);
|
||||
const menu = useMenuState({
|
||||
placement: 'bottom-end',
|
||||
currentId: null,
|
||||
gutter: 4,
|
||||
});
|
||||
const [searchValue, setSearchValue] = useState<string | null>(null);
|
||||
let value: string | number | readonly string[] | undefined = controlledValue ?? defaultValue ?? undefined;
|
||||
|
||||
if (state && name !== undefined && name in state) {
|
||||
value = state[name];
|
||||
}
|
||||
|
||||
const selectedItem = items.find(item => keySelector(item) === value);
|
||||
|
||||
let inputValue = (selectedItem ? valueSelector(selectedItem) : searchValue) ?? '';
|
||||
|
||||
if (searchValue !== null && selectedItem && valueSelector(selectedItem) !== searchValue) {
|
||||
inputValue = searchValue;
|
||||
}
|
||||
|
||||
const handleChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.target.value;
|
||||
onChange(value, name);
|
||||
setSearchValue(value);
|
||||
},
|
||||
[name, onChange]
|
||||
);
|
||||
|
||||
const handleRemove = useCallback(
|
||||
() => {
|
||||
menu.hide();
|
||||
if (state) {
|
||||
state[name] = null;
|
||||
}
|
||||
if (onSelect) {
|
||||
onSelect(null, name, value);
|
||||
}
|
||||
if (context) {
|
||||
context.change(null, name);
|
||||
}
|
||||
setSearchValue(null);
|
||||
},
|
||||
[value, state, name, menu, context, onSelect]
|
||||
);
|
||||
|
||||
const handleMenuSelect = useCallback(
|
||||
(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
menu.hide();
|
||||
const id = event.currentTarget.id;
|
||||
if (state) {
|
||||
state[name] = id;
|
||||
}
|
||||
if (onSelect) {
|
||||
onSelect(id, name, value);
|
||||
}
|
||||
if (context) {
|
||||
context.change(id, name);
|
||||
}
|
||||
setSearchValue(null);
|
||||
},
|
||||
[value, state, name, menu, context, onSelect]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current === document.activeElement && inputValue === searchValue) {
|
||||
menu.show();
|
||||
}
|
||||
});
|
||||
|
||||
useLayoutEffect(() => onSwitch?.(menu.visible), [onSwitch, menu.visible]);
|
||||
|
||||
const filteredItems = items.filter(
|
||||
item => !searchValue || valueSelector(item).toUpperCase().includes(searchValue.toUpperCase())
|
||||
);
|
||||
|
||||
return styled(useStyles(baseFormControlStylesNew, styles))(
|
||||
<field className={className}>
|
||||
<field-label title={title} as='label'>{children}{rest.required && ' *'}</field-label>
|
||||
<input-box>
|
||||
<input
|
||||
ref={ref}
|
||||
role='new'
|
||||
autoComplete="off"
|
||||
name={name}
|
||||
title={title}
|
||||
value={inputValue}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
onChange={handleChange}
|
||||
{...rest}
|
||||
/>
|
||||
{(selectedItem && !readOnly && searchable) && (
|
||||
<IconButton type="button" name="reject" viewBox="0 0 11 11" onClick={handleRemove} />
|
||||
)}
|
||||
<MenuButton {...menu} disabled={readOnly || disabled}><Icon name="arrow" viewBox="0 0 16 16" {...use({ focus: menu.visible })} /></MenuButton>
|
||||
<Menu
|
||||
{...menu}
|
||||
aria-label={propertyName}
|
||||
unstable_initialFocusRef={ref}
|
||||
unstable_finalFocusRef={ref}
|
||||
>
|
||||
{filteredItems.map(item => (
|
||||
<MenuItem key={keySelector(item)} id={keySelector(item)} type='button' {...menu} onClick={handleMenuSelect}>
|
||||
{valueSelector(item)}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</input-box>
|
||||
</field>
|
||||
);
|
||||
});
|
||||
@@ -14,7 +14,7 @@ import { composes, useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { IconButton } from '../IconButton';
|
||||
import { useFocus } from '../useFocus';
|
||||
import { InputFieldNew } from './InputFieldNew';
|
||||
import { InputField } from './InputField';
|
||||
|
||||
const styles = css`
|
||||
filter-container {
|
||||
@@ -22,7 +22,7 @@ const styles = css`
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
InputFieldNew {
|
||||
InputField {
|
||||
display: none;
|
||||
width: 300px;
|
||||
&[|max] {
|
||||
@@ -148,7 +148,7 @@ export const Filter = observer<ControlledProps | ObjectsProps<any, any>>(functio
|
||||
|
||||
return styled(useStyles(styles, toggleMode && toggleModeButtonStyle))(
|
||||
<filter-container className={className}>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
ref={inputRef}
|
||||
style={innerInputStyle}
|
||||
placeholder={placeholder}
|
||||
|
||||
@@ -6,32 +6,37 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import styled, { use } from 'reshadow';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { baseFormControlStyles } from './baseFormControlStyles';
|
||||
|
||||
const style = css`
|
||||
field-label {
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
label?: string;
|
||||
long?: boolean;
|
||||
short?: boolean;
|
||||
raw?: boolean;
|
||||
title?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const FormFieldDescription: React.FC<Props> = function FormFieldDescription({
|
||||
label,
|
||||
long,
|
||||
short,
|
||||
raw,
|
||||
title,
|
||||
children,
|
||||
className,
|
||||
}) {
|
||||
return styled(useStyles(baseFormControlStyles))(
|
||||
<field as='div' className={className} {...use({ long, short, raw })}>
|
||||
const styles = useStyles(baseFormControlStyles, style);
|
||||
|
||||
return styled(styles)(
|
||||
<field title={title} className={className}>
|
||||
{label && <field-label as='label'>{label}</field-label>}
|
||||
<field-description as='div'>
|
||||
<field-description>
|
||||
{children}
|
||||
</field-description>
|
||||
</field>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 styled from 'reshadow';
|
||||
import { css } from 'reshadow';
|
||||
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { baseFormControlStylesNew } from './baseFormControlStylesNew';
|
||||
|
||||
const formFieldDescriptionNewStyles = css`
|
||||
field-label {
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
label?: string;
|
||||
title?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const FormFieldDescriptionNew: React.FC<Props> = function FormFieldDescriptionNew({
|
||||
label,
|
||||
title,
|
||||
children,
|
||||
className,
|
||||
}) {
|
||||
const styles = useStyles(baseFormControlStylesNew, formFieldDescriptionNewStyles);
|
||||
|
||||
return styled(styles)(
|
||||
<field title={title} as='div' className={className}>
|
||||
{label && <field-label as='label'>{label}</field-label>}
|
||||
<field-description as='div'>
|
||||
{children}
|
||||
</field-description>
|
||||
</field>
|
||||
);
|
||||
};
|
||||
@@ -7,26 +7,73 @@
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import styled, { use } from 'reshadow';
|
||||
import { useCallback, useContext, useState } from 'react';
|
||||
import styled, { use, css } from 'reshadow';
|
||||
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { ComponentStyle, composes, useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
|
||||
import { Icon } from '../Icon';
|
||||
import { baseFormControlStyles } from './baseFormControlStyles';
|
||||
import { FormContext } from './FormContext';
|
||||
import { isControlPresented } from './isControlPresented';
|
||||
|
||||
type BaseProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'name' | 'value'> & {
|
||||
const INPUT_FIELD_STYLES = composes(
|
||||
css`
|
||||
Icon {
|
||||
composes: theme-text-on-secondary from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
field-label {
|
||||
display: block;
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
}
|
||||
field-label:not(:empty) {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
input-container {
|
||||
position: relative;
|
||||
}
|
||||
icon-container {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
& Icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
input[disabled] + icon-container {
|
||||
cursor: auto;
|
||||
opacity: 0.8;
|
||||
}
|
||||
input:not(:only-child) {
|
||||
padding-right: 32px !important;
|
||||
}
|
||||
`);
|
||||
|
||||
type BaseProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'name' | 'value'> & ILayoutSizeProps & {
|
||||
description?: string;
|
||||
mod?: 'surface';
|
||||
long?: boolean;
|
||||
short?: boolean;
|
||||
ref?: React.Ref<HTMLInputElement>;
|
||||
style?: ComponentStyle;
|
||||
onCustomCopy?: () => void;
|
||||
};
|
||||
|
||||
type ControlledProps = BaseProps & {
|
||||
name?: string;
|
||||
value?: string;
|
||||
onChange?: (value: string, name?: string) => any;
|
||||
value?: string | number;
|
||||
mapState?: (value: string | number) => string | number;
|
||||
mapValue?: (value: string | number) => string | number;
|
||||
onChange?: (value: string | number, name?: string) => any;
|
||||
state?: never;
|
||||
autoHide?: never;
|
||||
};
|
||||
@@ -34,7 +81,9 @@ type ControlledProps = BaseProps & {
|
||||
type ObjectProps<TKey extends keyof TState, TState> = BaseProps & {
|
||||
name: TKey;
|
||||
state: TState;
|
||||
onChange?: (value: string, name: TKey) => any;
|
||||
mapState?: (value: TState[TKey]) => TState[TKey] | string | number;
|
||||
mapValue?: (value: TState[TKey]) => TState[TKey];
|
||||
onChange?: (value: TState[TKey], name: TKey) => any;
|
||||
autoHide?: boolean;
|
||||
value?: never;
|
||||
};
|
||||
@@ -46,61 +95,107 @@ interface InputFieldType {
|
||||
|
||||
export const InputField: InputFieldType = observer(function InputField({
|
||||
name,
|
||||
style,
|
||||
value: valueControlled,
|
||||
defaultValue,
|
||||
required,
|
||||
state,
|
||||
mapState,
|
||||
mapValue,
|
||||
children,
|
||||
className,
|
||||
description,
|
||||
mod,
|
||||
long,
|
||||
short,
|
||||
fill,
|
||||
small,
|
||||
medium,
|
||||
large,
|
||||
tiny,
|
||||
autoHide,
|
||||
onChange,
|
||||
onCustomCopy,
|
||||
...rest
|
||||
}: ControlledProps | ObjectProps<any, any>) {
|
||||
const styles = useStyles(baseFormControlStyles);
|
||||
}: ControlledProps | ObjectProps<any, any>, ref: React.Ref<HTMLInputElement>) {
|
||||
const [passwordRevealed, setPasswordRevealed] = useState(false);
|
||||
const translate = useTranslate();
|
||||
const styles = useStyles(baseFormControlStyles, INPUT_FIELD_STYLES, style);
|
||||
const context = useContext(FormContext);
|
||||
|
||||
const revealPassword = useCallback(() => {
|
||||
if (rest.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
setPasswordRevealed(prev => !prev);
|
||||
}, [rest.disabled]);
|
||||
|
||||
const handleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = mapValue?.(event.target.value) ?? event.target.value;
|
||||
|
||||
if (state) {
|
||||
state[name] = event.target.value;
|
||||
state[name] = value;
|
||||
}
|
||||
if (onChange) {
|
||||
onChange(event.target.value, name);
|
||||
onChange(value, name);
|
||||
}
|
||||
if (context) {
|
||||
context.change(event.target.value, name);
|
||||
context.change(value, name);
|
||||
}
|
||||
}, [state, name, context, onChange]);
|
||||
|
||||
if (autoHide && !isControlPresented(name, state, defaultValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let value: any = valueControlled ?? defaultValue ?? undefined;
|
||||
|
||||
if (state && name !== undefined && name in state) {
|
||||
value = state[name];
|
||||
}
|
||||
|
||||
if (autoHide && !isControlPresented(name, state, defaultValue)) {
|
||||
return null;
|
||||
if (mapState) {
|
||||
value = mapState(value);
|
||||
}
|
||||
|
||||
const showRevealPasswordButton = rest.type === 'password' && !rest.readOnly;
|
||||
|
||||
return styled(styles)(
|
||||
<field as="div" className={className} {...use({ long, short })}>
|
||||
<field-label as='label' title={rest.title}>{children} {required && '*'}</field-label>
|
||||
<input
|
||||
{...rest}
|
||||
name={name}
|
||||
value={value ?? ''}
|
||||
onChange={handleChange}
|
||||
{...use({ mod })}
|
||||
required={required}
|
||||
/>
|
||||
<field className={className} {...use({ small, medium, large, tiny })}>
|
||||
<field-label title={rest.title}>{children}{required && ' *'}</field-label>
|
||||
<input-container>
|
||||
<input
|
||||
ref={ref}
|
||||
role='new'
|
||||
{...rest}
|
||||
type={passwordRevealed ? 'text' : rest.type}
|
||||
name={name}
|
||||
value={value ?? ''}
|
||||
onChange={handleChange}
|
||||
{...use({ mod })}
|
||||
required={required}
|
||||
/>
|
||||
{showRevealPasswordButton && (
|
||||
<icon-container
|
||||
title={translate('ui_reveal_password')}
|
||||
onClick={revealPassword}
|
||||
>
|
||||
<Icon
|
||||
name={passwordRevealed ? 'password-hide' : 'password-show'}
|
||||
viewBox='0 0 16 16'
|
||||
/>
|
||||
</icon-container>
|
||||
)}
|
||||
{onCustomCopy && (
|
||||
<icon-container title={translate('ui_copy_to_clipboard')} onClick={onCustomCopy}>
|
||||
<Icon name="copy" viewBox='0 0 32 32' />
|
||||
</icon-container>
|
||||
)}
|
||||
</input-container>
|
||||
{description && (
|
||||
<field-description as='div'>
|
||||
<field-description>
|
||||
{description}
|
||||
</field-description>
|
||||
)}
|
||||
</field>
|
||||
);
|
||||
});
|
||||
}, { forwardRef: true });
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { useCallback, useContext, useState } from 'react';
|
||||
import styled, { use, css } from 'reshadow';
|
||||
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { ComponentStyle, composes, useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
|
||||
import { Icon } from '../Icon';
|
||||
import { baseFormControlStylesNew } from './baseFormControlStylesNew';
|
||||
import { FormContext } from './FormContext';
|
||||
import { isControlPresented } from './isControlPresented';
|
||||
|
||||
const INPUT_FIELD_STYLES = composes(
|
||||
css`
|
||||
Icon {
|
||||
composes: theme-text-on-secondary from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
field-label {
|
||||
display: block;
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
}
|
||||
field-label:not(:empty) {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
input-container {
|
||||
position: relative;
|
||||
}
|
||||
icon-container {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
& Icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
input[disabled] + icon-container {
|
||||
cursor: auto;
|
||||
opacity: 0.8;
|
||||
}
|
||||
input:not(:only-child) {
|
||||
padding-right: 32px !important;
|
||||
}
|
||||
`);
|
||||
|
||||
type BaseProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'name' | 'value'> & ILayoutSizeProps & {
|
||||
description?: string;
|
||||
mod?: 'surface';
|
||||
ref?: React.Ref<HTMLInputElement>;
|
||||
style?: ComponentStyle;
|
||||
onCustomCopy?: () => void;
|
||||
};
|
||||
|
||||
type ControlledProps = BaseProps & {
|
||||
name?: string;
|
||||
value?: string | number;
|
||||
mapState?: (value: string | number) => string | number;
|
||||
mapValue?: (value: string | number) => string | number;
|
||||
onChange?: (value: string | number, name?: string) => any;
|
||||
state?: never;
|
||||
autoHide?: never;
|
||||
};
|
||||
|
||||
type ObjectProps<TKey extends keyof TState, TState> = BaseProps & {
|
||||
name: TKey;
|
||||
state: TState;
|
||||
mapState?: (value: TState[TKey]) => TState[TKey] | string | number;
|
||||
mapValue?: (value: TState[TKey]) => TState[TKey];
|
||||
onChange?: (value: TState[TKey], name: TKey) => any;
|
||||
autoHide?: boolean;
|
||||
value?: never;
|
||||
};
|
||||
|
||||
interface InputFieldType {
|
||||
(props: ControlledProps): React.ReactElement<any, any> | null;
|
||||
<TKey extends keyof TState, TState>(props: ObjectProps<TKey, TState>): React.ReactElement<any, any> | null;
|
||||
}
|
||||
|
||||
export const InputFieldNew: InputFieldType = observer(function InputFieldNew({
|
||||
name,
|
||||
style,
|
||||
value: valueControlled,
|
||||
defaultValue,
|
||||
required,
|
||||
state,
|
||||
mapState,
|
||||
mapValue,
|
||||
children,
|
||||
className,
|
||||
description,
|
||||
mod,
|
||||
fill,
|
||||
small,
|
||||
medium,
|
||||
large,
|
||||
tiny,
|
||||
autoHide,
|
||||
onChange,
|
||||
onCustomCopy,
|
||||
...rest
|
||||
}: ControlledProps | ObjectProps<any, any>, ref: React.Ref<HTMLInputElement>) {
|
||||
const [passwordRevealed, setPasswordRevealed] = useState(false);
|
||||
const translate = useTranslate();
|
||||
const styles = useStyles(baseFormControlStylesNew, INPUT_FIELD_STYLES, style);
|
||||
const context = useContext(FormContext);
|
||||
|
||||
const revealPassword = useCallback(() => {
|
||||
if (rest.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
setPasswordRevealed(prev => !prev);
|
||||
}, [rest.disabled]);
|
||||
|
||||
const handleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = mapValue?.(event.target.value) ?? event.target.value;
|
||||
|
||||
if (state) {
|
||||
state[name] = value;
|
||||
}
|
||||
if (onChange) {
|
||||
onChange(value, name);
|
||||
}
|
||||
if (context) {
|
||||
context.change(value, name);
|
||||
}
|
||||
}, [state, name, context, onChange]);
|
||||
|
||||
if (autoHide && !isControlPresented(name, state, defaultValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let value: any = valueControlled ?? defaultValue ?? undefined;
|
||||
|
||||
if (state && name !== undefined && name in state) {
|
||||
value = state[name];
|
||||
}
|
||||
|
||||
if (mapState) {
|
||||
value = mapState(value);
|
||||
}
|
||||
|
||||
const showRevealPasswordButton = rest.type === 'password' && !rest.readOnly;
|
||||
|
||||
return styled(styles)(
|
||||
<field className={className} {...use({ small, medium, large, tiny })}>
|
||||
<field-label title={rest.title}>{children}{required && ' *'}</field-label>
|
||||
<input-container>
|
||||
<input
|
||||
ref={ref}
|
||||
role='new'
|
||||
{...rest}
|
||||
type={passwordRevealed ? 'text' : rest.type}
|
||||
name={name}
|
||||
value={value ?? ''}
|
||||
onChange={handleChange}
|
||||
{...use({ mod })}
|
||||
required={required}
|
||||
/>
|
||||
{showRevealPasswordButton && (
|
||||
<icon-container
|
||||
title={translate('ui_reveal_password')}
|
||||
onClick={revealPassword}
|
||||
>
|
||||
<Icon
|
||||
name={passwordRevealed ? 'password-hide' : 'password-show'}
|
||||
viewBox='0 0 16 16'
|
||||
/>
|
||||
</icon-container>
|
||||
)}
|
||||
{onCustomCopy && (
|
||||
<icon-container title={translate('ui_copy_to_clipboard')} onClick={onCustomCopy}>
|
||||
<Icon name="copy" viewBox='0 0 32 32' />
|
||||
</icon-container>
|
||||
)}
|
||||
</input-container>
|
||||
{description && (
|
||||
<field-description>
|
||||
{description}
|
||||
</field-description>
|
||||
)}
|
||||
</field>
|
||||
);
|
||||
}, { forwardRef: true });
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 styled, { css, use } from 'reshadow';
|
||||
|
||||
import { useStyles, composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { baseFormControlStyles } from './baseFormControlStyles';
|
||||
|
||||
const styles = composes(
|
||||
css`
|
||||
field-label {
|
||||
composes: theme-border-color-background from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
field-label {
|
||||
composes: theme-typography--body2 from global;
|
||||
margin-left: 180px;
|
||||
text-align: left;
|
||||
font-weight: initial;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: solid 1px #dedede;
|
||||
width: 100%;
|
||||
|
||||
&[|long] {
|
||||
margin-left: 200px;
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
interface Props {
|
||||
className?: string;
|
||||
long?: boolean;
|
||||
}
|
||||
|
||||
export const InputGroup: React.FC<Props> = function InputGroup({
|
||||
children,
|
||||
className,
|
||||
long,
|
||||
}) {
|
||||
return styled(useStyles(baseFormControlStyles, styles))(
|
||||
<field as="div" className={className}>
|
||||
<field-label as='label' {...use({ long })}>{children}</field-label>
|
||||
</field>
|
||||
);
|
||||
};
|
||||
@@ -10,8 +10,9 @@ import { observer } from 'mobx-react-lite';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import styled, { css, use } from 'reshadow';
|
||||
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
import { ComponentStyle, useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
|
||||
import { baseFormControlStyles } from './baseFormControlStyles';
|
||||
import { FormContext } from './FormContext';
|
||||
|
||||
@@ -19,18 +20,39 @@ const styles = css`
|
||||
textarea {
|
||||
line-height: 19px;
|
||||
}
|
||||
field[|embedded] {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
& textarea {
|
||||
border-radius: 0 !important;
|
||||
height: 100%;
|
||||
resize: none !important;
|
||||
}
|
||||
}
|
||||
field-label {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type BaseProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange'> & {
|
||||
type BaseProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange' | 'style'> & ILayoutSizeProps & {
|
||||
mod?: 'surface';
|
||||
long?: boolean;
|
||||
style?: ComponentStyle;
|
||||
embedded?: boolean;
|
||||
};
|
||||
|
||||
type ControlledProps = BaseProps & {
|
||||
name?: string;
|
||||
value?: string;
|
||||
onChange?: (value: string, name?: string) => any;
|
||||
|
||||
state?: never;
|
||||
};
|
||||
|
||||
@@ -38,7 +60,6 @@ type ObjectProps<TKey extends keyof TState, TState> = BaseProps & {
|
||||
name: TKey;
|
||||
state: TState;
|
||||
onChange?: (value: string, name: TKey) => any;
|
||||
|
||||
value?: never;
|
||||
};
|
||||
|
||||
@@ -49,12 +70,18 @@ interface TextareaType {
|
||||
|
||||
export const Textarea: TextareaType = observer(function Textarea({
|
||||
name,
|
||||
style,
|
||||
value: controlledValue,
|
||||
state,
|
||||
children,
|
||||
className,
|
||||
fill,
|
||||
tiny,
|
||||
small,
|
||||
medium,
|
||||
large,
|
||||
mod,
|
||||
long,
|
||||
embedded,
|
||||
onChange = () => {},
|
||||
...rest
|
||||
}: ControlledProps | ObjectProps<any, any>) {
|
||||
@@ -74,13 +101,15 @@ export const Textarea: TextareaType = observer(function Textarea({
|
||||
|
||||
const value = state ? state[name] : controlledValue;
|
||||
|
||||
return styled(useStyles(baseFormControlStyles, styles))(
|
||||
<field as="div" className={className} {...use({ long })}>
|
||||
<field-label as='label'>{children}</field-label>
|
||||
return styled(useStyles(baseFormControlStyles, styles, style))(
|
||||
<field className={className} {...use({ tiny, small, medium, large, embedded })}>
|
||||
<field-label as='label' title={rest.title}>{children}</field-label>
|
||||
<textarea
|
||||
{...rest}
|
||||
role='new'
|
||||
value={value ?? ''}
|
||||
name={name}
|
||||
data-embedded={embedded}
|
||||
onChange={handleChange}
|
||||
{...use({ mod })}
|
||||
/>
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { useCallback, useContext } from 'react';
|
||||
import styled, { css, use } from 'reshadow';
|
||||
|
||||
import { ComponentStyle, useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
|
||||
import { baseFormControlStylesNew } from './baseFormControlStylesNew';
|
||||
import { FormContext } from './FormContext';
|
||||
|
||||
const styles = css`
|
||||
textarea {
|
||||
line-height: 19px;
|
||||
}
|
||||
field[|embedded] {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
& textarea {
|
||||
border-radius: 0 !important;
|
||||
height: 100%;
|
||||
resize: none !important;
|
||||
}
|
||||
}
|
||||
field-label {
|
||||
display: block;
|
||||
padding-bottom: 10px;
|
||||
composes: theme-typography--body1 from global;
|
||||
font-weight: 500;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
type BaseProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange' | 'style'> & ILayoutSizeProps & {
|
||||
mod?: 'surface';
|
||||
style?: ComponentStyle;
|
||||
embedded?: boolean;
|
||||
};
|
||||
|
||||
type ControlledProps = BaseProps & {
|
||||
name?: string;
|
||||
value?: string;
|
||||
onChange?: (value: string, name?: string) => any;
|
||||
state?: never;
|
||||
};
|
||||
|
||||
type ObjectProps<TKey extends keyof TState, TState> = BaseProps & {
|
||||
name: TKey;
|
||||
state: TState;
|
||||
onChange?: (value: string, name: TKey) => any;
|
||||
value?: never;
|
||||
};
|
||||
|
||||
interface TextareaType {
|
||||
(props: ControlledProps): JSX.Element;
|
||||
<TKey extends keyof TState, TState>(props: ObjectProps<TKey, TState>): JSX.Element;
|
||||
}
|
||||
|
||||
export const TextareaNew: TextareaType = observer(function TextareaNew({
|
||||
name,
|
||||
style,
|
||||
value: controlledValue,
|
||||
state,
|
||||
children,
|
||||
className,
|
||||
fill,
|
||||
tiny,
|
||||
small,
|
||||
medium,
|
||||
large,
|
||||
mod,
|
||||
embedded,
|
||||
onChange = () => {},
|
||||
...rest
|
||||
}: ControlledProps | ObjectProps<any, any>) {
|
||||
const context = useContext(FormContext);
|
||||
|
||||
const handleChange = useCallback((event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
if (state) {
|
||||
state[name] = event.target.value;
|
||||
}
|
||||
if (onChange) {
|
||||
onChange(event.target.value, name);
|
||||
}
|
||||
if (context) {
|
||||
context.change(event.target.value, name);
|
||||
}
|
||||
}, [state, name, onChange]);
|
||||
|
||||
const value = state ? state[name] : controlledValue;
|
||||
|
||||
return styled(useStyles(baseFormControlStylesNew, styles, style))(
|
||||
<field className={className} {...use({ tiny, small, medium, large, embedded })}>
|
||||
<field-label as='label' title={rest.title}>{children}</field-label>
|
||||
<textarea
|
||||
{...rest}
|
||||
role='new'
|
||||
value={value ?? ''}
|
||||
name={name}
|
||||
data-embedded={embedded}
|
||||
onChange={handleChange}
|
||||
{...use({ mod })}
|
||||
/>
|
||||
</field>
|
||||
);
|
||||
});
|
||||
@@ -18,66 +18,29 @@ export const baseFormControlStyles = composes(
|
||||
`,
|
||||
css`
|
||||
field {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: auto;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
min-height: 54px;
|
||||
|
||||
& input,
|
||||
& textarea {
|
||||
flex: 1;
|
||||
min-height: 26px;
|
||||
max-width: 100%;
|
||||
&[|small] {
|
||||
max-width: 250px;
|
||||
}
|
||||
&[|medium] {
|
||||
max-width: 450px;
|
||||
}
|
||||
&[|large] {
|
||||
max-width: 650px;
|
||||
}
|
||||
}
|
||||
|
||||
field-label {
|
||||
composes: theme-typography--body1 from global;
|
||||
box-sizing: border-box;
|
||||
width: 180px;
|
||||
text-align: right;
|
||||
padding: 0 16px;
|
||||
line-height: 16px;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
field-description {
|
||||
composes: theme-typography--caption from global;
|
||||
flex-basis: 100%;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
padding-left: 180px;
|
||||
}
|
||||
|
||||
field[|raw] {
|
||||
& field-description {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
field[|long] {
|
||||
& field-label {
|
||||
width: 200px;
|
||||
}
|
||||
& field-description {
|
||||
padding-left: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
field[|short] {
|
||||
& field-label {
|
||||
width: auto;
|
||||
}
|
||||
& field-description {
|
||||
padding-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
field-label + field-description {
|
||||
padding-left: 0!important;
|
||||
flex-basis: auto;
|
||||
padding-top: 4px;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { css } from 'reshadow';
|
||||
|
||||
import { composes } from '@cloudbeaver/core-theming';
|
||||
|
||||
export const baseFormControlStylesNew = composes(
|
||||
css`
|
||||
field-description {
|
||||
composes: theme-text-text-hint-on-light from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
field {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
&[|small] {
|
||||
max-width: 250px;
|
||||
}
|
||||
&[|medium] {
|
||||
max-width: 450px;
|
||||
}
|
||||
&[|large] {
|
||||
max-width: 650px;
|
||||
}
|
||||
}
|
||||
|
||||
field-label {
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
field-description {
|
||||
composes: theme-typography--caption from global;
|
||||
padding-top: 4px;
|
||||
}
|
||||
`
|
||||
);
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { DetailedHTMLProps, IframeHTMLAttributes } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { composes, useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
const styles = composes(
|
||||
css`
|
||||
iframe {
|
||||
composes: theme-border-color-background from global;
|
||||
}
|
||||
`,
|
||||
css`
|
||||
iframe {
|
||||
border: 1px solid;
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
export const Iframe: React.FC<DetailedHTMLProps<IframeHTMLAttributes<HTMLIFrameElement>, HTMLIFrameElement>> = function Iframe(props) {
|
||||
return styled(useStyles(styles))(
|
||||
<iframe {...props} />
|
||||
);
|
||||
};
|
||||
+21
-127
@@ -8,127 +8,17 @@
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useCallback } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { InputField } from '@cloudbeaver/core-blocks';
|
||||
import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
import { FieldCheckbox } from '../../FormControls/Checkboxes/FieldCheckbox';
|
||||
import { Combobox } from '../../FormControls/Combobox';
|
||||
import { FormFieldDescription } from '../../FormControls/FormFieldDescription';
|
||||
import { FormGroup } from '../../FormControls/FormGroup';
|
||||
import { isControlPresented } from '../../FormControls/isControlPresented';
|
||||
import { Link } from '../../Link';
|
||||
import type { ILayoutSizeProps } from '../../Containers/ILayoutSizeProps';
|
||||
import { TextPlaceholder } from '../../TextPlaceholder';
|
||||
import { formStyles } from './formStyles';
|
||||
import { RenderField } from './RenderField';
|
||||
|
||||
const RESERVED_KEYWORDS = ['no', 'off', 'new-password'];
|
||||
|
||||
interface RenderFieldProps {
|
||||
property: ObjectPropertyInfo;
|
||||
state: Record<string, any>;
|
||||
editable?: boolean;
|
||||
autofillToken?: string;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
autoHide?: boolean;
|
||||
showRememberTip?: boolean;
|
||||
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
||||
}
|
||||
|
||||
const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
property,
|
||||
state,
|
||||
editable = true,
|
||||
autofillToken = '',
|
||||
disabled,
|
||||
readOnly,
|
||||
autoHide,
|
||||
showRememberTip,
|
||||
onFocus,
|
||||
}) {
|
||||
const href = property.features.includes('href');
|
||||
const password = property.features.includes('password');
|
||||
const checkbox = property.dataType === 'Boolean';
|
||||
const combobox = property.validValues && property.validValues.length > 0;
|
||||
let description: string | undefined;
|
||||
|
||||
if (href) {
|
||||
return (
|
||||
<FormFieldDescription label={property.displayName} raw>
|
||||
<Link href={state[property.id!]} target='_blank' rel='noopener noreferrer'>{property.description}</Link>
|
||||
</FormFieldDescription>
|
||||
);
|
||||
}
|
||||
|
||||
if (!editable) {
|
||||
if (autoHide && !isControlPresented(property.id!, state)) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<FormFieldDescription label={property.displayName} raw>
|
||||
{state[property.id!]}
|
||||
</FormFieldDescription>
|
||||
);
|
||||
}
|
||||
|
||||
if (showRememberTip && password && property.value) {
|
||||
description = 'Password saved';
|
||||
}
|
||||
|
||||
if (checkbox) {
|
||||
return (
|
||||
<FieldCheckbox
|
||||
id={property.id}
|
||||
name={property.id!}
|
||||
state={state}
|
||||
label={property.displayName}
|
||||
title={property.description}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (combobox) {
|
||||
return (
|
||||
<Combobox
|
||||
name={property.id!}
|
||||
state={state}
|
||||
items={property.validValues!}
|
||||
keySelector={value => value}
|
||||
valueSelector={value => value}
|
||||
defaultValue={property.defaultValue}
|
||||
mod="surface"
|
||||
title={property.description}
|
||||
disabled={disabled}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</Combobox>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<InputField
|
||||
type={password ? 'password' : 'text'}
|
||||
name={property.id!}
|
||||
state={state}
|
||||
description={description}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
autoHide={autoHide}
|
||||
autoComplete={RESERVED_KEYWORDS.includes(autofillToken) ? autofillToken : `${autofillToken} ${property.id}`}
|
||||
mod='surface'
|
||||
onFocus={onFocus}
|
||||
>
|
||||
{property.displayName}
|
||||
</InputField>
|
||||
);
|
||||
});
|
||||
|
||||
interface ObjectPropertyFormProps {
|
||||
properties: ObjectPropertyInfo[] | undefined;
|
||||
state: Record<string, string | number>;
|
||||
interface ObjectPropertyFormProps extends ILayoutSizeProps {
|
||||
properties: ObjectPropertyInfo[];
|
||||
state?: Record<string, any>;
|
||||
category?: string | null;
|
||||
editable?: boolean;
|
||||
autofillToken?: string;
|
||||
className?: string;
|
||||
@@ -142,32 +32,36 @@ interface ObjectPropertyFormProps {
|
||||
export const ObjectPropertyInfoForm = observer<ObjectPropertyFormProps>(function ObjectPropertyInfoForm({
|
||||
properties,
|
||||
state,
|
||||
category,
|
||||
editable = true,
|
||||
autofillToken = '',
|
||||
className,
|
||||
autofillToken = '',
|
||||
disabled,
|
||||
readOnly,
|
||||
autoHide,
|
||||
showRememberTip,
|
||||
onFocus,
|
||||
}) {
|
||||
const style = useStyles(formStyles);
|
||||
|
||||
const handleFocus = useCallback((e: React.FocusEvent<HTMLInputElement>) => {
|
||||
if (onFocus) {
|
||||
onFocus(e.target.name);
|
||||
}
|
||||
}, [onFocus]);
|
||||
|
||||
if (!properties || properties.length === 0) {
|
||||
if (properties.length === 0) {
|
||||
return <TextPlaceholder>Properties empty</TextPlaceholder>;
|
||||
}
|
||||
|
||||
return styled(style)(
|
||||
<form-body as='div' className={className}>
|
||||
{properties.map(property => (
|
||||
<FormGroup key={property.id}>
|
||||
return (
|
||||
<>
|
||||
{properties.map(property => {
|
||||
if (category !== undefined && property.category !== category) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<RenderField
|
||||
key={property.id}
|
||||
className={className}
|
||||
property={property}
|
||||
state={state}
|
||||
editable={editable}
|
||||
@@ -178,8 +72,8 @@ export const ObjectPropertyInfoForm = observer<ObjectPropertyFormProps>(function
|
||||
showRememberTip={showRememberTip}
|
||||
onFocus={handleFocus}
|
||||
/>
|
||||
</FormGroup>
|
||||
))}
|
||||
</form-body>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { useCallback } from 'react';
|
||||
|
||||
import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import type { ILayoutSizeProps } from '../../Containers/ILayoutSizeProps';
|
||||
import { TextPlaceholder } from '../../TextPlaceholder';
|
||||
import { RenderField } from './RenderField';
|
||||
|
||||
interface ObjectPropertyFormProps extends ILayoutSizeProps {
|
||||
properties: ObjectPropertyInfo[];
|
||||
state?: Record<string, any>;
|
||||
category?: string | null;
|
||||
editable?: boolean;
|
||||
autofillToken?: string;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
readOnly?: boolean;
|
||||
autoHide?: boolean;
|
||||
showRememberTip?: boolean;
|
||||
onFocus?: (name: string) => void;
|
||||
}
|
||||
|
||||
export const ObjectPropertyInfoFormNew = observer<ObjectPropertyFormProps>(function ObjectPropertyInfoFormNew({
|
||||
properties,
|
||||
state,
|
||||
category,
|
||||
editable = true,
|
||||
className,
|
||||
autofillToken = '',
|
||||
disabled,
|
||||
readOnly,
|
||||
autoHide,
|
||||
showRememberTip,
|
||||
onFocus,
|
||||
}) {
|
||||
const handleFocus = useCallback((e: React.FocusEvent<HTMLInputElement>) => {
|
||||
if (onFocus) {
|
||||
onFocus(e.target.name);
|
||||
}
|
||||
}, [onFocus]);
|
||||
|
||||
if (properties.length === 0) {
|
||||
return <TextPlaceholder>Properties empty</TextPlaceholder>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{properties.map(property => {
|
||||
if (category !== undefined && property.category !== category) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<RenderField
|
||||
key={property.id}
|
||||
className={className}
|
||||
property={property}
|
||||
state={state}
|
||||
editable={editable}
|
||||
autofillToken={autofillToken}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
autoHide={autoHide}
|
||||
showRememberTip={showRememberTip}
|
||||
onFocus={handleFocus}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
});
|
||||
+25
-25
@@ -10,12 +10,12 @@ import { observer } from 'mobx-react-lite';
|
||||
|
||||
import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
|
||||
import { FieldCheckboxNew } from '../../FormControls/Checkboxes/FieldCheckboxNew';
|
||||
import { ComboboxNew } from '../../FormControls/ComboboxNew';
|
||||
import { FormFieldDescriptionNew } from '../../FormControls/FormFieldDescriptionNew';
|
||||
import { InputFieldNew } from '../../FormControls/InputFieldNew';
|
||||
import { FieldCheckbox } from '../../FormControls/Checkboxes/FieldCheckbox';
|
||||
import { Combobox } from '../../FormControls/Combobox';
|
||||
import { FormFieldDescription } from '../../FormControls/FormFieldDescription';
|
||||
import { InputField } from '../../FormControls/InputField';
|
||||
import { isControlPresented } from '../../FormControls/isControlPresented';
|
||||
import { TextareaNew } from '../../FormControls/TextareaNew';
|
||||
import { Textarea } from '../../FormControls/Textarea';
|
||||
import { Link } from '../../Link';
|
||||
|
||||
const RESERVED_KEYWORDS = ['no', 'off', 'new-password'];
|
||||
@@ -86,9 +86,9 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
|
||||
if (controltype === 'link') {
|
||||
return (
|
||||
<FormFieldDescriptionNew label={property.displayName} className={className}>
|
||||
<FormFieldDescription label={property.displayName} className={className}>
|
||||
<Link href={state?.[property.id!]} target='_blank' rel='noopener noreferrer'>{property.description}</Link>
|
||||
</FormFieldDescriptionNew>
|
||||
</FormFieldDescription>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,9 +97,9 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<FormFieldDescriptionNew title={property.description} label={property.displayName} className={className}>
|
||||
<FormFieldDescription title={property.description} label={property.displayName} className={className}>
|
||||
{state?.[property.id!]}
|
||||
</FormFieldDescriptionNew>
|
||||
</FormFieldDescription>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
if (controltype === 'checkbox') {
|
||||
if (state !== undefined) {
|
||||
return (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={property.id}
|
||||
name={property.id!}
|
||||
state={state}
|
||||
@@ -120,11 +120,11 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
className={className}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={property.id}
|
||||
name={property.id!}
|
||||
checked={value}
|
||||
@@ -134,14 +134,14 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
className={className}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
);
|
||||
}
|
||||
|
||||
if (controltype === 'combobox') {
|
||||
if (state !== undefined) {
|
||||
return (
|
||||
<ComboboxNew
|
||||
<Combobox
|
||||
name={property.id!}
|
||||
state={state}
|
||||
items={property.validValues!}
|
||||
@@ -154,12 +154,12 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
className={className}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</ComboboxNew>
|
||||
</Combobox>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ComboboxNew
|
||||
<Combobox
|
||||
name={property.id!}
|
||||
items={property.validValues!}
|
||||
keySelector={value => value}
|
||||
@@ -171,14 +171,14 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
className={className}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</ComboboxNew>
|
||||
</Combobox>
|
||||
);
|
||||
}
|
||||
|
||||
if (controltype === 'textarea') {
|
||||
if (state !== undefined) {
|
||||
return (
|
||||
<TextareaNew
|
||||
<Textarea
|
||||
title={property.description}
|
||||
name={property.id!}
|
||||
state={state}
|
||||
@@ -188,12 +188,12 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
className={className}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</TextareaNew>
|
||||
</Textarea>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TextareaNew
|
||||
<Textarea
|
||||
title={property.description}
|
||||
name={property.id!}
|
||||
value={value}
|
||||
@@ -203,13 +203,13 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
className={className}
|
||||
>
|
||||
{property.displayName ?? ''}
|
||||
</TextareaNew>
|
||||
</Textarea>
|
||||
);
|
||||
}
|
||||
|
||||
if (state !== undefined) {
|
||||
return (
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type={password ? 'password' : 'text'}
|
||||
title={property.description}
|
||||
name={property.id!}
|
||||
@@ -225,11 +225,11 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
onFocus={onFocus}
|
||||
>
|
||||
{property.displayName}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type={password ? 'password' : 'text'}
|
||||
title={property.description}
|
||||
name={property.id!}
|
||||
@@ -244,6 +244,6 @@ export const RenderField = observer<RenderFieldProps>(function RenderField({
|
||||
onFocus={onFocus}
|
||||
>
|
||||
{property.displayName}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
);
|
||||
});
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { css } from 'reshadow';
|
||||
|
||||
export const formStyles = css`
|
||||
form-body {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
`;
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
||||
/// <reference path="react-sanitized-html.d.ts" />
|
||||
|
||||
import Sanitized from 'react-sanitized-html';
|
||||
|
||||
export interface SanitizedHTMLProps {
|
||||
html: string;
|
||||
}
|
||||
|
||||
const allowedTags = ['h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
|
||||
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div',
|
||||
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre'];
|
||||
|
||||
const nonTextTags = ['title', 'style', 'script', 'textarea', 'noscript'];
|
||||
|
||||
export function ReactSanitizedHTML({ html }: SanitizedHTMLProps) {
|
||||
return (
|
||||
<Sanitized html={html} allowedTags={allowedTags} nonTextTags={nonTextTags} />
|
||||
);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 { ComplexLoader, createComplexLoader, Loader } from '@cloudbeaver/core-blocks';
|
||||
|
||||
const loader = createComplexLoader(async function loader() {
|
||||
const { ReactSanitizedHTML } = await import('./ReactSanitizedHTML');
|
||||
return { ReactSanitizedHTML };
|
||||
});
|
||||
|
||||
interface Props {
|
||||
html: string;
|
||||
}
|
||||
|
||||
export const SanitizedHTML: React.FC<Props> = function SanitizedHTML({ html }) {
|
||||
return (
|
||||
<ComplexLoader
|
||||
loader={loader}
|
||||
placeholder={<Loader />}
|
||||
>
|
||||
{({ ReactSanitizedHTML }) => (
|
||||
<ReactSanitizedHTML html={html} />
|
||||
)}
|
||||
</ComplexLoader>
|
||||
);
|
||||
};
|
||||
@@ -1,14 +0,0 @@
|
||||
declare module 'react-sanitized-html' {
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
interface ReactSanitizedHtmlProps {
|
||||
html: string;
|
||||
// see https://github.com/apostrophecms/sanitize-html documentation
|
||||
allowedTags?: string[];
|
||||
nonTextTags?: string[];
|
||||
}
|
||||
|
||||
export default class ReactSanitizedHtml extends Component<ReactSanitizedHtmlProps, any> {
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ export * from './layout/AppLogo';
|
||||
export * from './layout/TopAppBar';
|
||||
export * from './Loader/Loader';
|
||||
export * from './ObjectPropertyInfo/ObjectPropertyInfoForm/ObjectPropertyInfoForm';
|
||||
export * from './ObjectPropertyInfo/ObjectPropertyInfoForm/ObjectPropertyInfoFormNew';
|
||||
export * from './ObjectPropertyInfo/useObjectPropertyCategories';
|
||||
|
||||
export * from './Placeholder/Placeholder';
|
||||
@@ -25,7 +24,6 @@ export * from './Placeholder/PlaceholderContainer';
|
||||
export * from './PropertiesTable/PropertiesTable';
|
||||
export * from './PropertiesTable/IProperty';
|
||||
|
||||
export * from './SanitizedHTML/SanitizedHTML';
|
||||
export * from './Slide/SlideBox';
|
||||
export * from './Slide/SlideBoxStyles';
|
||||
export * from './Slide/SlideElement';
|
||||
@@ -98,10 +96,8 @@ export * from './ToolsPanel/ToolsAction';
|
||||
export * from './ToolsPanel/ToolsPanel';
|
||||
export * from './FormControls/Checkboxes/Checkbox';
|
||||
export * from './FormControls/Checkboxes/FieldCheckbox';
|
||||
export * from './FormControls/Checkboxes/FieldCheckboxNew';
|
||||
export * from './FormControls/Checkboxes/CheckboxMarkup';
|
||||
export * from './FormControls/Checkboxes/Switch';
|
||||
export * from './FormControls/Checkboxes/SwitchNew';
|
||||
export * from './FormControls/Checkboxes/useCheckboxState';
|
||||
export * from './FormControls/FormBox';
|
||||
export * from './FormControls/Filter';
|
||||
@@ -117,21 +113,16 @@ export * from './Containers/IContainerProps';
|
||||
export * from './Containers/ILayoutSizeProps';
|
||||
export * from './FormControls/FormBoxElement';
|
||||
export * from './FormControls/Combobox';
|
||||
export * from './FormControls/ComboboxNew';
|
||||
export * from './FormControls/FormContext';
|
||||
export * from './FormControls/FormFieldDescription';
|
||||
export * from './FormControls/FormFieldDescriptionNew';
|
||||
export * from './FormControls/FormGroup';
|
||||
export * from './FormControls/InputField';
|
||||
export * from './FormControls/InputFieldNew';
|
||||
export * from './FormControls/InputGroup';
|
||||
export * from './FormControls/Radio';
|
||||
export * from './FormControls/RadioGroup';
|
||||
export * from './FormControls/RadioGroupContext';
|
||||
export * from './FormControls/ShadowInput';
|
||||
export * from './FormControls/SubmittingForm';
|
||||
export * from './FormControls/Textarea';
|
||||
export * from './FormControls/TextareaNew';
|
||||
export * from './Link';
|
||||
export * from './Cell';
|
||||
export * from './ErrorMessage';
|
||||
@@ -143,6 +134,7 @@ export * from './IconOrImage';
|
||||
export * from './StaticImage';
|
||||
export * from './TextPlaceholder';
|
||||
export * from './InfoItem';
|
||||
export * from './Iframe';
|
||||
export * from './useClickEvents';
|
||||
export * from './useClipboard';
|
||||
export * from './useDataResource';
|
||||
|
||||
@@ -24,8 +24,6 @@ const excludedFromVendor = [
|
||||
'backbone',
|
||||
'lodash',
|
||||
'canvg',
|
||||
'sanitize-html',
|
||||
'react-sanitized-html',
|
||||
'dagre',
|
||||
'svg-pathdata',
|
||||
'@emotion',
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, Container, FieldCheckboxNew, Group, GroupTitle, ObjectPropertyInfoFormNew, TextPlaceholder, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Container, FieldCheckbox, Group, GroupTitle, ObjectPropertyInfoForm, TextPlaceholder, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { ObjectPropertyInfo } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -48,14 +48,14 @@ export const ConnectionAuthenticationForm = observer<Props>(function ConnectionA
|
||||
{properties ? (
|
||||
<>
|
||||
{!!networkHandlers?.length && <GroupTitle>{translate('connections_database_authentication')}</GroupTitle>}
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
autofillToken={`section-${formId || ''} section-auth`}
|
||||
properties={properties}
|
||||
state={config.credentials}
|
||||
disabled={disabled}
|
||||
/>
|
||||
{allowSaveCredentials && (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={formId || 'DBAuthSaveCredentials'}
|
||||
name="saveCredentials"
|
||||
label={translate('connections_connection_edit_save_credentials')}
|
||||
|
||||
+6
-6
@@ -9,7 +9,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, FieldCheckboxNew, GroupTitle, InputFieldNew, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, FieldCheckbox, GroupTitle, InputField, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { NetworkHandlerConfigInput } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -41,7 +41,7 @@ export const NetworkHandlerAuthForm = observer<Props>(function NetworkHandlerAut
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<>
|
||||
<GroupTitle>{handler.data?.label || translate(`connections_network_handler_${id}_title`, 'connections_network_handler_default_title')}</GroupTitle>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type="text"
|
||||
name="userName"
|
||||
state={state}
|
||||
@@ -49,8 +49,8 @@ export const NetworkHandlerAuthForm = observer<Props>(function NetworkHandlerAut
|
||||
mod='surface'
|
||||
>
|
||||
{translate(`connections_network_handler_${id}_user`, 'connections_network_handler_default_user')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type="password"
|
||||
name="password"
|
||||
state={state}
|
||||
@@ -58,9 +58,9 @@ export const NetworkHandlerAuthForm = observer<Props>(function NetworkHandlerAut
|
||||
mod='surface'
|
||||
>
|
||||
{translate(`connections_network_handler_${id}_password`, 'connections_network_handler_default_password')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
{allowSaveCredentials && (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={id + ' savePassword'}
|
||||
name="savePassword"
|
||||
state={state}
|
||||
|
||||
@@ -13,7 +13,7 @@ import styled, { css } from 'reshadow';
|
||||
import { useAdministrationSettings } from '@cloudbeaver/core-administration';
|
||||
import { AUTH_PROVIDER_LOCAL_ID } from '@cloudbeaver/core-authentication';
|
||||
import {
|
||||
InputFieldNew,
|
||||
InputField,
|
||||
SubmittingForm,
|
||||
TabContainerPanelComponent,
|
||||
useMapResource,
|
||||
@@ -21,10 +21,10 @@ import {
|
||||
BASE_CONTAINERS_STYLES,
|
||||
Group,
|
||||
GroupTitle,
|
||||
FieldCheckboxNew,
|
||||
ObjectPropertyInfoFormNew,
|
||||
TextareaNew,
|
||||
ComboboxNew,
|
||||
FieldCheckbox,
|
||||
ObjectPropertyInfoForm,
|
||||
Textarea,
|
||||
Combobox,
|
||||
Container,
|
||||
useFormValidator,
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
@@ -39,7 +39,7 @@ import { DBDriverResource } from '../../DBDriverResource';
|
||||
import { isJDBCConnection } from '../../isJDBCConnection';
|
||||
import { ConnectionFormService } from '../ConnectionFormService';
|
||||
import type { IConnectionFormProps } from '../IConnectionFormProps';
|
||||
import { ParametersFormNew } from './ParametersFormNew';
|
||||
import { ParametersForm } from './ParametersForm';
|
||||
import { useOptions } from './useOptions';
|
||||
|
||||
const styles = css`
|
||||
@@ -120,7 +120,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
<Container medium gap>
|
||||
<Group form gap>
|
||||
<Container wrap gap>
|
||||
<ComboboxNew
|
||||
<Combobox
|
||||
name='driverId'
|
||||
state={config}
|
||||
items={drivers}
|
||||
@@ -132,8 +132,8 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
fill
|
||||
>
|
||||
{translate('connections_connection_driver')}
|
||||
</ComboboxNew>
|
||||
<InputFieldNew
|
||||
</Combobox>
|
||||
<InputField
|
||||
type="text"
|
||||
name="name"
|
||||
minLength={1}
|
||||
@@ -146,10 +146,10 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
fill
|
||||
>
|
||||
{translate('connections_connection_name')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Container>
|
||||
{JDBC ? (
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type="text"
|
||||
name="url"
|
||||
state={config}
|
||||
@@ -159,9 +159,9 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
mod='surface'
|
||||
>
|
||||
{translate('customConnection_url_JDBC')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
) : (
|
||||
<ParametersFormNew
|
||||
<ParametersForm
|
||||
config={config}
|
||||
embedded={driver.data?.embedded}
|
||||
disabled={disabled}
|
||||
@@ -170,7 +170,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
/>
|
||||
)}
|
||||
{admin && originLocal && (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={config.connectionId}
|
||||
name="template"
|
||||
state={config}
|
||||
@@ -179,9 +179,9 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
// autoHide={} // maybe better to use autoHide
|
||||
>
|
||||
{translate('connections_connection_template')}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
)}
|
||||
<TextareaNew
|
||||
<Textarea
|
||||
name="description"
|
||||
rows={3}
|
||||
state={config}
|
||||
@@ -189,7 +189,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
readOnly={readonly}
|
||||
>
|
||||
{translate('connections_connection_description')}
|
||||
</TextareaNew>
|
||||
</Textarea>
|
||||
</Group>
|
||||
</Container>
|
||||
<Container medium gap>
|
||||
@@ -197,7 +197,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
<Group form gap>
|
||||
<GroupTitle>{translate('connections_connection_edit_authentication')}</GroupTitle>
|
||||
<Container wrap gap>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
autofillToken='new-password'
|
||||
properties={properties}
|
||||
state={config.credentials}
|
||||
@@ -208,13 +208,13 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
/>
|
||||
</Container>
|
||||
{credentialsSavingEnabled && (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={config.connectionId + 'authNeeded'}
|
||||
name="saveCredentials"
|
||||
state={config}
|
||||
disabled={disabled || readonly}
|
||||
>{translate('connections_connection_edit_save_credentials')}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
)}
|
||||
</Group>
|
||||
)}
|
||||
@@ -223,7 +223,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
<GroupTitle>{translate('connections_connection_edit_settings')}</GroupTitle>
|
||||
{booleanProviderProperties && booleanProviderProperties.length > 0 && (
|
||||
<Container gap wrap>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
properties={booleanProviderProperties}
|
||||
state={config.providerProperties}
|
||||
disabled={disabled}
|
||||
@@ -234,7 +234,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormProps> = observe
|
||||
)}
|
||||
{providerPropertiesWithoutBoolean && (
|
||||
<Container wrap gap>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
properties={providerPropertiesWithoutBoolean}
|
||||
state={config.providerProperties}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css, use } from 'reshadow';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { FormGroup, InputField } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Container, InputField } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { ConnectionConfig } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -19,66 +19,54 @@ interface Props {
|
||||
disabled?: boolean;
|
||||
embedded?: boolean;
|
||||
readOnly?: boolean;
|
||||
originLocal?: boolean;
|
||||
}
|
||||
|
||||
const parametersFormStyles = css`
|
||||
sub-label {
|
||||
composes: theme-typography--caption from global;
|
||||
line-height: 14px;
|
||||
}`;
|
||||
|
||||
export const ParametersForm = observer<Props>(function ParametersForm({
|
||||
config,
|
||||
embedded,
|
||||
disabled,
|
||||
readOnly,
|
||||
originLocal,
|
||||
}) {
|
||||
const translate = useTranslate();
|
||||
|
||||
return styled(useStyles(parametersFormStyles))(
|
||||
<>
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<Container gap>
|
||||
{!embedded && (
|
||||
<layout-grid-inner as="div">
|
||||
<layout-grid-cell as='div' {...use({ 'span-tablet': 12, 'span-desktop': 8 })}>
|
||||
<InputField
|
||||
type="text"
|
||||
name="host"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
mod='surface'
|
||||
>
|
||||
{translate('customConnection_custom_host')}
|
||||
<sub-label as="div">{translate('customConnection_custom_obligatory')}</sub-label>
|
||||
</InputField>
|
||||
</layout-grid-cell>
|
||||
<layout-grid-cell as='div' {...use({ 'span-tablet': 12, 'span-desktop': 4 })}>
|
||||
<InputField
|
||||
type="number"
|
||||
name="port"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
mod='surface'
|
||||
short
|
||||
>
|
||||
{translate('customConnection_custom_port')}
|
||||
</InputField>
|
||||
</layout-grid-cell>
|
||||
</layout-grid-inner>
|
||||
<Container wrap gap>
|
||||
<InputField
|
||||
type="text"
|
||||
name="host"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly || !originLocal}
|
||||
small
|
||||
required
|
||||
>
|
||||
{translate('customConnection_custom_host')}
|
||||
</InputField>
|
||||
<InputField
|
||||
type="number"
|
||||
name="port"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly || !originLocal}
|
||||
tiny
|
||||
>
|
||||
{translate('customConnection_custom_port')}
|
||||
</InputField>
|
||||
</Container>
|
||||
)}
|
||||
<FormGroup>
|
||||
<InputField
|
||||
type="text"
|
||||
name="databaseName"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
mod='surface'
|
||||
>
|
||||
{translate('customConnection_custom_database')}
|
||||
</InputField>
|
||||
</FormGroup>
|
||||
</>
|
||||
<InputField
|
||||
type="text"
|
||||
name="databaseName"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
>
|
||||
{translate('customConnection_custom_database')}
|
||||
</InputField>
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2021 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 styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, Container, InputFieldNew } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { ConnectionConfig } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
interface Props {
|
||||
config: ConnectionConfig;
|
||||
disabled?: boolean;
|
||||
embedded?: boolean;
|
||||
readOnly?: boolean;
|
||||
originLocal?: boolean;
|
||||
}
|
||||
|
||||
export const ParametersFormNew = observer<Props>(function ParametersFormNew({
|
||||
config,
|
||||
embedded,
|
||||
disabled,
|
||||
readOnly,
|
||||
originLocal,
|
||||
}) {
|
||||
const translate = useTranslate();
|
||||
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<Container gap>
|
||||
{!embedded && (
|
||||
<Container wrap gap>
|
||||
<InputFieldNew
|
||||
type="text"
|
||||
name="host"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly || !originLocal}
|
||||
small
|
||||
required
|
||||
>
|
||||
{translate('customConnection_custom_host')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
type="number"
|
||||
name="port"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly || !originLocal}
|
||||
tiny
|
||||
>
|
||||
{translate('customConnection_custom_port')}
|
||||
</InputFieldNew>
|
||||
</Container>
|
||||
)}
|
||||
<InputFieldNew
|
||||
type="text"
|
||||
name="databaseName"
|
||||
state={config}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
>
|
||||
{translate('customConnection_custom_database')}
|
||||
</InputFieldNew>
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { UserInfoResource } from '@cloudbeaver/core-authentication';
|
||||
import { TextPlaceholder, useTab, Loader, useTabState, ExceptionMessage, useMapResource, ColoredContainer, Group, ObjectPropertyInfoFormNew, BASE_CONTAINERS_STYLES } from '@cloudbeaver/core-blocks';
|
||||
import { TextPlaceholder, useTab, Loader, useTabState, ExceptionMessage, useMapResource, ColoredContainer, Group, ObjectPropertyInfoForm, BASE_CONTAINERS_STYLES } from '@cloudbeaver/core-blocks';
|
||||
import type { TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
@@ -103,7 +103,7 @@ export const OriginInfo: TabContainerPanelComponent<IConnectionFormProps> = obse
|
||||
return styled(styles)(
|
||||
<ColoredContainer parent>
|
||||
<Group large gap>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
properties={connection.data.origin.details}
|
||||
state={state}
|
||||
readOnly
|
||||
|
||||
@@ -12,7 +12,7 @@ import styled from 'reshadow';
|
||||
import { css } from 'reshadow';
|
||||
|
||||
import { useAdministrationSettings } from '@cloudbeaver/core-administration';
|
||||
import { Group, SubmittingForm, useMapResource, Button, ColoredContainer, InputFieldNew, FieldCheckboxNew, BASE_CONTAINERS_STYLES, SwitchNew, GroupItem, Container } from '@cloudbeaver/core-blocks';
|
||||
import { Group, SubmittingForm, useMapResource, Button, ColoredContainer, InputField, FieldCheckbox, BASE_CONTAINERS_STYLES, Switch, GroupItem, Container } from '@cloudbeaver/core-blocks';
|
||||
import type { TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -78,16 +78,16 @@ export const SSH: TabContainerPanelComponent<IConnectionFormProps> = observer(fu
|
||||
<SubmittingForm onSubmit={save}>
|
||||
<ColoredContainer parent>
|
||||
<Group form gap keepSize large>
|
||||
<SwitchNew
|
||||
<Switch
|
||||
name="enabled"
|
||||
state={state}
|
||||
mod={['primary']}
|
||||
disabled={disabled || readonly}
|
||||
>
|
||||
{translate('connections_network_handler_ssh_tunnel_enable')}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
<Container wrap gap>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type="text"
|
||||
name="host"
|
||||
state={state.properties}
|
||||
@@ -97,8 +97,8 @@ export const SSH: TabContainerPanelComponent<IConnectionFormProps> = observer(fu
|
||||
small
|
||||
>
|
||||
{translate('connections_network_handler_ssh_tunnel_host')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type="number"
|
||||
name="port"
|
||||
state={state.properties}
|
||||
@@ -108,10 +108,10 @@ export const SSH: TabContainerPanelComponent<IConnectionFormProps> = observer(fu
|
||||
tiny
|
||||
>
|
||||
{translate('connections_network_handler_ssh_tunnel_port')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Container>
|
||||
<Container wrap gap>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type="text"
|
||||
name="userName"
|
||||
state={state}
|
||||
@@ -121,8 +121,8 @@ export const SSH: TabContainerPanelComponent<IConnectionFormProps> = observer(fu
|
||||
tiny
|
||||
>
|
||||
{translate('connections_network_handler_ssh_tunnel_user')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type="password"
|
||||
name="password"
|
||||
placeholder={passwordHint}
|
||||
@@ -134,16 +134,16 @@ export const SSH: TabContainerPanelComponent<IConnectionFormProps> = observer(fu
|
||||
tiny
|
||||
>
|
||||
{translate('connections_network_handler_ssh_tunnel_password')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Container>
|
||||
{credentialsSavingEnabled && (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
id={SSH_TUNNEL_ID + ' savePassword'}
|
||||
name="savePassword"
|
||||
state={state}
|
||||
disabled={disabled || !enabled || readonly}
|
||||
>{translate('connections_connection_edit_save_credentials')}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
)}
|
||||
<GroupItem>
|
||||
<Button
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import { useState } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, Button, Container, InputFieldNew, SubmittingForm, useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Button, Container, InputField, SubmittingForm, useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { Translate, useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
@@ -84,12 +84,12 @@ export const RenameDialog: DialogComponent<RenameDialogPayload, string> = functi
|
||||
>
|
||||
<SubmittingForm ref={focusedRef} onSubmit={() => resolveDialog(name)}>
|
||||
<Container center>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
value={name}
|
||||
onChange={value => setName(String(value))}
|
||||
>
|
||||
{translate('ui_name') + ':'}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Container>
|
||||
</SubmittingForm>
|
||||
</CommonDialogWrapper>
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { useClipboard, Button, SanitizedHTML } from '@cloudbeaver/core-blocks';
|
||||
import { useClipboard, Button, Iframe } from '@cloudbeaver/core-blocks';
|
||||
import { CommonDialogWrapper, DialogComponent } from '@cloudbeaver/core-dialogs';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
@@ -66,7 +66,7 @@ export const ErrorDetailsDialog: DialogComponent<Error | string, null> = observe
|
||||
onReject={props.rejectDialog}
|
||||
>
|
||||
{error.reason && <property>{error.reason}</property>}
|
||||
{error.htmlBody && (<SanitizedHTML html={error.htmlBody} />)}
|
||||
{error.htmlBody && <Iframe srcDoc={error.htmlBody} />}
|
||||
{error.errors.map(
|
||||
(error, id) => (
|
||||
<>
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, SwitchNew } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Switch } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { ServerConfigInput } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -25,7 +25,7 @@ export const ServerConfigurationConfigurationForm = observer<Props>(function Ser
|
||||
const translate = useTranslate();
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<>
|
||||
<SwitchNew
|
||||
<Switch
|
||||
name="customConnectionsEnabled"
|
||||
state={serverConfig}
|
||||
description={translate('administration_configuration_wizard_configuration_custom_connections_description')}
|
||||
@@ -34,7 +34,7 @@ export const ServerConfigurationConfigurationForm = observer<Props>(function Ser
|
||||
autoHide
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_custom_connections')}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
+7
-7
@@ -10,7 +10,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { Group, GroupTitle, BASE_CONTAINERS_STYLES, InputFieldNew } from '@cloudbeaver/core-blocks';
|
||||
import { Group, GroupTitle, BASE_CONTAINERS_STYLES, InputField } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
@@ -27,7 +27,7 @@ export const ServerConfigurationInfoForm = observer<Props>(function ServerConfig
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<Group form gap medium>
|
||||
<GroupTitle>{translate('administration_configuration_wizard_configuration_server_info')}</GroupTitle>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type="text"
|
||||
name="serverName"
|
||||
state={state.serverConfig}
|
||||
@@ -36,8 +36,8 @@ export const ServerConfigurationInfoForm = observer<Props>(function ServerConfig
|
||||
medium
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_server_name')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
title={translate('administration_configuration_wizard_configuration_server_url_description')}
|
||||
type="url"
|
||||
name="serverURL"
|
||||
@@ -47,8 +47,8 @@ export const ServerConfigurationInfoForm = observer<Props>(function ServerConfig
|
||||
medium
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_server_url')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
title={translate('administration_configuration_wizard_configuration_server_session_lifetime_description')}
|
||||
type="number"
|
||||
name="sessionExpireTime"
|
||||
@@ -61,7 +61,7 @@ export const ServerConfigurationInfoForm = observer<Props>(function ServerConfig
|
||||
tiny
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_server_session_lifetime')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Group>
|
||||
);
|
||||
});
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import { useCallback } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, SwitchNew } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Switch } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { CONNECTION_NAVIGATOR_VIEW_SETTINGS, isNavigatorViewSettingsEqual } from '@cloudbeaver/core-root';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -38,7 +38,7 @@ export const ServerConfigurationNavigatorViewForm = observer<Props>(function Ser
|
||||
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<>
|
||||
<SwitchNew
|
||||
<Switch
|
||||
name="simpleNavigatorViewEnabled"
|
||||
description={translate('administration_configuration_wizard_configuration_navigation_tree_view_description')}
|
||||
mod={['primary']}
|
||||
@@ -47,7 +47,7 @@ export const ServerConfigurationNavigatorViewForm = observer<Props>(function Ser
|
||||
onChange={onNavigatorViewChangeHandler}
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_navigation_tree_view')}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
+5
-5
@@ -9,7 +9,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, Group, GroupTitle, SwitchNew } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Group, GroupTitle, Switch } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { ServerConfigInput } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -25,7 +25,7 @@ export const ServerConfigurationSecurityForm = observer<Props>(function ServerCo
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<Group form gap medium>
|
||||
<GroupTitle>{translate('administration_configuration_wizard_configuration_security')}</GroupTitle>
|
||||
<SwitchNew
|
||||
<Switch
|
||||
name="adminCredentialsSaveEnabled"
|
||||
state={serverConfig}
|
||||
description={translate('administration_configuration_wizard_configuration_security_admin_credentials_description')}
|
||||
@@ -34,8 +34,8 @@ export const ServerConfigurationSecurityForm = observer<Props>(function ServerCo
|
||||
autoHide
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_security_admin_credentials')}
|
||||
</SwitchNew>
|
||||
<SwitchNew
|
||||
</Switch>
|
||||
<Switch
|
||||
name="publicCredentialsSaveEnabled"
|
||||
state={serverConfig}
|
||||
description={translate('administration_configuration_wizard_configuration_security_public_credentials_description')}
|
||||
@@ -45,7 +45,7 @@ export const ServerConfigurationSecurityForm = observer<Props>(function ServerCo
|
||||
autoHide
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_security_public_credentials')}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
</Group>
|
||||
);
|
||||
});
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ import styled, { css, use } from 'reshadow';
|
||||
import { AuthProvidersResource } from '@cloudbeaver/core-authentication';
|
||||
import {
|
||||
TableItem, TableColumnValue, TableItemSelect, TableItemExpand,
|
||||
Placeholder, StaticImage, useMapResource, FieldCheckboxNew
|
||||
Placeholder, StaticImage, useMapResource, FieldCheckbox
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import type { AdminAuthProviderConfiguration } from '@cloudbeaver/core-sdk';
|
||||
@@ -63,7 +63,7 @@ export const AuthConfiguration = observer<Props>(function AuthConfiguration({ co
|
||||
<TableColumnValue>{configuration.providerId}</TableColumnValue>
|
||||
<TableColumnValue title={configuration.description} ellipsis>{configuration.description || ''}</TableColumnValue>
|
||||
<TableColumnValue>
|
||||
<FieldCheckboxNew checked={configuration.disabled} disabled />
|
||||
<FieldCheckbox checked={configuration.disabled} disabled />
|
||||
</TableColumnValue>
|
||||
<TableColumnValue flex {...use({ gap: true })}>
|
||||
<Placeholder container={service.configurationDetailsPlaceholder} configuration={configuration} />
|
||||
|
||||
+21
-21
@@ -12,9 +12,9 @@ import styled, { css } from 'reshadow';
|
||||
|
||||
import { AuthConfigurationParametersResource, AuthProvidersResource } from '@cloudbeaver/core-authentication';
|
||||
import {
|
||||
BASE_CONTAINERS_STYLES, ColoredContainer, ComboboxNew, FieldCheckboxNew, Group, GroupTitle,
|
||||
InputFieldNew, Link, ObjectPropertyInfoFormNew, SubmittingForm, TabContainerPanelComponent,
|
||||
TextareaNew, useClipboard, useMapResource, useObjectPropertyCategories
|
||||
BASE_CONTAINERS_STYLES, ColoredContainer, Combobox, FieldCheckbox, Group, GroupTitle,
|
||||
InputField, Link, ObjectPropertyInfoForm, SubmittingForm, TabContainerPanelComponent,
|
||||
Textarea, useClipboard, useMapResource, useObjectPropertyCategories
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { AuthProviderConfigurationParametersFragment, CachedMapAllKey } from '@cloudbeaver/core-sdk';
|
||||
@@ -56,7 +56,7 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
<SubmittingForm ref={formRef} onSubmit={state.save}>
|
||||
<ColoredContainer parent gap overflow>
|
||||
<Group small gap>
|
||||
<ComboboxNew
|
||||
<Combobox
|
||||
name='providerId'
|
||||
state={state.config}
|
||||
items={identityProviders}
|
||||
@@ -70,8 +70,8 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
fill
|
||||
>
|
||||
{translate('administration_identity_providers_provider')}
|
||||
</ComboboxNew>
|
||||
<InputFieldNew
|
||||
</Combobox>
|
||||
<InputField
|
||||
name='id'
|
||||
state={state.config}
|
||||
readOnly={state.readonly || edit}
|
||||
@@ -81,8 +81,8 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
fill
|
||||
>
|
||||
{translate('administration_identity_providers_provider_id')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
name='displayName'
|
||||
state={state.config}
|
||||
minLength={1}
|
||||
@@ -93,24 +93,24 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
fill
|
||||
>
|
||||
{translate('administration_identity_providers_provider_configuration_name')}
|
||||
</InputFieldNew>
|
||||
<TextareaNew
|
||||
</InputField>
|
||||
<Textarea
|
||||
name='description'
|
||||
state={state.config}
|
||||
disabled={state.disabled}
|
||||
readOnly={state.readonly}
|
||||
>
|
||||
{translate('administration_identity_providers_provider_configuration_description')}
|
||||
</TextareaNew>
|
||||
<InputFieldNew
|
||||
</Textarea>
|
||||
<InputField
|
||||
name='iconURL'
|
||||
state={state.config}
|
||||
disabled={state.disabled}
|
||||
readOnly={state.readonly}
|
||||
>
|
||||
{translate('administration_identity_providers_provider_configuration_icon_url')}
|
||||
</InputFieldNew>
|
||||
<FieldCheckboxNew
|
||||
</InputField>
|
||||
<FieldCheckbox
|
||||
id={edit ? state.config.id : 'AuthConfigurationDisabled'}
|
||||
name='disabled'
|
||||
state={state.config}
|
||||
@@ -118,14 +118,14 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
readOnly={state.readonly}
|
||||
>
|
||||
{translate('administration_identity_providers_provider_configuration_disabled')}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
</Group>
|
||||
{parameters.isLoaded() && parameters.data && (
|
||||
<>
|
||||
{isUncategorizedExists && (
|
||||
<Group small gap vertical>
|
||||
<GroupTitle>{translate('administration_identity_providers_provider_configuration_parameters')}</GroupTitle>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
state={state.config.parameters}
|
||||
properties={parameters.data}
|
||||
category={null}
|
||||
@@ -137,7 +137,7 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
{categories.map(category => (
|
||||
<Group key={category} small gap vertical>
|
||||
<GroupTitle keepSize>{category}</GroupTitle>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
state={state.config.parameters}
|
||||
properties={parameters.data!}
|
||||
category={category}
|
||||
@@ -152,7 +152,7 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
{(state.config.metadataLink || state.config.signInLink || state.config.signOutLink) && (
|
||||
<Group small gap>
|
||||
<GroupTitle>{translate('administration_identity_providers_provider_configuration_links')}</GroupTitle>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
name='signInLink'
|
||||
state={state.config}
|
||||
title={state.config.signInLink}
|
||||
@@ -162,8 +162,8 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
onCustomCopy={() => copy(state.config.signInLink!, true)}
|
||||
>
|
||||
Sign in
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
name='signOutLink'
|
||||
state={state.config}
|
||||
title={state.config.signOutLink}
|
||||
@@ -173,7 +173,7 @@ export const AuthConfigurationOptions: TabContainerPanelComponent<IAuthConfigura
|
||||
onCustomCopy={() => copy(state.config.signOutLink!, true)}
|
||||
>
|
||||
Sign out
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
{state.config.metadataLink && (
|
||||
<Link
|
||||
href={state.config.metadataLink}
|
||||
|
||||
+7
-7
@@ -12,7 +12,7 @@ import styled, { css } from 'reshadow';
|
||||
|
||||
import {
|
||||
BASE_CONTAINERS_STYLES, ColoredContainer, Group,
|
||||
InputFieldNew, SubmittingForm, TabContainerPanelComponent, TextareaNew,
|
||||
InputField, SubmittingForm, TabContainerPanelComponent, Textarea,
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -39,7 +39,7 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
|
||||
<SubmittingForm ref={formRef} onSubmit={state.save}>
|
||||
<ColoredContainer parent gap overflow>
|
||||
<Group small gap>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
name='roleId'
|
||||
state={state.config}
|
||||
readOnly={state.readonly || edit}
|
||||
@@ -49,8 +49,8 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
|
||||
fill
|
||||
>
|
||||
{translate('administration_roles_role_id')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
name='roleName'
|
||||
state={state.config}
|
||||
readOnly={state.readonly}
|
||||
@@ -59,8 +59,8 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
|
||||
fill
|
||||
>
|
||||
{translate('administration_roles_role_name')}
|
||||
</InputFieldNew>
|
||||
<TextareaNew
|
||||
</InputField>
|
||||
<Textarea
|
||||
name='description'
|
||||
state={state.config}
|
||||
readOnly={state.readonly}
|
||||
@@ -69,7 +69,7 @@ export const RoleOptions: TabContainerPanelComponent<IRoleFormProps> = observer(
|
||||
fill
|
||||
>
|
||||
{translate('administration_roles_role_description')}
|
||||
</TextareaNew>
|
||||
</Textarea>
|
||||
</Group>
|
||||
</ColoredContainer>
|
||||
</SubmittingForm>
|
||||
|
||||
+7
-7
@@ -11,7 +11,7 @@ import { useContext } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { AuthProviderService, AuthProvidersResource, AUTH_PROVIDER_LOCAL_ID } from '@cloudbeaver/core-authentication';
|
||||
import { BASE_CONTAINERS_STYLES, Container, FormContext, Group, GroupTitle, Loader, PlaceholderComponent, SwitchNew, useExecutor, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Container, FormContext, Group, GroupTitle, Loader, PlaceholderComponent, Switch, useExecutor, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
|
||||
@@ -58,7 +58,7 @@ export const AuthenticationProviders: PlaceholderComponent<IConfigurationPlaceho
|
||||
<>
|
||||
<Group key='authentication' form gap medium>
|
||||
<GroupTitle>{translate('administration_configuration_wizard_configuration_authentication_group')}</GroupTitle>
|
||||
<SwitchNew
|
||||
<Switch
|
||||
name="anonymousAccessEnabled"
|
||||
state={serverConfig}
|
||||
description={translate('administration_configuration_wizard_configuration_anonymous_access_description')}
|
||||
@@ -68,10 +68,10 @@ export const AuthenticationProviders: PlaceholderComponent<IConfigurationPlaceho
|
||||
autoHide
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_anonymous_access')}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
<Loader state={providers} inline>
|
||||
{() => localProvider && styled(styles)(
|
||||
<SwitchNew
|
||||
<Switch
|
||||
key={localProvider.id}
|
||||
value={localProvider.id}
|
||||
name="enabledAuthProviders"
|
||||
@@ -82,7 +82,7 @@ export const AuthenticationProviders: PlaceholderComponent<IConfigurationPlaceho
|
||||
autoHide
|
||||
>
|
||||
{localProvider.label}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
)}
|
||||
</Loader>
|
||||
</Group>
|
||||
@@ -101,7 +101,7 @@ export const AuthenticationProviders: PlaceholderComponent<IConfigurationPlaceho
|
||||
const links = authProviderService.getServiceDescriptionLinks(provider);
|
||||
|
||||
return (
|
||||
<SwitchNew
|
||||
<Switch
|
||||
key={provider.id}
|
||||
value={provider.id}
|
||||
name="enabledAuthProviders"
|
||||
@@ -121,7 +121,7 @@ export const AuthenticationProviders: PlaceholderComponent<IConfigurationPlaceho
|
||||
autoHide
|
||||
>
|
||||
{provider.label}
|
||||
</SwitchNew>
|
||||
</Switch>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
|
||||
+5
-5
@@ -10,7 +10,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, Group, GroupTitle, InputFieldNew } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Group, GroupTitle, InputField } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { ServerConfigInput } from '@cloudbeaver/core-sdk';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
@@ -28,7 +28,7 @@ export const ServerConfigurationAdminForm = observer<Props>(function ServerConfi
|
||||
return styled(style)(
|
||||
<Group form gap medium>
|
||||
<GroupTitle>{translate('administration_configuration_wizard_configuration_admin')}</GroupTitle>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type="text"
|
||||
name="adminName"
|
||||
state={serverConfig}
|
||||
@@ -38,8 +38,8 @@ export const ServerConfigurationAdminForm = observer<Props>(function ServerConfi
|
||||
tiny
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_admin_name')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type="password"
|
||||
name="adminPassword"
|
||||
state={serverConfig}
|
||||
@@ -49,7 +49,7 @@ export const ServerConfigurationAdminForm = observer<Props>(function ServerConfi
|
||||
tiny
|
||||
>
|
||||
{translate('administration_configuration_wizard_configuration_admin_password')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Group>
|
||||
);
|
||||
});
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { AUTH_PROVIDER_LOCAL_ID, UserInfoResource, UsersResource } from '@cloudbeaver/core-authentication';
|
||||
import { TextPlaceholder, useTab, Loader, useTabState, ExceptionMessage, BASE_CONTAINERS_STYLES, ColoredContainer, ObjectPropertyInfoFormNew, Group } from '@cloudbeaver/core-blocks';
|
||||
import { TextPlaceholder, useTab, Loader, useTabState, ExceptionMessage, BASE_CONTAINERS_STYLES, ColoredContainer, ObjectPropertyInfoForm, Group } from '@cloudbeaver/core-blocks';
|
||||
import type { TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
@@ -132,7 +132,7 @@ export const OriginInfo: TabContainerPanelComponent<IUserFormProps> = observer(f
|
||||
return styled(style)(
|
||||
<ColoredContainer parent>
|
||||
<Group gap large>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
properties={state.properties}
|
||||
state={state.state}
|
||||
readOnly
|
||||
|
||||
+9
-9
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import { useCallback } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, ColoredContainer, FieldCheckboxNew, Group, GroupTitle, InputFieldNew, TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, ColoredContainer, FieldCheckbox, Group, GroupTitle, InputField, TabContainerPanelComponent } from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
import { uuid } from '@cloudbeaver/core-utils';
|
||||
@@ -38,7 +38,7 @@ export const UserInfo: TabContainerPanelComponent<IUserFormProps> = observer(fun
|
||||
<ColoredContainer parent gap overflow>
|
||||
<Group small gap vertical overflow>
|
||||
<GroupTitle keepSize>{translate('authentication_user_credentials')}</GroupTitle>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type='text'
|
||||
name='login'
|
||||
state={controller.credentials}
|
||||
@@ -50,10 +50,10 @@ export const UserInfo: TabContainerPanelComponent<IUserFormProps> = observer(fun
|
||||
required
|
||||
>
|
||||
{translate('authentication_user_name')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
{controller.local && (
|
||||
<>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
type='password'
|
||||
name='password'
|
||||
state={controller.credentials}
|
||||
@@ -66,8 +66,8 @@ export const UserInfo: TabContainerPanelComponent<IUserFormProps> = observer(fun
|
||||
required
|
||||
>
|
||||
{translate('authentication_user_password')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type='password'
|
||||
name='passwordRepeat'
|
||||
state={controller.credentials}
|
||||
@@ -79,7 +79,7 @@ export const UserInfo: TabContainerPanelComponent<IUserFormProps> = observer(fun
|
||||
required
|
||||
>
|
||||
{translate('authentication_user_password_repeat')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</>
|
||||
)}
|
||||
</Group>
|
||||
@@ -89,7 +89,7 @@ export const UserInfo: TabContainerPanelComponent<IUserFormProps> = observer(fun
|
||||
const label = `${role.roleId}${role.roleName && role.roleName !== role.roleId ? ' (' + role.roleName + ')' : ''}`;
|
||||
const tooltip = `${label}${role.description ? '\n' + role.description : ''}`;
|
||||
return (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
key={role.roleId}
|
||||
id={uuid()}
|
||||
title={tooltip}
|
||||
@@ -99,7 +99,7 @@ export const UserInfo: TabContainerPanelComponent<IUserFormProps> = observer(fun
|
||||
onChange={checked => handleRoleChange(role.roleId, checked)}
|
||||
>
|
||||
{label}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
);
|
||||
})}
|
||||
</Group>
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ import { useCallback } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import type { AuthProvider } from '@cloudbeaver/core-authentication';
|
||||
import { BASE_CONTAINERS_STYLES, Group, InputFieldNew, useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Group, InputField, useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { useStyles } from '@cloudbeaver/core-theming';
|
||||
|
||||
interface Props {
|
||||
@@ -33,7 +33,7 @@ export const AuthProviderForm = observer<Props>(function AuthProviderForm({
|
||||
return styled(useStyles(BASE_CONTAINERS_STYLES))(
|
||||
<Group ref={elementRef} gap small center>
|
||||
{provider.credentialParameters.map(parameter => parameter.user && (
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
key={parameter.id}
|
||||
title={parameter.description}
|
||||
type={parameter.encryption === 'none' ? 'text' : 'password'}
|
||||
@@ -45,7 +45,7 @@ export const AuthProviderForm = observer<Props>(function AuthProviderForm({
|
||||
onChange={value => handleChange(parameter.id, value)}
|
||||
>
|
||||
{parameter.displayName}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
))}
|
||||
</Group>
|
||||
);
|
||||
|
||||
+7
-7
@@ -12,7 +12,7 @@ import { useState, useCallback, useEffect } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { UsersResource } from '@cloudbeaver/core-authentication';
|
||||
import { BASE_CONTAINERS_STYLES, Container, ErrorMessage, Group, InputFieldNew, SubmittingForm, useErrorDetails, useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Container, ErrorMessage, Group, InputField, SubmittingForm, useErrorDetails, useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogWrapper, DialogComponent, DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
@@ -113,7 +113,7 @@ export const ChangeUserPasswordDialog: DialogComponent<null, null> = observer(
|
||||
<SubmittingForm onSubmit={change}>
|
||||
<Container>
|
||||
<Group small gap center>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
ref={focusedRef}
|
||||
type='password'
|
||||
name='oldPassword'
|
||||
@@ -124,8 +124,8 @@ export const ChangeUserPasswordDialog: DialogComponent<null, null> = observer(
|
||||
required
|
||||
>
|
||||
{translate('authentication_user_current_password')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type='password'
|
||||
name='newPassword'
|
||||
autoComplete='new-password'
|
||||
@@ -136,8 +136,8 @@ export const ChangeUserPasswordDialog: DialogComponent<null, null> = observer(
|
||||
required
|
||||
>
|
||||
{translate('authentication_user_new_password')}
|
||||
</InputFieldNew>
|
||||
<InputFieldNew
|
||||
</InputField>
|
||||
<InputField
|
||||
type='password'
|
||||
name='repeatedPassword'
|
||||
state={state}
|
||||
@@ -147,7 +147,7 @@ export const ChangeUserPasswordDialog: DialogComponent<null, null> = observer(
|
||||
required
|
||||
>
|
||||
{translate('authentication_user_password_repeat')}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</Group>
|
||||
</Container>
|
||||
</SubmittingForm>
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import { useState, useCallback, useRef, useEffect } from 'react';
|
||||
import { css } from 'reshadow';
|
||||
|
||||
import { Button, InputFieldNew } from '@cloudbeaver/core-blocks';
|
||||
import { Button, InputField } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogWrapper, DialogComponent, DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
@@ -79,14 +79,14 @@ export const FilterCustomValueDialog: DialogComponent<IPayload, string | number>
|
||||
noOverflow
|
||||
onReject={rejectDialog}
|
||||
>
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
ref={inputRef}
|
||||
name='customValue'
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
>
|
||||
{payload.inputTitle}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
</CommonDialogWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ import { observable } from 'mobx';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { BASE_CONTAINERS_STYLES, TabContainerPanelComponent, TabList, TabsState, TextareaNew, UNDERLINE_TAB_STYLES, useObservableRef } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, TabContainerPanelComponent, TabList, TabsState, Textarea, UNDERLINE_TAB_STYLES, useObservableRef } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { composes, useStyles } from '@cloudbeaver/core-theming';
|
||||
import { CodeEditorLoader } from '@cloudbeaver/plugin-codemirror';
|
||||
@@ -48,7 +48,7 @@ const styles = composes(
|
||||
padding: 0 8px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
TextareaNew {
|
||||
Textarea {
|
||||
flex: 1;
|
||||
}
|
||||
CodeEditorLoader {
|
||||
@@ -170,7 +170,7 @@ export const TextValuePresentation: TabContainerPanelComponent<IDataValuePanelPr
|
||||
onBeforeChange={(editor, data, value) => handleChange(value)}
|
||||
/>
|
||||
) : (
|
||||
<TextareaNew
|
||||
<Textarea
|
||||
name="value"
|
||||
rows={3}
|
||||
value={stringValue}
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { DBObjectResource, NavNodeInfoResource, NavTreeResource } from '@cloudbeaver/core-app';
|
||||
import { ColoredContainer, Loader, TextPlaceholder, useObjectPropertyCategories, GroupTitle, ObjectPropertyInfoFormNew, Group, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { ColoredContainer, Loader, TextPlaceholder, useObjectPropertyCategories, GroupTitle, ObjectPropertyInfoForm, Group, useMapResource } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES } from '@cloudbeaver/core-blocks';
|
||||
import { ConnectionInfoResource } from '@cloudbeaver/core-connections';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
@@ -59,7 +59,7 @@ export const ObjectProperties = observer<Props>(function ObjectProperties({
|
||||
<ColoredContainer overflow parent gap>
|
||||
{isUncategorizedExists && (
|
||||
<Group gap large>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
properties={properties}
|
||||
category={null}
|
||||
small
|
||||
@@ -70,7 +70,7 @@ export const ObjectProperties = observer<Props>(function ObjectProperties({
|
||||
{categories.map(category => (
|
||||
<Group key={category} gap large>
|
||||
<GroupTitle>{category}</GroupTitle>
|
||||
<ObjectPropertyInfoFormNew
|
||||
<ObjectPropertyInfoForm
|
||||
properties={properties}
|
||||
category={category}
|
||||
small
|
||||
|
||||
+5
-5
@@ -8,7 +8,7 @@
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { FieldCheckboxNew, InputFieldNew } from '@cloudbeaver/core-blocks';
|
||||
import { FieldCheckbox, InputField } from '@cloudbeaver/core-blocks';
|
||||
|
||||
import type { ObjectPropertyProps } from '../../formControls';
|
||||
import { additionalProps, filterProperty, getValue, matchType } from '../../helpers';
|
||||
@@ -25,7 +25,7 @@ export const ObjectProperty = observer<ObjectPropertyProps>(function ObjectPrope
|
||||
<>
|
||||
{matchType(objectProperty.dataType) === 'checkbox'
|
||||
? (
|
||||
<FieldCheckboxNew
|
||||
<FieldCheckbox
|
||||
className={className}
|
||||
title={objectProperty.description}
|
||||
name={objectProperty.id}
|
||||
@@ -34,10 +34,10 @@ export const ObjectProperty = observer<ObjectPropertyProps>(function ObjectPrope
|
||||
{...additionalProps(objectProperty)}
|
||||
>
|
||||
{objectProperty.displayName}
|
||||
</FieldCheckboxNew>
|
||||
</FieldCheckbox>
|
||||
)
|
||||
: (
|
||||
<InputFieldNew
|
||||
<InputField
|
||||
className={className}
|
||||
title={objectProperty.description}
|
||||
name={objectProperty.id}
|
||||
@@ -45,7 +45,7 @@ export const ObjectProperty = observer<ObjectPropertyProps>(function ObjectPrope
|
||||
readOnly
|
||||
{...additionalProps(objectProperty)}
|
||||
>{objectProperty.displayName}
|
||||
</InputFieldNew>
|
||||
</InputField>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { useAppVersion } from '@cloudbeaver/core-app';
|
||||
import { BASE_CONTAINERS_STYLES, Button, ColoredContainer, FormFieldDescriptionNew, Group, IconOrImage, Link, TextPlaceholder } from '@cloudbeaver/core-blocks';
|
||||
import { BASE_CONTAINERS_STYLES, Button, ColoredContainer, FormFieldDescription, Group, IconOrImage, Link, TextPlaceholder } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogWrapper, DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
@@ -29,7 +29,7 @@ const productInfoDialogStyles = css`
|
||||
display: flex;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
FormFieldDescriptionNew {
|
||||
FormFieldDescription {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
IconOrImage {
|
||||
@@ -72,33 +72,33 @@ export const ProductInfoDialog = observer<DialogComponentProps<null>>(
|
||||
) : (
|
||||
<>
|
||||
<IconOrImage icon={logoIcon} />
|
||||
<FormFieldDescriptionNew label={translate('app_product_info_name')}>
|
||||
<FormFieldDescription label={translate('app_product_info_name')}>
|
||||
{productInfo.name}
|
||||
</FormFieldDescriptionNew>
|
||||
<FormFieldDescriptionNew label={translate('app_product_info_description')}>
|
||||
</FormFieldDescription>
|
||||
<FormFieldDescription label={translate('app_product_info_description')}>
|
||||
{productInfo.description}
|
||||
</FormFieldDescriptionNew>
|
||||
</FormFieldDescription>
|
||||
{productInfo.licenseInfo && (
|
||||
<FormFieldDescriptionNew label={translate('app_product_info_license_info')}>
|
||||
<FormFieldDescription label={translate('app_product_info_license_info')}>
|
||||
{productInfo.licenseInfo}
|
||||
</FormFieldDescriptionNew>
|
||||
</FormFieldDescription>
|
||||
)}
|
||||
<FormFieldDescriptionNew label={translate('app_product_info_build_time')}>
|
||||
<FormFieldDescription label={translate('app_product_info_build_time')}>
|
||||
{productInfo.buildTime}
|
||||
</FormFieldDescriptionNew>
|
||||
<FormFieldDescriptionNew label="Backend version">
|
||||
</FormFieldDescription>
|
||||
<FormFieldDescription label="Backend version">
|
||||
{productInfo.version}
|
||||
</FormFieldDescriptionNew>
|
||||
<FormFieldDescriptionNew label="Frontend version">
|
||||
</FormFieldDescription>
|
||||
<FormFieldDescription label="Frontend version">
|
||||
{version.frontendVersion}
|
||||
</FormFieldDescriptionNew>
|
||||
<FormFieldDescriptionNew label={translate('app_product_info_contacts')}>
|
||||
<contacts-info as='div'>You can contact us via our
|
||||
</FormFieldDescription>
|
||||
<FormFieldDescription label={translate('app_product_info_contacts')}>
|
||||
<contacts-info>You can contact us via our
|
||||
<Link href="https://cloudbeaver.io/contact/" target='_blank' rel='noopener noreferrer'> Site </Link>
|
||||
or
|
||||
<Link href="https://github.com/dbeaver/cloudbeaver" target='_blank' rel='noopener noreferrer'> Github</Link>
|
||||
</contacts-info>
|
||||
</FormFieldDescriptionNew>
|
||||
</FormFieldDescription>
|
||||
</>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ import styled, { css } from 'reshadow';
|
||||
|
||||
import {
|
||||
Split, Pane, ResizerControls, splitStyles, TextPlaceholder,
|
||||
Table, TableHeader, TableColumnHeader, TableBody, TextareaNew
|
||||
Table, TableHeader, TableColumnHeader, TableBody, Textarea
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
import type { SqlExecutionPlanNode } from '@cloudbeaver/core-sdk';
|
||||
@@ -46,7 +46,7 @@ const styles = composes(
|
||||
Pane:last-child {
|
||||
flex: 0 0 150px;
|
||||
}
|
||||
TextareaNew > :global(textarea) {
|
||||
Textarea > :global(textarea) {
|
||||
border: none !important;
|
||||
}
|
||||
`
|
||||
@@ -97,7 +97,7 @@ export const ExecutionPlanTreeBlock = observer<Props>(function ExecutionPlanTree
|
||||
</Pane>
|
||||
<ResizerControls />
|
||||
<Pane main>
|
||||
<TextareaNew
|
||||
<Textarea
|
||||
className={className}
|
||||
name='value'
|
||||
rows={3}
|
||||
|
||||
@@ -9782,11 +9782,6 @@ parse-path@^4.0.0:
|
||||
qs "^6.9.4"
|
||||
query-string "^6.13.8"
|
||||
|
||||
parse-srcset@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
|
||||
integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=
|
||||
|
||||
parse-url@^5.0.0:
|
||||
version "5.0.7"
|
||||
resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.7.tgz#2ca3c32816f1a092c35e1f2afe63bb7924dde261"
|
||||
@@ -11083,11 +11078,6 @@ react-popper@^2.2.5:
|
||||
react-fast-compare "^3.0.1"
|
||||
warning "^4.0.2"
|
||||
|
||||
react-sanitized-html@^2.x.x:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-sanitized-html/-/react-sanitized-html-2.0.0.tgz#2ac300ae60e8e7cb28378b1233b9630e415d0241"
|
||||
integrity sha512-G1n8smzDSqiHoBtvfJqcyvDKXlWTrvARRgWoSKhqeDVxxb9emO4ourS1OYnzV6yxx/G4jLqzaFSx8b6roL29Kw==
|
||||
|
||||
react@>=15, react@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
@@ -11757,16 +11747,6 @@ safe-regex@^1.1.0:
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
sanitize-html@^1.x.x:
|
||||
version "1.27.5"
|
||||
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.27.5.tgz#6c8149462adb23e360e1bb71cc0bae7f08c823c7"
|
||||
integrity sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A==
|
||||
dependencies:
|
||||
htmlparser2 "^4.1.0"
|
||||
lodash "^4.17.15"
|
||||
parse-srcset "^1.0.2"
|
||||
postcss "^7.0.27"
|
||||
|
||||
sass-graph@2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.5.tgz#a981c87446b8319d96dce0671e487879bd24c2e8"
|
||||
|
||||
Reference in New Issue
Block a user