mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-26 01:46:26 +00:00
GEN-1694: metric entity improvement (#18659)
* GEN-1694: metric entity improvement * add clike and python language mode in schemaeditor * add getMetricExpressionLanguageName util to extract the language from metric expression
This commit is contained in:
parent
cf17d8c83a
commit
be642e7253
@ -110,6 +110,7 @@ export const updateExpression = async (
|
|||||||
language: string,
|
language: string,
|
||||||
code: string
|
code: string
|
||||||
) => {
|
) => {
|
||||||
|
await page.getByRole('tab', { name: 'Expression', exact: true }).click();
|
||||||
await page.click(`[data-testid="edit-expression-button"]`);
|
await page.click(`[data-testid="edit-expression-button"]`);
|
||||||
|
|
||||||
// Select the language
|
// Select the language
|
||||||
@ -128,8 +129,10 @@ export const updateExpression = async (
|
|||||||
await patchPromise;
|
await patchPromise;
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.getByLabel('Overview').locator('.CodeMirror-scroll')
|
page.getByLabel('Expression').locator('.CodeMirror-scroll')
|
||||||
).toContainText(code);
|
).toContainText(code);
|
||||||
|
|
||||||
|
await page.getByRole('tab', { name: 'Overview', exact: true }).click();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateRelatedMetric = async (
|
export const updateRelatedMetric = async (
|
||||||
|
@ -21,7 +21,9 @@ import 'codemirror/addon/fold/foldgutter.css';
|
|||||||
import 'codemirror/addon/fold/foldgutter.js';
|
import 'codemirror/addon/fold/foldgutter.js';
|
||||||
import 'codemirror/addon/selection/active-line';
|
import 'codemirror/addon/selection/active-line';
|
||||||
import 'codemirror/lib/codemirror.css';
|
import 'codemirror/lib/codemirror.css';
|
||||||
|
import 'codemirror/mode/clike/clike';
|
||||||
import 'codemirror/mode/javascript/javascript';
|
import 'codemirror/mode/javascript/javascript';
|
||||||
|
import 'codemirror/mode/python/python';
|
||||||
import 'codemirror/mode/sql/sql';
|
import 'codemirror/mode/sql/sql';
|
||||||
import { isUndefined } from 'lodash';
|
import { isUndefined } from 'lodash';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
@ -292,8 +292,9 @@ const MetricDetails: React.FC<MetricDetailsProps> = ({
|
|||||||
firstPanel={{
|
firstPanel={{
|
||||||
className: 'entity-resizable-panel-container',
|
className: 'entity-resizable-panel-container',
|
||||||
children: (
|
children: (
|
||||||
<div className="d-flex flex-col gap-4 p-t-sm m-x-lg">
|
<div className="d-flex flex-col gap-4 p-y-sm m-x-lg">
|
||||||
<DescriptionV1
|
<DescriptionV1
|
||||||
|
isDescriptionExpanded
|
||||||
description={metricDetails.description}
|
description={metricDetails.description}
|
||||||
entityFqn={decodedMetricFqn}
|
entityFqn={decodedMetricFqn}
|
||||||
entityName={entityName}
|
entityName={entityName}
|
||||||
@ -307,10 +308,6 @@ const MetricDetails: React.FC<MetricDetailsProps> = ({
|
|||||||
onDescriptionUpdate={onDescriptionUpdate}
|
onDescriptionUpdate={onDescriptionUpdate}
|
||||||
onThreadLinkSelect={onThreadLinkSelect}
|
onThreadLinkSelect={onThreadLinkSelect}
|
||||||
/>
|
/>
|
||||||
<MetricExpression
|
|
||||||
metricDetails={metricDetails}
|
|
||||||
onMetricUpdate={onMetricUpdate}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
...COMMON_RESIZABLE_PANEL_CONFIG.LEFT_PANEL,
|
...COMMON_RESIZABLE_PANEL_CONFIG.LEFT_PANEL,
|
||||||
@ -355,6 +352,20 @@ const MetricDetails: React.FC<MetricDetailsProps> = ({
|
|||||||
</Row>
|
</Row>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<TabsLabel id={EntityTabs.EXPRESSION} name={t('label.expression')} />
|
||||||
|
),
|
||||||
|
key: EntityTabs.EXPRESSION,
|
||||||
|
children: (
|
||||||
|
<div className="p-t-sm m-x-lg">
|
||||||
|
<MetricExpression
|
||||||
|
metricDetails={metricDetails}
|
||||||
|
onMetricUpdate={onMetricUpdate}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: (
|
label: (
|
||||||
<TabsLabel
|
<TabsLabel
|
||||||
|
@ -15,11 +15,11 @@ import React, { FC, useMemo } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
|
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
|
||||||
import { DE_ACTIVE_COLOR } from '../../../constants/constants';
|
import { DE_ACTIVE_COLOR } from '../../../constants/constants';
|
||||||
import { CSMode } from '../../../enums/codemirror.enum';
|
|
||||||
import { Language } from '../../../generated/api/data/createMetric';
|
import { Language } from '../../../generated/api/data/createMetric';
|
||||||
import { Metric } from '../../../generated/entity/data/metric';
|
import { Metric } from '../../../generated/entity/data/metric';
|
||||||
import { FieldProp, FieldTypes } from '../../../interface/FormUtils.interface';
|
import { FieldProp, FieldTypes } from '../../../interface/FormUtils.interface';
|
||||||
import { generateFormFields } from '../../../utils/formUtils';
|
import { generateFormFields } from '../../../utils/formUtils';
|
||||||
|
import { getMetricExpressionLanguageName } from '../../../utils/MetricEntityUtils/MetricUtils';
|
||||||
import SchemaEditor from '../../Database/SchemaEditor/SchemaEditor';
|
import SchemaEditor from '../../Database/SchemaEditor/SchemaEditor';
|
||||||
|
|
||||||
interface MetricExpressionProps {
|
interface MetricExpressionProps {
|
||||||
@ -37,6 +37,8 @@ const MetricExpression: FC<MetricExpressionProps> = ({
|
|||||||
const [isUpdating, setIsUpdating] = React.useState(false);
|
const [isUpdating, setIsUpdating] = React.useState(false);
|
||||||
const [isEditing, setIsEditing] = React.useState(false);
|
const [isEditing, setIsEditing] = React.useState(false);
|
||||||
|
|
||||||
|
const selectedLanguage = Form.useWatch('language', form);
|
||||||
|
|
||||||
const handleSubmit = async (values: Metric['metricExpression']) => {
|
const handleSubmit = async (values: Metric['metricExpression']) => {
|
||||||
try {
|
try {
|
||||||
setIsUpdating(true);
|
setIsUpdating(true);
|
||||||
@ -137,8 +139,8 @@ const MetricExpression: FC<MetricExpressionProps> = ({
|
|||||||
name="code"
|
name="code"
|
||||||
trigger="onChange">
|
trigger="onChange">
|
||||||
<SchemaEditor
|
<SchemaEditor
|
||||||
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
|
className="custom-query-editor full-screen-editor-height custom-code-mirror-theme"
|
||||||
mode={{ name: CSMode.SQL }}
|
mode={{ name: getMetricExpressionLanguageName(selectedLanguage) }}
|
||||||
showCopyButton={false}
|
showCopyButton={false}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@ -165,8 +167,12 @@ const MetricExpression: FC<MetricExpressionProps> = ({
|
|||||||
</Form>
|
</Form>
|
||||||
) : (
|
) : (
|
||||||
<SchemaEditor
|
<SchemaEditor
|
||||||
editorClass="custom-code-mirror-theme"
|
editorClass="custom-code-mirror-theme full-screen-editor-height"
|
||||||
mode={{ name: CSMode.SQL }}
|
mode={{
|
||||||
|
name: getMetricExpressionLanguageName(
|
||||||
|
metricDetails?.metricExpression?.language
|
||||||
|
),
|
||||||
|
}}
|
||||||
options={{
|
options={{
|
||||||
styleActiveLine: false,
|
styleActiveLine: false,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
|
@ -272,6 +272,12 @@
|
|||||||
.code-copy-button[data-copied='true'] {
|
.code-copy-button[data-copied='true'] {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
// for latex expressions
|
||||||
|
.katex {
|
||||||
|
mtext {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,4 +14,6 @@
|
|||||||
export enum CSMode {
|
export enum CSMode {
|
||||||
JAVASCRIPT = 'javascript',
|
JAVASCRIPT = 'javascript',
|
||||||
SQL = 'sql',
|
SQL = 'sql',
|
||||||
|
PYTHON = 'python',
|
||||||
|
CLIKE = 'clike',
|
||||||
}
|
}
|
||||||
|
@ -209,6 +209,7 @@ export enum EntityTabs {
|
|||||||
TERMS = 'terms',
|
TERMS = 'terms',
|
||||||
GLOSSARY_TERMS = 'glossary_terms',
|
GLOSSARY_TERMS = 'glossary_terms',
|
||||||
ASSETS = 'assets',
|
ASSETS = 'assets',
|
||||||
|
EXPRESSION = 'expression',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EntityAction {
|
export enum EntityAction {
|
||||||
|
@ -34,7 +34,8 @@
|
|||||||
min-height: 60px;
|
min-height: 60px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.full-screen-editor-height > .CodeMirror {
|
.full-screen-editor-height > .CodeMirror,
|
||||||
|
.full-screen-editor-height > .react-codemirror2 > .CodeMirror {
|
||||||
height: calc(100vh - 250px) !important;
|
height: calc(100vh - 250px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,15 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { UnitOfMeasurement } from '../../generated/entity/data/metric';
|
import { CSMode } from '../../enums/codemirror.enum';
|
||||||
import { getSortedOptions } from './MetricUtils';
|
import {
|
||||||
|
Language,
|
||||||
|
UnitOfMeasurement,
|
||||||
|
} from '../../generated/entity/data/metric';
|
||||||
|
import {
|
||||||
|
getMetricExpressionLanguageName,
|
||||||
|
getSortedOptions,
|
||||||
|
} from './MetricUtils';
|
||||||
|
|
||||||
describe('getSortedOptions', () => {
|
describe('getSortedOptions', () => {
|
||||||
it('should sort options by granularity order if valueKey is granularity', () => {
|
it('should sort options by granularity order if valueKey is granularity', () => {
|
||||||
@ -67,3 +74,31 @@ describe('getSortedOptions', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getMetricExpressionLanguageName', () => {
|
||||||
|
it('should return SQL if language is not provided', () => {
|
||||||
|
const result = getMetricExpressionLanguageName();
|
||||||
|
|
||||||
|
expect(result).toBe(CSMode.SQL);
|
||||||
|
|
||||||
|
const result2 = getMetricExpressionLanguageName(undefined);
|
||||||
|
|
||||||
|
expect(result2).toBe(CSMode.SQL);
|
||||||
|
|
||||||
|
const result3 = getMetricExpressionLanguageName('' as Language);
|
||||||
|
|
||||||
|
expect(result3).toBe(CSMode.SQL);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return CLIKE if language is Java', () => {
|
||||||
|
const result = getMetricExpressionLanguageName(Language.Java);
|
||||||
|
|
||||||
|
expect(result).toBe(CSMode.CLIKE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return language in lowercase if language is provided', () => {
|
||||||
|
const result = getMetricExpressionLanguageName(Language.Python);
|
||||||
|
|
||||||
|
expect(result).toBe('python');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -10,7 +10,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { Metric, MetricGranularity } from '../../generated/entity/data/metric';
|
import { CSMode } from '../../enums/codemirror.enum';
|
||||||
|
import {
|
||||||
|
Language,
|
||||||
|
Metric,
|
||||||
|
MetricGranularity,
|
||||||
|
} from '../../generated/entity/data/metric';
|
||||||
|
|
||||||
const granularityOrder = [
|
const granularityOrder = [
|
||||||
MetricGranularity.Second,
|
MetricGranularity.Second,
|
||||||
@ -46,3 +51,15 @@ export const getSortedOptions = (
|
|||||||
: 0;
|
: 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getMetricExpressionLanguageName = (language?: Language) => {
|
||||||
|
if (!language) {
|
||||||
|
return CSMode.SQL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (language === Language.Java) {
|
||||||
|
return CSMode.CLIKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return language.toLowerCase() as CSMode;
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user