Skip to content

Commit

Permalink
Merge branch 'devel' into CB-4382-anonymous-access-restricted-error
Browse files Browse the repository at this point in the history
  • Loading branch information
s.teleshev committed Jan 25, 2024
2 parents a744986 + 3e93752 commit 05ee030
Show file tree
Hide file tree
Showing 39 changed files with 1,000 additions and 36 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io
## Changelog


### 23.3.2. 2024-01-22
### 23.3.3. 2024-01-22
- Added password policy for the local authorization. Password parameters can be set in the configuration file;
- The 'Keep alive' option has been added to the connection settings to keep the connection active even in case of inactivity;
- Added ability to display full text for a string data type in value panel;
Expand Down
2 changes: 1 addition & 1 deletion deploy/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ubuntu:23.04
FROM ubuntu:23.10

MAINTAINER DBeaver Corp, [email protected]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ type DatabaseObjectInfo {
type NavigatorNodeInfo {
# Node ID - generally a full path to the node from root of tree
id: ID!
# # Node URI - a unique path to a node including all parent nodes
# uri: ID! @since(version: "23.3.1")
# Node URI - a unique path to a node including all parent nodes
# uri: ID! @since(version: "23.3.1")
# Node human readable name
name: String
#Node full name
Expand Down
15 changes: 13 additions & 2 deletions webapp/packages/core-blocks/src/FormControls/Textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react-lite';
import { useCallback, useContext } from 'react';
import { useCallback, useContext, useLayoutEffect, useRef } from 'react';

import { filterLayoutFakeProps, getLayoutProps } from '../Containers/filterLayoutFakeProps';
import type { ILayoutSizeProps } from '../Containers/ILayoutSizeProps';
Expand All @@ -23,6 +23,7 @@ type BaseProps = Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChan
description?: string;
labelTooltip?: string;
embedded?: boolean;
cursorInitiallyAtEnd?: boolean;
};

type ControlledProps = BaseProps & {
Expand Down Expand Up @@ -54,9 +55,11 @@ export const Textarea: TextareaType = observer(function Textarea({
description,
labelTooltip,
embedded,
cursorInitiallyAtEnd,
onChange = () => {},
...rest
}: ControlledProps | ObjectProps<any, any>) {
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
const layoutProps = getLayoutProps(rest);
rest = filterLayoutFakeProps(rest);
const styles = useS(textareaStyle);
Expand All @@ -79,13 +82,21 @@ export const Textarea: TextareaType = observer(function Textarea({

const value = state ? state[name] : controlledValue;

useLayoutEffect(() => {
if (cursorInitiallyAtEnd && typeof value === 'string') {
const position = value.length;
textareaRef.current?.setSelectionRange(position, position);
}
}, [cursorInitiallyAtEnd]);

return (
<Field {...layoutProps} className={s(styles, { field: true, embedded }, className)}>
<FieldLabel className={s(styles, { fieldLabel: true })} title={labelTooltip || rest.title} required={required}>
<FieldLabel className={s(styles, { fieldLabel: true })} title={labelTooltip || rest.title} required={required}>
{children}
</FieldLabel>
<textarea
{...rest}
ref={textareaRef}
required={required}
className={s(styles, { textarea: true })}
value={value ?? ''}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
.treeNodeNested {
box-sizing: border-box;
padding-left: 8px;
display: none;

&.root {
padding: 0;
display: block;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createDataContext } from '@cloudbeaver/core-data-context';

export const DATA_CONTEXT_NAV_NODE_ID = createDataContext<string>('nav-node-id');
1 change: 1 addition & 0 deletions webapp/packages/core-navigation-tree/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './NodesManager/extensions/IObjectNavNodeProvider';
export * from './NodesManager/DBObjectResource';
export * from './NodesManager/DATA_CONTEXT_ACTIVE_NODE';
export * from './NodesManager/DATA_CONTEXT_NAV_NODE';
export * from './NodesManager/DATA_CONTEXT_NAV_NODE_ID';
export * from './NodesManager/DATA_CONTEXT_NAV_NODES';
export * from './NodesManager/NavNodeInfoResource';
export * from './NodesManager/NavNodeManagerService';
Expand Down
10 changes: 9 additions & 1 deletion webapp/packages/plugin-codemirror6/src/IReactCodemirrorProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,25 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { Compartment, Extension } from '@codemirror/state';
import type { Compartment, Extension, SelectionRange } from '@codemirror/state';
import type { ViewUpdate } from '@codemirror/view';

/** Currently we support only main selection range */
interface ISelection {
anchor: number;
head?: number;
}

export interface IReactCodeMirrorProps extends React.PropsWithChildren {
/** in case of using editor in editing mode its better for performance to use getValue instead */
value?: string;
cursor?: ISelection;
incomingValue?: string;
getValue?: () => string;
extensions?: Map<Compartment, Extension>;
readonly?: boolean;
autoFocus?: boolean;
onChange?: (value: string, update: ViewUpdate) => void;
onCursorChange?: (selection: SelectionRange, update: ViewUpdate) => void;
onUpdate?: (update: ViewUpdate) => void;
}
44 changes: 35 additions & 9 deletions webapp/packages/plugin-codemirror6/src/ReactCodemirror.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
*/
import { MergeView } from '@codemirror/merge';
import { Annotation, Compartment, Extension, StateEffect } from '@codemirror/state';
import { Annotation, Compartment, Extension, StateEffect, TransactionSpec } from '@codemirror/state';
import { EditorView, ViewUpdate } from '@codemirror/view';
import { observer } from 'mobx-react-lite';
import { forwardRef, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from 'react';
Expand All @@ -22,7 +22,19 @@ const External = Annotation.define<boolean>();

export const ReactCodemirror = observer<IReactCodeMirrorProps, IEditorRef>(
forwardRef(function ReactCodemirror(
{ children, getValue, value, incomingValue, extensions = new Map<Compartment, Extension>(), readonly, autoFocus, onChange, onUpdate },
{
children,
getValue,
value,
cursor,
incomingValue,
extensions = new Map<Compartment, Extension>(),
readonly,
autoFocus,
onChange,
onCursorChange,
onUpdate,
},
ref,
) {
value = value ?? getValue?.();
Expand All @@ -32,7 +44,7 @@ export const ReactCodemirror = observer<IReactCodeMirrorProps, IEditorRef>(
const [container, setContainer] = useState<HTMLDivElement | null>(null);
const [view, setView] = useState<EditorView | null>(null);
const [incomingView, setIncomingView] = useState<EditorView | null>(null);
const callbackRef = useObjectRef({ onChange, onUpdate });
const callbackRef = useObjectRef({ onChange, onCursorChange, onUpdate });
const [selection, setSelection] = useState(view?.state.selection.main ?? null);

useLayoutEffect(() => {
Expand All @@ -50,6 +62,11 @@ export const ReactCodemirror = observer<IReactCodeMirrorProps, IEditorRef>(
callbackRef.onChange?.(value, update);
}

if (update.selectionSet && !remote) {
const selection = update.state.selection.main;
callbackRef.onCursorChange?.(selection, update);
}

callbackRef.onUpdate?.(update);
});

Expand Down Expand Up @@ -136,13 +153,22 @@ export const ReactCodemirror = observer<IReactCodeMirrorProps, IEditorRef>(
});

useLayoutEffect(() => {
if (value !== undefined && view && value !== view.state.doc.toString()) {
view.dispatch({
changes: { from: 0, to: view.state.doc.length, insert: value },
annotations: [External.of(true)],
});
if (view) {
const transaction: TransactionSpec = { annotations: [External.of(true)] };

if (value !== undefined && value !== view.state.doc.toString()) {
transaction.changes = { from: 0, to: view.state.doc.length, insert: value };
}

if (cursor && (view.state.selection.main.anchor !== cursor.anchor || view.state.selection.main.head !== cursor.head)) {
transaction.selection = cursor;
}

if (transaction.changes || transaction.selection) {
view.dispatch(transaction);
}
}
}, [value, view]);
});

useLayoutEffect(() => {
if (incomingValue !== undefined && incomingView && incomingValue !== incomingView.state.doc.toString()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/

export type TreeDataTransformer<T> = (nodeId: string, data: T) => T;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { TreeDataTransformer } from './TreeDataTransformer';

export function applyTransforms<T>(id: string, data: T, transformers?: TreeDataTransformer<T>[]) {
if (!transformers) {
return data;
}

for (const transformer of transformers) {
data = transformer(id, data);
}

return data;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { INode } from '../INode';
import type { INodeState } from '../INodeState';
import type { TreeDataTransformer } from './TreeDataTransformer';

export function rootNodeStateTransformer(root: string): TreeDataTransformer<INodeState> {
return function rootNodeStateTransformer(nodeId, data) {
if (nodeId === root) {
return {
...data,
expanded: true,
};
}

return data;
};
}

export function rootNodeTransformer(root: string): TreeDataTransformer<INode> {
return function rootNodeTransformer(nodeId, data) {
if (nodeId === root) {
return {
...data,
leaf: false,
};
}

return data;
};
}
14 changes: 14 additions & 0 deletions webapp/packages/plugin-navigation-tree/src/TreeNew/INode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/

export interface INode {
name: string;
tooltip?: string;
icon?: string;
leaf?: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/

export interface INodeComponentBaseProps {
nodeId: string;
offsetHeight: number;
}

export interface INodeComponentProps extends INodeComponentBaseProps {
childrenRenderer: React.FC<INodeComponentBaseProps>;
}

export type NodeComponent = React.FC<INodeComponentProps>;

export type INodeRenderer = (nodeId: string) => NodeComponent | null;
12 changes: 12 additions & 0 deletions webapp/packages/plugin-navigation-tree/src/TreeNew/INodeState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/

export interface INodeState {
selected: boolean;
expanded: boolean;
}
51 changes: 51 additions & 0 deletions webapp/packages/plugin-navigation-tree/src/TreeNew/Node.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react-lite';
import { useContext } from 'react';

import { TreeNode } from '@cloudbeaver/core-blocks';

import { TreeContext } from './contexts/TreeContext';
import { TreeDataContext } from './contexts/TreeDataContext';
import type { NodeComponent } from './INodeRenderer';
import { NodeControl } from './NodeControl';
import { useNodeDnD } from './useNodeDnD';

export const Node: NodeComponent = observer(function Node({ nodeId, offsetHeight, childrenRenderer }) {
const tree = useContext(TreeContext)!;
const data = useContext(TreeDataContext)!;

const { expanded, selected } = data.getState(nodeId);

const dndData = useNodeDnD(nodeId, () => {
if (!selected) {
tree.selectNode(nodeId, true);
}
});

function handleOpen() {
return tree.openNode(nodeId);
}

function handleToggleExpand() {
return tree.expandNode(nodeId, !expanded);
}

function handleSelect() {
tree.selectNode(nodeId, !selected);
}

const NavigationTreeChildrenNew = childrenRenderer;

return (
<TreeNode selected={selected} expanded={expanded} onExpand={handleToggleExpand} onOpen={handleOpen} onSelect={handleSelect}>
<NodeControl ref={dndData.setTargetRef} nodeId={nodeId} />
{expanded && <NavigationTreeChildrenNew nodeId={nodeId} offsetHeight={offsetHeight + tree.getNodeHeight(nodeId)} />}
</TreeNode>
);
});
Loading

0 comments on commit 05ee030

Please sign in to comment.