diff --git a/webapp/packages/core-app/public/icons/icons.svg b/webapp/packages/core-app/public/icons/icons.svg index ba0ebf32e9..bded064902 100644 --- a/webapp/packages/core-app/public/icons/icons.svg +++ b/webapp/packages/core-app/public/icons/icons.svg @@ -29,6 +29,10 @@ + + + + diff --git a/webapp/packages/core-blocks/src/Button.tsx b/webapp/packages/core-blocks/src/Button.tsx index 3506f36390..f9b6660757 100644 --- a/webapp/packages/core-blocks/src/Button.tsx +++ b/webapp/packages/core-blocks/src/Button.tsx @@ -13,6 +13,7 @@ import { use } from 'reshadow'; import { useStyles, composes } from '@cloudbeaver/core-theming'; +import { Icon } from './Icons'; import { Loader } from './Loader/Loader'; import { useObjectRef } from './useObjectRef'; @@ -21,6 +22,12 @@ const buttonStyles = composes( Button { composes: theme-button from global; } + button-label { + composes: theme-button__label from global; + } + button-icon { + composes: theme-button__icon from global; + } ripple { composes: theme-button_ripple from global; } @@ -92,6 +99,8 @@ type ButtonProps = ( & React.LinkHTMLAttributes ) & { loading?: boolean; + icon?: string; + viewBox?: string; mod?: Array; tag?: 'button' | 'a'; href?: string; @@ -103,6 +112,8 @@ type ButtonProps = ( export const Button: React.FC = observer(function Button({ children, + icon, + viewBox, mod, tag = 'button', disabled = false, @@ -139,8 +150,9 @@ export const Button: React.FC = observer(function Button({ const Button = tag; return styled(useStyles(buttonStyles, ...(mod || []).map(mod => buttonMod[mod])))( ); diff --git a/webapp/packages/core-blocks/src/Containers/BASE_CONTAINERS_STYLES.ts b/webapp/packages/core-blocks/src/Containers/BASE_CONTAINERS_STYLES.ts index 4cad4d9483..24eecfdc2e 100644 --- a/webapp/packages/core-blocks/src/Containers/BASE_CONTAINERS_STYLES.ts +++ b/webapp/packages/core-blocks/src/Containers/BASE_CONTAINERS_STYLES.ts @@ -71,6 +71,11 @@ export const BASE_CONTAINERS_STYLES = composes( margin-right: 25%; } + &[box] { + padding: 0; + overflow: hidden; + } + &[center] { margin: 0 auto; } diff --git a/webapp/packages/core-blocks/src/Containers/Group.tsx b/webapp/packages/core-blocks/src/Containers/Group.tsx index 9f56c2222c..a4f1666db6 100644 --- a/webapp/packages/core-blocks/src/Containers/Group.tsx +++ b/webapp/packages/core-blocks/src/Containers/Group.tsx @@ -12,6 +12,7 @@ interface Props extends IContainerProps { className?: string; form?: boolean; center?: boolean; + box?: boolean; } export const Group: React.FC = function Group({ children, className }) { diff --git a/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx b/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx index a18e4c73ab..7ad9cad8ad 100644 --- a/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx +++ b/webapp/packages/core-blocks/src/PropertiesTable/PropertiesTable.tsx @@ -6,8 +6,9 @@ * you may not use this file except in compliance with the License. */ +import { computed } from 'mobx'; import { observer } from 'mobx-react-lite'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import styled from 'reshadow'; import { useTranslate } from '@cloudbeaver/core-localization'; @@ -21,22 +22,25 @@ import { PROPERTIES_TABLE_STYLES } from './styles'; type PropertiesState = Record; -interface PropertiesTableProps { +interface Props { properties: IProperty[]; propertiesState?: PropertiesState; readOnly?: boolean; onKeyChange?: (id: string, name: string) => void; onChange?: (state: PropertiesState) => void; onAdd?: () => void; - onRemove?: (id: string) => void; + onRemove?: (property: IProperty) => void; className?: string; } -export const PropertiesTable = observer(function PropertiesTable(props: PropertiesTableProps) { +export const PropertiesTable = observer(function PropertiesTable(props: Props) { const { className, onAdd, readOnly, propertiesState } = props; const translate = useTranslate(); const propsRef = useObjectRef({ ...props }); + const sortedProperties = useMemo(() => computed(() => propsRef.properties.slice().sort( + (a, b) => (a?.displayName ?? '').localeCompare(b?.displayName ?? ''))), [propsRef.properties]); + const changeName = useCallback((id: string, key: string) => { const { properties, propertiesState, onKeyChange } = propsRef; const property = properties.find(property => property.id === id); @@ -92,9 +96,8 @@ export const PropertiesTable = observer(function PropertiesTable(props: Properti } if (onRemove) { - onRemove(id); + onRemove(property); } - properties.splice(properties.indexOf(property), 1); }, []); const isKeyUnique = useCallback( @@ -102,24 +105,30 @@ export const PropertiesTable = observer(function PropertiesTable(props: Properti [] ); - const alphabetOrderProperties = propsRef.properties.slice().sort( - (a, b) => (a?.displayName ?? '').localeCompare(b?.displayName ?? '')); - return styled(useStyles(PROPERTIES_TABLE_STYLES))( - - - + + + {translate('block_properties_table_name')} - + {translate('block_properties_table_value')} - - {onAdd && !readOnly && } - - - {alphabetOrderProperties.map(property => ( + + {onAdd && !readOnly && ( + + + + )} + {sortedProperties.get().map(property => ( tabId, state: formState, }) { - const style = useStyles(styles); + const style = useStyles(styles, BASE_CONTAINERS_STYLES); const { selected } = useTab(tabId); const [state] = useState(() => { @@ -50,7 +53,11 @@ export const DriverProperties: TabContainerPanelComponent }); } - return { propertiesList, add }; + function remove(property: IProperty) { + propertiesList.splice(propertiesList.indexOf(property), 1); + } + + return { propertiesList, add, remove }; }); const driver = useMapResource( @@ -87,17 +94,20 @@ export const DriverProperties: TabContainerPanelComponent ])), [driver.data]); return styled(style)( - - - {() => ( - - )} - - + + {() => styled(style)( + + + + + + )} + ); }); diff --git a/webapp/packages/core-theming/src/styles/_button.scss b/webapp/packages/core-theming/src/styles/_button.scss index ef4a93f13c..45f76dacb1 100644 --- a/webapp/packages/core-theming/src/styles/_button.scss +++ b/webapp/packages/core-theming/src/styles/_button.scss @@ -15,12 +15,18 @@ .theme-button { composes: mdc-button; - height: 28px; + height: 32px; &[disabled] { opacity: 1; } } + .theme-button__label { + composes: mdc-button__label; + } + .theme-button__icon { + composes: mdc-button__icon; + } .theme-button_ripple { composes: mdc-button__ripple; }