mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-28 03:41:48 +08:00
Cb 3963 migrate core view to css modules (#2192)
* CB-3963 error message reshadow refactor
* CB-3963 remove extra reshadow use from ItemListSearch
* CB-3963 remove reshadow from TopAppBar
* CB-3963 remove unused LoadingScreen component
* CB-3963 removed reshadow from VersionUpdate
* CB-3963 removed reshadow from VersionSelector
* CB-3963 removed reshadow from renderLayout
* CB-3963 removed reshadow from AuthenticationProvider
* CB-3963 removed reshadow from VersionInfo
* CB-3963 removed reshadow from TableItemSelect
* CB-3963 removed reshadow from CaptureView
* CB-3963 removed reshadow from ConnectionList
* CB-3963 removed reshadow from WizzardStepper
* CB-3963 removed reshadow from ConfigurationWizardTittle
* Revert "CB-3963 removed reshadow from AuthenticationProvider"
This reverts commit d5828c2689.
* CB.3963 fix checkboxes margin in table items
---------
Co-authored-by: s.teleshev <s.teleshev@mu.se>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
This commit is contained in:
co-authored by
s.teleshev
mr-anton-t
parent
e9081598e3
commit
9a69f4e660
@@ -0,0 +1,30 @@
|
||||
.message {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: var(--theme-group-element-radius);
|
||||
height: 50px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.errorIcon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.messageBody {
|
||||
composes: theme-typography--body2 from global;
|
||||
max-height: 100%;
|
||||
line-height: 1.2;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
-webkit-line-clamp: 2;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.messageActions {
|
||||
margin-left: 16px;
|
||||
}
|
||||
@@ -6,43 +6,13 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button } from './Button';
|
||||
import { IconOrImage } from './IconOrImage';
|
||||
import { useTranslate } from './localization/useTranslate';
|
||||
import { useS } from './useS';
|
||||
|
||||
const styles = css`
|
||||
message {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: var(--theme-group-element-radius);
|
||||
height: 50px;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
IconOrImage {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
message-body {
|
||||
composes: theme-typography--body2 from global;
|
||||
max-height: 100%;
|
||||
line-height: 1.2;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
-webkit-line-clamp: 2;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
message-actions {
|
||||
margin-left: 16px;
|
||||
}
|
||||
`;
|
||||
import styles from './ErrorMessage.m.css';
|
||||
import { s } from './s';
|
||||
|
||||
interface Props {
|
||||
hasDetails?: boolean;
|
||||
@@ -53,18 +23,19 @@ interface Props {
|
||||
|
||||
export const ErrorMessage = observer<Props>(function ErrorMessage({ text, className, hasDetails, onShowDetails }) {
|
||||
const translate = useTranslate();
|
||||
const style = useS(styles);
|
||||
|
||||
return styled(styles)(
|
||||
<message className={className}>
|
||||
<IconOrImage icon="/icons/error_icon_sm.svg" />
|
||||
<message-body title={text}>{text}</message-body>
|
||||
<message-actions>
|
||||
return (
|
||||
<div className={s(style, { message: true }, className)}>
|
||||
<IconOrImage className={s(style, { errorIcon: true })} icon="/icons/error_icon_sm.svg" />
|
||||
<div className={s(style, { messageBody: true })} title={text}>{text}</div>
|
||||
<div className={s(style, { messageActions: true })}>
|
||||
{hasDetails && (
|
||||
<Button type="button" mod={['outlined']} onClick={onShowDetails}>
|
||||
{translate('ui_errors_details')}
|
||||
</Button>
|
||||
)}
|
||||
</message-actions>
|
||||
</message>,
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { use } from 'reshadow';
|
||||
|
||||
import { IconButton } from '../IconButton';
|
||||
import { useTranslate } from '../localization/useTranslate';
|
||||
@@ -67,7 +66,6 @@ export const ItemListSearch: React.FC<IProps> = function ItemListSearch({ value,
|
||||
autoComplete="off"
|
||||
disabled={disabled}
|
||||
onChange={event => changeHandler(event.target.value)}
|
||||
{...use({ mod: 'surface' })}
|
||||
/>
|
||||
<div className={s(styles, { actionButton: true })}>
|
||||
{!onSearch && inputValue ? (
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2023 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 { useEffect, useRef } from 'react';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { Icon } from '../Icon';
|
||||
import styles from './loading-screen.css';
|
||||
|
||||
const FADE_IN_DELAY = 300;
|
||||
|
||||
function LoadingScreen() {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
const appContainer = document.querySelector('#__next')!;
|
||||
const loadingNode = appContainer.appendChild(ref.current!.cloneNode(true));
|
||||
setTimeout(() => (loadingNode as any).classList.add(styles.fadeIn));
|
||||
setTimeout(() => appContainer.removeChild(loadingNode), FADE_IN_DELAY);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return styled(styles)(
|
||||
<div ref={ref}>
|
||||
<Icon name="logo" viewBox="0 0 1755.6533 681.13202" />
|
||||
</div>,
|
||||
);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
:global(html) {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
background-color: #ffffff;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fadeIn {
|
||||
transition: opacity 0.3s ease;
|
||||
opacity: 0;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
Icon {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
div::before {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
z-index: 1;
|
||||
width: 500%;
|
||||
margin-left: -250%;
|
||||
animation: wave 1.3s linear infinite;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
rgba(255, 255, 255, 0) 46%,
|
||||
rgba(255, 255, 255, 0.35) 50%,
|
||||
rgba(255, 255, 255, 0) 54%
|
||||
)
|
||||
50% 50%;
|
||||
}
|
||||
|
||||
@keyframes wave {
|
||||
0% {
|
||||
transform: translate3d(-30%, 0, 0);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(30%, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Icon } from '../Icon';
|
||||
import { s } from '../s';
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.checkbox {
|
||||
margin-left: -10px;
|
||||
margin-right: -10px;
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useContext } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { EventContext } from '@cloudbeaver/core-events';
|
||||
|
||||
@@ -15,6 +14,9 @@ import { Checkbox } from '../FormControls/Checkboxes/Checkbox';
|
||||
import { EventTableItemSelectionFlag } from './EventTableItemSelectionFlag';
|
||||
import { TableContext } from './TableContext';
|
||||
import { TableItemContext } from './TableItemContext';
|
||||
import { useS } from '../useS';
|
||||
import styles from './TableItemSelect.m.css';
|
||||
import { s } from '../s';
|
||||
|
||||
interface Props {
|
||||
checked?: boolean;
|
||||
@@ -23,17 +25,11 @@ interface Props {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const styles = css`
|
||||
Checkbox {
|
||||
margin-left: -10px;
|
||||
margin-right: -10px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const TableItemSelect = observer<Props>(function TableItemSelect({ checked, disabled, tooltip, className }) {
|
||||
const tableContext = useContext(TableContext);
|
||||
const context = useContext(TableItemContext);
|
||||
const selected = checked ?? context?.isSelected();
|
||||
const style = useS(styles);
|
||||
|
||||
function handleClick(event: React.MouseEvent<HTMLInputElement>) {
|
||||
if (!context) {
|
||||
@@ -48,7 +44,13 @@ export const TableItemSelect = observer<Props>(function TableItemSelect({ checke
|
||||
return null;
|
||||
}
|
||||
|
||||
return styled(styles)(
|
||||
<Checkbox className={className} title={tooltip} disabled={context.selectDisabled || disabled} checked={selected} onClick={handleClick} />,
|
||||
return (
|
||||
<Checkbox
|
||||
className={s(style, { checkbox: true }, className)}
|
||||
title={tooltip}
|
||||
disabled={context.selectDisabled || disabled}
|
||||
checked={selected}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
.header {
|
||||
composes: theme-text-on-primary theme-typography--body2 from global;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
padding: 0 8px;
|
||||
background-color: #2a7cb4;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -5,25 +5,17 @@
|
||||
* 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';
|
||||
|
||||
export const topAppBarStyles = css`
|
||||
header {
|
||||
composes: theme-text-on-primary theme-typography--body2 from global;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
padding: 0 8px;
|
||||
background-color: #2a7cb4;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
`;
|
||||
import { s } from '../s';
|
||||
import { useS } from '../useS';
|
||||
import styles from './TopAppBar.m.css';
|
||||
|
||||
interface Props extends React.PropsWithChildren {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const TopAppBar: React.FC<Props> = function TopAppBar({ children, className }) {
|
||||
return styled(topAppBarStyles)(<header className={className}>{children}</header>);
|
||||
const style = useS(styles);
|
||||
|
||||
return (<header className={s(style, { header: true }, className)}>{children}</header>);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.loader {
|
||||
height: 100vh;
|
||||
}
|
||||
@@ -7,11 +7,11 @@
|
||||
*/
|
||||
import { Suspense } from 'react';
|
||||
import { createRoot, Root } from 'react-dom/client';
|
||||
import styled from 'reshadow';
|
||||
|
||||
import { Body } from '@cloudbeaver/core-app';
|
||||
import { DisplayError, ErrorBoundary, Loader } from '@cloudbeaver/core-blocks';
|
||||
import { DisplayError, ErrorBoundary, Loader, s } from '@cloudbeaver/core-blocks';
|
||||
import { AppContext, IServiceInjector } from '@cloudbeaver/core-di';
|
||||
import styles from './renderLayout.m.css';
|
||||
|
||||
interface IRender {
|
||||
initRoot(): Root;
|
||||
@@ -46,18 +46,14 @@ export function renderLayout(serviceInjector: IServiceInjector): IRender {
|
||||
},
|
||||
renderApp() {
|
||||
this.initRoot().render(
|
||||
styled`
|
||||
Loader {
|
||||
height: 100vh;
|
||||
}
|
||||
`(
|
||||
(
|
||||
<AppContext app={serviceInjector}>
|
||||
<ErrorBoundary root>
|
||||
<Suspense fallback={<Loader />}>
|
||||
<Suspense fallback={<Loader className={s(styles, { loader: true })} />}>
|
||||
<Body />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</AppContext>,
|
||||
</AppContext>
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.container {
|
||||
outline: none;
|
||||
}
|
||||
@@ -8,9 +8,7 @@
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useContext } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { useFocus } from '@cloudbeaver/core-blocks';
|
||||
import { s, useFocus, useS } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { isObjectsEqual } from '@cloudbeaver/core-utils';
|
||||
|
||||
@@ -22,12 +20,7 @@ import type { IView } from './IView';
|
||||
import { parseHotkey } from './parseHotkey';
|
||||
import { useActiveView } from './useActiveView';
|
||||
import { useViewContext } from './useViewContext';
|
||||
|
||||
const styles = css`
|
||||
div {
|
||||
outline: none;
|
||||
}
|
||||
`;
|
||||
import styles from './CaptureView.m.css';
|
||||
|
||||
interface Props {
|
||||
view: IView<any>;
|
||||
@@ -40,6 +33,7 @@ export const CaptureView = observer<React.PropsWithChildren<Props>>(function Cap
|
||||
const actionService = useService(ActionService);
|
||||
const activeView = useActiveView(view);
|
||||
const [ref, state] = useFocus<HTMLDivElement>({ onFocus: activeView.focusView, onBlur: activeView.blurView });
|
||||
const style = useS(styles);
|
||||
|
||||
const actionItems = view.actions
|
||||
.map(action => actionService.getAction(viewContext, action))
|
||||
@@ -85,11 +79,11 @@ export const CaptureView = observer<React.PropsWithChildren<Props>>(function Cap
|
||||
},
|
||||
);
|
||||
|
||||
return styled(styles)(
|
||||
return (
|
||||
<CaptureViewContext.Provider value={viewContext}>
|
||||
<div ref={ref} className={className} tabIndex={0}>
|
||||
<div ref={ref} className={s(style, { container: true }, className)} tabIndex={0}>
|
||||
{children}
|
||||
</div>
|
||||
</CaptureViewContext.Provider>,
|
||||
</CaptureViewContext.Provider>
|
||||
);
|
||||
});
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
.wizardStepper {
|
||||
composes: theme-background-surface theme-text-on-surface theme-border-color-background from global;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
border-bottom: solid 2px;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.actions {
|
||||
composes: theme-border-color-background from global;
|
||||
border-right: solid 1px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.actions,
|
||||
.wizardText {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.wizardText {
|
||||
padding: 0 16px;
|
||||
}
|
||||
+9
-41
@@ -6,60 +6,28 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { ConfigurationWizardService } from '@cloudbeaver/core-administration';
|
||||
import { Button, useStyles, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { Button, s, useS, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
|
||||
const styles = css`
|
||||
wizard-stepper {
|
||||
composes: theme-background-surface theme-text-on-surface theme-border-color-background from global;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
align-items: center;
|
||||
border-bottom: solid 2px;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
actions {
|
||||
composes: theme-border-color-background from global;
|
||||
border-right: solid 1px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
actions,
|
||||
wizard-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
wizard-text {
|
||||
padding: 0 16px;
|
||||
}
|
||||
`;
|
||||
import styles from './WizardStepper.m.css';
|
||||
|
||||
export const WizardStepper = observer(function WizardStepper() {
|
||||
const service = useService(ConfigurationWizardService);
|
||||
const translate = useTranslate();
|
||||
const style = useS(styles);
|
||||
|
||||
return styled(useStyles(styles))(
|
||||
<wizard-stepper>
|
||||
<actions>
|
||||
return (
|
||||
<div className={s(style, { wizardStepper: true })}>
|
||||
<div className={s(style, { actions: true })}>
|
||||
<Button type="button" mod={['outlined']} disabled={service.currentStepIndex === 0} onClick={() => service.back()}>
|
||||
{translate('ui_stepper_back')}
|
||||
</Button>
|
||||
<Button type="button" mod={['unelevated']} onClick={() => service.next()}>
|
||||
{translate(service.currentStepIndex === service.steps.length - 1 ? 'ui_stepper_finish' : 'ui_stepper_next')}
|
||||
</Button>
|
||||
</actions>
|
||||
<wizard-text>{translate(service.currentStep?.configurationWizardOptions?.description || '')}</wizard-text>
|
||||
</wizard-stepper>,
|
||||
</div>
|
||||
<div className={s(style, { wizardText: true })}>{translate(service.currentStep?.configurationWizardOptions?.description || '')}</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
.wizardTitle {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
}
|
||||
+6
-13
@@ -5,21 +5,14 @@
|
||||
* 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 { Translate } from '@cloudbeaver/core-blocks';
|
||||
|
||||
const styles = css`
|
||||
wizard-title {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
}
|
||||
`;
|
||||
import { Translate, s, useS } from '@cloudbeaver/core-blocks';
|
||||
import styles from './ConfigurationWizardTitle.m.css';
|
||||
|
||||
export function ConfigurationWizardTitle() {
|
||||
return styled(styles)(
|
||||
<wizard-title as="div">
|
||||
const style = useS(styles);
|
||||
return (
|
||||
<div className={s(style, { wizardTitle : true })}>
|
||||
<Translate token="administration_configuration_wizard_title" />
|
||||
</wizard-title>,
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
.group {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.group,
|
||||
.container,
|
||||
.tableContainer {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tableContainer {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.grantedConnectionsTableHeader {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.table {
|
||||
composes: theme-background-surface theme-text-on-surface from global;
|
||||
width: 100%;
|
||||
}
|
||||
+13
-38
@@ -8,19 +8,19 @@
|
||||
import { observable } from 'mobx';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useCallback, useState } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import {
|
||||
Button,
|
||||
getComputed,
|
||||
getSelectedItems,
|
||||
Group,
|
||||
s,
|
||||
Table,
|
||||
TableBody,
|
||||
TableColumnValue,
|
||||
TableItem,
|
||||
useObjectRef,
|
||||
useStyles,
|
||||
useS,
|
||||
useTranslate,
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { Connection, DBDriverResource } from '@cloudbeaver/core-connections';
|
||||
@@ -30,32 +30,7 @@ import { getFilteredConnections } from './getFilteredConnections';
|
||||
import { GrantedConnectionsTableHeader, IFilterState } from './GrantedConnectionsTableHeader/GrantedConnectionsTableHeader';
|
||||
import { GrantedConnectionsTableInnerHeader } from './GrantedConnectionsTableHeader/GrantedConnectionsTableInnerHeader';
|
||||
import { GrantedConnectionsTableItem } from './GrantedConnectionsTableItem';
|
||||
|
||||
const styles = css`
|
||||
Group {
|
||||
position: relative;
|
||||
}
|
||||
Group,
|
||||
container,
|
||||
table-container {
|
||||
height: 100%;
|
||||
}
|
||||
container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
table-container {
|
||||
overflow: auto;
|
||||
}
|
||||
GrantedConnectionsTableHeader {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
Table {
|
||||
composes: theme-background-surface theme-text-on-surface from global;
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
import styles from './ConnectionList.m.css';
|
||||
|
||||
interface Props {
|
||||
connectionList: Connection[];
|
||||
@@ -66,7 +41,7 @@ interface Props {
|
||||
|
||||
export const ConnectionList = observer<Props>(function ConnectionList({ connectionList, grantedSubjects, disabled, onGrant }) {
|
||||
const props = useObjectRef({ onGrant });
|
||||
const style = useStyles(styles);
|
||||
const style = useS(styles);
|
||||
const translate = useTranslate();
|
||||
|
||||
const driversResource = useService(DBDriverResource);
|
||||
@@ -84,17 +59,17 @@ export const ConnectionList = observer<Props>(function ConnectionList({ connecti
|
||||
const connections = getFilteredConnections(connectionList, filterState.filterValue);
|
||||
const keys = connections.map(connection => connection.id);
|
||||
|
||||
return styled(style)(
|
||||
<Group box medium overflow>
|
||||
<container>
|
||||
return (
|
||||
<Group className={s(style, { group: true })} box medium overflow>
|
||||
<div className={s(style, { container: true })}>
|
||||
<GrantedConnectionsTableHeader filterState={filterState} disabled={disabled}>
|
||||
<Button disabled={disabled || !selected} mod={['unelevated']} onClick={grant}>
|
||||
{translate('ui_add')}
|
||||
</Button>
|
||||
</GrantedConnectionsTableHeader>
|
||||
<table-container>
|
||||
<Table keys={keys} selectedItems={selectedSubjects} isItemSelectable={item => !grantedSubjects.includes(item)} size="big">
|
||||
<GrantedConnectionsTableInnerHeader disabled={disabled} />
|
||||
<div className={s(style, { tableContainer: true })}>
|
||||
<Table className={s(style, { table: true })} keys={keys} selectedItems={selectedSubjects} isItemSelectable={item => !grantedSubjects.includes(item)} size="big">
|
||||
<GrantedConnectionsTableInnerHeader className={s(style, { grantedConnectionsTableHeader: true })} disabled={disabled} />
|
||||
<TableBody>
|
||||
{!connections.length && filterState.filterValue && (
|
||||
<TableItem item="tableInfo" selectDisabled>
|
||||
@@ -117,8 +92,8 @@ export const ConnectionList = observer<Props>(function ConnectionList({ connecti
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</table-container>
|
||||
</container>
|
||||
</Group>,
|
||||
</div>
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
.group {
|
||||
list-style-position: inside;
|
||||
height: 100%;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.reactMarkdown > * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -7,44 +7,32 @@
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Container, Group, GroupItem, GroupTitle, useResource, useStyles, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { Container, Group, GroupItem, GroupTitle, s, useResource, useS, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { VersionResource } from '@cloudbeaver/core-version';
|
||||
import styles from './VersionInfo.m.css';
|
||||
|
||||
interface Props {
|
||||
item: string;
|
||||
}
|
||||
|
||||
const style = css`
|
||||
Group {
|
||||
list-style-position: inside;
|
||||
height: 100%;
|
||||
max-height: 300px;
|
||||
}
|
||||
ReactMarkdown > * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const VersionInfo = observer<Props>(function VersionInfo({ item }) {
|
||||
const translate = useTranslate();
|
||||
const styles = useStyles(style);
|
||||
const style = useS(styles);
|
||||
const versionResource = useResource(VersionInfo, VersionResource, item);
|
||||
|
||||
const version = versionResource.tryGetData;
|
||||
|
||||
return styled(styles)(
|
||||
return (
|
||||
<Container wrap gap overflow large>
|
||||
<Group gap overflow>
|
||||
<Group className={s(style, { group: true })} gap overflow>
|
||||
<GroupTitle>{version ? `Release notes ${version.number} - ${version.date}` : translate('version_update_version_no_info')}</GroupTitle>
|
||||
{version && (
|
||||
<GroupItem>
|
||||
<ReactMarkdown>{version.releaseNotes}</ReactMarkdown>
|
||||
<ReactMarkdown className={s(style, { reactMarkdown: true })}>{version.releaseNotes}</ReactMarkdown>
|
||||
</GroupItem>
|
||||
)}
|
||||
</Group>
|
||||
</Container>,
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
.group {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
.instruction {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.h4 {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -7,37 +7,26 @@
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useEffect, useState } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Combobox, Container, Group, GroupItem, GroupTitle, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { Combobox, Container, Group, GroupItem, GroupTitle, s, useS, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { ServerConfigResource } from '@cloudbeaver/core-root';
|
||||
import { IVersion, VersionResource } from '@cloudbeaver/core-version';
|
||||
import { VersionUpdateService } from '@cloudbeaver/core-version-update';
|
||||
|
||||
import { VersionInfo } from './VersionInfo';
|
||||
import styles from './VersionSelector.m.css';
|
||||
|
||||
interface Props {
|
||||
versions: IVersion[];
|
||||
}
|
||||
|
||||
const style = css`
|
||||
Group {
|
||||
list-style-position: inside;
|
||||
}
|
||||
Instruction {
|
||||
white-space: pre-line;
|
||||
}
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const VersionSelector = observer<Props>(function VersionSelector({ versions }) {
|
||||
const versionUpdateService = useService(VersionUpdateService);
|
||||
const versionResource = useService(VersionResource);
|
||||
const serverConfigResource = useService(ServerConfigResource);
|
||||
const translate = useTranslate();
|
||||
const style = useS(styles);
|
||||
|
||||
const [selected, setSelected] = useState('');
|
||||
|
||||
@@ -50,9 +39,9 @@ export const VersionSelector = observer<Props>(function VersionSelector({ versio
|
||||
const version = versions.find(v => v.number === selected);
|
||||
const Instruction = versionUpdateService.versionInstructionGetter?.();
|
||||
|
||||
return styled(style)(
|
||||
return (
|
||||
<Container gap>
|
||||
<Group gap large>
|
||||
<Group className={s(style, { group: true })} gap large>
|
||||
<Combobox
|
||||
items={versions}
|
||||
keySelector={value => value.number}
|
||||
@@ -65,15 +54,15 @@ export const VersionSelector = observer<Props>(function VersionSelector({ versio
|
||||
</Combobox>
|
||||
{version && Instruction && (
|
||||
<GroupItem>
|
||||
<Instruction version={version} containerId={serverConfigResource.data?.containerId} />
|
||||
<Instruction className={s(style, { instruction: true })} version={version} containerId={serverConfigResource.data?.containerId} />
|
||||
</GroupItem>
|
||||
)}
|
||||
<GroupTitle>{translate('plugin_version_update_administration_recommendations_label')}</GroupTitle>
|
||||
<GroupItem>
|
||||
<h4>{translate('plugin_version_update_administration_recommendations')}</h4>
|
||||
<h4 className={s(style, { h4: true })}>{translate('plugin_version_update_administration_recommendations')}</h4>
|
||||
</GroupItem>
|
||||
</Group>
|
||||
{version && <VersionInfo item={version.number} />}
|
||||
</Container>,
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.coloredContainer {
|
||||
composes: theme-typography--body2 from global;
|
||||
list-style-position: inside;
|
||||
}
|
||||
@@ -6,11 +6,10 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
import { gte } from 'semver';
|
||||
|
||||
import type { AdministrationItemContentComponent } from '@cloudbeaver/core-administration';
|
||||
import { ColoredContainer, useResource, useStyles } from '@cloudbeaver/core-blocks';
|
||||
import { ColoredContainer, s, useResource, useS, useStyles } from '@cloudbeaver/core-blocks';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { CachedMapAllKey } from '@cloudbeaver/core-resource';
|
||||
import { VersionResource, VersionService } from '@cloudbeaver/core-version';
|
||||
@@ -18,16 +17,10 @@ import { VersionUpdateService } from '@cloudbeaver/core-version-update';
|
||||
|
||||
import { VersionChecker } from './VersionChecker';
|
||||
import { VersionSelector } from './VersionSelector';
|
||||
|
||||
const styles = css`
|
||||
ColoredContainer {
|
||||
composes: theme-typography--body2 from global;
|
||||
list-style-position: inside;
|
||||
}
|
||||
`;
|
||||
import styles from './VersionUpdate.m.css';
|
||||
|
||||
export const VersionUpdate: AdministrationItemContentComponent = observer(function VersionUpdate() {
|
||||
const style = useStyles(styles);
|
||||
const style = useS(styles);
|
||||
const versionService = useService(VersionService);
|
||||
const versionUpdateService = useService(VersionUpdateService);
|
||||
const versionResource = useResource(VersionUpdate, VersionResource, CachedMapAllKey, {
|
||||
@@ -37,8 +30,8 @@ export const VersionUpdate: AdministrationItemContentComponent = observer(functi
|
||||
const GeneralInstructions = versionUpdateService.generalInstructionsGetter?.();
|
||||
const versions = versionResource.resource.values.filter(v => gte(v.number, versionService.current));
|
||||
|
||||
return styled(style)(
|
||||
<ColoredContainer wrap gap overflow parent>
|
||||
return (
|
||||
<ColoredContainer className={s(style, { coloredContainer: true })} wrap gap overflow parent>
|
||||
<VersionChecker />
|
||||
{versions.length > 0 && (
|
||||
<>
|
||||
@@ -46,6 +39,6 @@ export const VersionUpdate: AdministrationItemContentComponent = observer(functi
|
||||
<VersionSelector versions={versions} />
|
||||
</>
|
||||
)}
|
||||
</ColoredContainer>,
|
||||
</ColoredContainer>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user