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:
Sachin Chaurasiya 2024-11-15 20:30:42 +05:30 committed by GitHub
parent cf17d8c83a
commit be642e7253
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 99 additions and 15 deletions

View File

@ -110,6 +110,7 @@ export const updateExpression = async (
language: string,
code: string
) => {
await page.getByRole('tab', { name: 'Expression', exact: true }).click();
await page.click(`[data-testid="edit-expression-button"]`);
// Select the language
@ -128,8 +129,10 @@ export const updateExpression = async (
await patchPromise;
await expect(
page.getByLabel('Overview').locator('.CodeMirror-scroll')
page.getByLabel('Expression').locator('.CodeMirror-scroll')
).toContainText(code);
await page.getByRole('tab', { name: 'Overview', exact: true }).click();
};
export const updateRelatedMetric = async (

View File

@ -21,7 +21,9 @@ import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/foldgutter.js';
import 'codemirror/addon/selection/active-line';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/clike/clike';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/python/python';
import 'codemirror/mode/sql/sql';
import { isUndefined } from 'lodash';
import React, { useEffect, useState } from 'react';

View File

@ -292,8 +292,9 @@ const MetricDetails: React.FC<MetricDetailsProps> = ({
firstPanel={{
className: 'entity-resizable-panel-container',
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
isDescriptionExpanded
description={metricDetails.description}
entityFqn={decodedMetricFqn}
entityName={entityName}
@ -307,10 +308,6 @@ const MetricDetails: React.FC<MetricDetailsProps> = ({
onDescriptionUpdate={onDescriptionUpdate}
onThreadLinkSelect={onThreadLinkSelect}
/>
<MetricExpression
metricDetails={metricDetails}
onMetricUpdate={onMetricUpdate}
/>
</div>
),
...COMMON_RESIZABLE_PANEL_CONFIG.LEFT_PANEL,
@ -355,6 +352,20 @@ const MetricDetails: React.FC<MetricDetailsProps> = ({
</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: (
<TabsLabel

View File

@ -15,11 +15,11 @@ import React, { FC, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { ReactComponent as EditIcon } from '../../../assets/svg/edit-new.svg';
import { DE_ACTIVE_COLOR } from '../../../constants/constants';
import { CSMode } from '../../../enums/codemirror.enum';
import { Language } from '../../../generated/api/data/createMetric';
import { Metric } from '../../../generated/entity/data/metric';
import { FieldProp, FieldTypes } from '../../../interface/FormUtils.interface';
import { generateFormFields } from '../../../utils/formUtils';
import { getMetricExpressionLanguageName } from '../../../utils/MetricEntityUtils/MetricUtils';
import SchemaEditor from '../../Database/SchemaEditor/SchemaEditor';
interface MetricExpressionProps {
@ -37,6 +37,8 @@ const MetricExpression: FC<MetricExpressionProps> = ({
const [isUpdating, setIsUpdating] = React.useState(false);
const [isEditing, setIsEditing] = React.useState(false);
const selectedLanguage = Form.useWatch('language', form);
const handleSubmit = async (values: Metric['metricExpression']) => {
try {
setIsUpdating(true);
@ -137,8 +139,8 @@ const MetricExpression: FC<MetricExpressionProps> = ({
name="code"
trigger="onChange">
<SchemaEditor
className="custom-query-editor query-editor-h-200 custom-code-mirror-theme"
mode={{ name: CSMode.SQL }}
className="custom-query-editor full-screen-editor-height custom-code-mirror-theme"
mode={{ name: getMetricExpressionLanguageName(selectedLanguage) }}
showCopyButton={false}
/>
</Form.Item>
@ -165,8 +167,12 @@ const MetricExpression: FC<MetricExpressionProps> = ({
</Form>
) : (
<SchemaEditor
editorClass="custom-code-mirror-theme"
mode={{ name: CSMode.SQL }}
editorClass="custom-code-mirror-theme full-screen-editor-height"
mode={{
name: getMetricExpressionLanguageName(
metricDetails?.metricExpression?.language
),
}}
options={{
styleActiveLine: false,
readOnly: true,

View File

@ -272,6 +272,12 @@
.code-copy-button[data-copied='true'] {
opacity: 0;
}
// for latex expressions
.katex {
mtext {
font-size: 14px;
}
}
}
}

View File

@ -14,4 +14,6 @@
export enum CSMode {
JAVASCRIPT = 'javascript',
SQL = 'sql',
PYTHON = 'python',
CLIKE = 'clike',
}

View File

@ -209,6 +209,7 @@ export enum EntityTabs {
TERMS = 'terms',
GLOSSARY_TERMS = 'glossary_terms',
ASSETS = 'assets',
EXPRESSION = 'expression',
}
export enum EntityAction {

View File

@ -34,7 +34,8 @@
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;
}

View File

@ -10,8 +10,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { UnitOfMeasurement } from '../../generated/entity/data/metric';
import { getSortedOptions } from './MetricUtils';
import { CSMode } from '../../enums/codemirror.enum';
import {
Language,
UnitOfMeasurement,
} from '../../generated/entity/data/metric';
import {
getMetricExpressionLanguageName,
getSortedOptions,
} from './MetricUtils';
describe('getSortedOptions', () => {
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');
});
});

View File

@ -10,7 +10,12 @@
* See the License for the specific language governing permissions and
* 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 = [
MetricGranularity.Second,
@ -46,3 +51,15 @@ export const getSortedOptions = (
: 0;
});
};
export const getMetricExpressionLanguageName = (language?: Language) => {
if (!language) {
return CSMode.SQL;
}
if (language === Language.Java) {
return CSMode.CLIKE;
}
return language.toLowerCase() as CSMode;
};