mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-28 07:58:31 +00:00
* supported copy button in query editor * fix sonar issue
This commit is contained in:
parent
890820ed92
commit
af47b856e7
@ -326,7 +326,7 @@ const DataModelDetails = ({
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
styleActiveLine: false,
|
||||
readOnly: 'nocursor',
|
||||
readOnly: true,
|
||||
}}
|
||||
value={dataModelData?.sql}
|
||||
/>
|
||||
|
||||
@ -99,9 +99,7 @@ const ParameterForm: React.FC<ParameterFormProps> = ({ definition, table }) => {
|
||||
<SchemaEditor
|
||||
className="custom-query-editor query-editor-h-200"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
showCopyButton={false}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
||||
@ -161,9 +161,7 @@ const CustomMetricForm = ({
|
||||
<SchemaEditor
|
||||
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
showCopyButton={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
@ -526,9 +526,6 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
|
||||
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
||||
data-testid="profiler-setting-sql-editor"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
value={state?.sqlQuery ?? ''}
|
||||
onChange={handleCodeMirrorChange}
|
||||
/>
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2024 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { CSMode } from '../../../enums/codemirror.enum';
|
||||
|
||||
type Mode = {
|
||||
name: CSMode;
|
||||
json?: boolean;
|
||||
};
|
||||
|
||||
export interface SchemaEditorProps {
|
||||
value?: string;
|
||||
className?: string;
|
||||
mode?: Mode;
|
||||
readOnly?: boolean;
|
||||
options?: {
|
||||
[key: string]: string | boolean | Array<string>;
|
||||
};
|
||||
editorClass?: string;
|
||||
showCopyButton?: boolean;
|
||||
onChange?: (value: string) => void;
|
||||
}
|
||||
@ -11,28 +11,88 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import SchemaEditor from './SchemaEditor';
|
||||
|
||||
const mockOnChange = jest.fn();
|
||||
const mockOnCopyToClipBoard = jest.fn();
|
||||
|
||||
jest.mock('../../../constants/constants', () => ({
|
||||
JSON_TAB_SIZE: 25,
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/SchemaEditor.utils', () => ({
|
||||
getSchemaEditorValue: jest.fn().mockReturnValue('test SQL query'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../hooks/useClipBoard', () => ({
|
||||
...jest.requireActual('../../../hooks/useClipBoard'),
|
||||
useClipboard: jest
|
||||
.fn()
|
||||
.mockImplementation(() => ({ onCopyToClipBoard: mockOnCopyToClipBoard })),
|
||||
}));
|
||||
|
||||
jest.mock('react-codemirror2', () => ({
|
||||
...jest.requireActual('react-codemirror2'),
|
||||
Controlled: jest.fn().mockImplementation(({ value, onChange }) => (
|
||||
<div>
|
||||
<span>{value}</span>
|
||||
<input
|
||||
data-testid="code-mirror-editor-input"
|
||||
type="text"
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
)),
|
||||
}));
|
||||
|
||||
const mockProps = {
|
||||
value: 'test SQL query',
|
||||
showCopyButton: true,
|
||||
onChange: mockOnChange,
|
||||
};
|
||||
|
||||
describe('SchemaEditor component test', () => {
|
||||
it('Component should render properly', async () => {
|
||||
render(<SchemaEditor value="" />);
|
||||
render(<SchemaEditor {...mockProps} />);
|
||||
|
||||
expect(
|
||||
await screen.findByTestId('code-mirror-container')
|
||||
).toBeInTheDocument();
|
||||
|
||||
expect(await screen.findByTestId('query-copy-button')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Value provided via props should be visible', async () => {
|
||||
render(<SchemaEditor value="test SQL query" />);
|
||||
render(<SchemaEditor {...mockProps} />);
|
||||
|
||||
expect(
|
||||
(await screen.findByTestId('code-mirror-container')).textContent
|
||||
).toBe('test SQL query');
|
||||
});
|
||||
|
||||
it('Copy button should not be visible', async () => {
|
||||
render(<SchemaEditor {...mockProps} showCopyButton={false} />);
|
||||
|
||||
expect(screen.queryByTestId('query-copy-button')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Should call onCopyToClipBoard', async () => {
|
||||
render(<SchemaEditor {...mockProps} />);
|
||||
|
||||
fireEvent.click(screen.getByTestId('query-copy-button'));
|
||||
|
||||
expect(mockOnCopyToClipBoard).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('Should call onChange handler', async () => {
|
||||
render(<SchemaEditor {...mockProps} />);
|
||||
|
||||
fireEvent.change(screen.getByTestId('code-mirror-editor-input'), {
|
||||
target: { value: 'new SQL query' },
|
||||
});
|
||||
|
||||
expect(mockOnChange).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { Editor, EditorChange } from 'codemirror';
|
||||
import 'codemirror/addon/edit/closebrackets.js';
|
||||
import 'codemirror/addon/edit/matchbrackets.js';
|
||||
@ -24,14 +26,14 @@ import 'codemirror/mode/sql/sql';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Controlled as CodeMirror } from 'react-codemirror2';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ReactComponent as CopyIcon } from '../../../assets/svg/icon-copy.svg';
|
||||
import { JSON_TAB_SIZE } from '../../../constants/constants';
|
||||
import { CSMode } from '../../../enums/codemirror.enum';
|
||||
import { useClipboard } from '../../../hooks/useClipBoard';
|
||||
import { getSchemaEditorValue } from '../../../utils/SchemaEditor.utils';
|
||||
|
||||
type Mode = {
|
||||
name: CSMode;
|
||||
json?: boolean;
|
||||
};
|
||||
import './schema-editor.less';
|
||||
import { SchemaEditorProps } from './SchemaEditor.interface';
|
||||
|
||||
const SchemaEditor = ({
|
||||
value = '',
|
||||
@ -42,18 +44,10 @@ const SchemaEditor = ({
|
||||
},
|
||||
options,
|
||||
editorClass,
|
||||
showCopyButton = true,
|
||||
onChange,
|
||||
}: {
|
||||
value?: string;
|
||||
className?: string;
|
||||
mode?: Mode;
|
||||
readOnly?: boolean;
|
||||
options?: {
|
||||
[key: string]: string | boolean | Array<string>;
|
||||
};
|
||||
editorClass?: string;
|
||||
onChange?: (value: string) => void;
|
||||
}) => {
|
||||
}: SchemaEditorProps) => {
|
||||
const { t } = useTranslation();
|
||||
const defaultOptions = {
|
||||
tabSize: JSON_TAB_SIZE,
|
||||
indentUnit: JSON_TAB_SIZE,
|
||||
@ -72,6 +66,8 @@ const SchemaEditor = ({
|
||||
const [internalValue, setInternalValue] = useState<string>(
|
||||
getSchemaEditorValue(value)
|
||||
);
|
||||
const { onCopyToClipBoard } = useClipboard(internalValue);
|
||||
|
||||
const handleEditorInputBeforeChange = (
|
||||
_editor: Editor,
|
||||
_data: EditorChange,
|
||||
@ -94,7 +90,22 @@ const SchemaEditor = ({
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className={className} data-testid="code-mirror-container">
|
||||
<div
|
||||
className={classNames('relative', className)}
|
||||
data-testid="code-mirror-container">
|
||||
{showCopyButton && (
|
||||
<div className="query-editor-button">
|
||||
<Tooltip title={t('message.copy-to-clipboard')}>
|
||||
<Button
|
||||
className="flex-center bg-white"
|
||||
data-testid="query-copy-button"
|
||||
icon={<CopyIcon height={16} width={16} />}
|
||||
onClick={onCopyToClipBoard}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<CodeMirror
|
||||
className={editorClass}
|
||||
options={defaultOptions}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2024 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
.query-editor-button {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 14px;
|
||||
right: 14px;
|
||||
}
|
||||
@ -245,6 +245,7 @@ const QueryCard: FC<QueryCardProp> = ({
|
||||
styleActiveLine: isEditMode,
|
||||
readOnly: isEditMode ? false : 'nocursor',
|
||||
}}
|
||||
showCopyButton={false}
|
||||
value={query.query ?? ''}
|
||||
onChange={handleQueryChange}
|
||||
/>
|
||||
|
||||
@ -84,7 +84,7 @@ const StoredProcedureSummary = ({
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
styleActiveLine: false,
|
||||
readOnly: 'nocursor',
|
||||
readOnly: true,
|
||||
}}
|
||||
value={
|
||||
(
|
||||
|
||||
@ -100,9 +100,7 @@ export const ModalWithQueryEditor = ({
|
||||
<SchemaEditor
|
||||
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
showCopyButton={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
@ -530,9 +530,7 @@ export const PropertyValue: FC<PropertyValueProps> = ({
|
||||
<SchemaEditor
|
||||
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
showCopyButton={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
@ -227,9 +227,7 @@ const AddQueryPage = () => {
|
||||
<SchemaEditor
|
||||
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
readOnly: false,
|
||||
}}
|
||||
showCopyButton={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
|
||||
@ -565,7 +565,7 @@ const StoredProcedurePage = () => {
|
||||
mode={{ name: CSMode.SQL }}
|
||||
options={{
|
||||
styleActiveLine: false,
|
||||
readOnly: 'nocursor',
|
||||
readOnly: true,
|
||||
}}
|
||||
value={code}
|
||||
/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user