UI : Added Classification Field in DBT (#9727)

* Added Classification Field in DBT

* fix cypress issue

* fix cypress issue
This commit is contained in:
Ashish Gupta 2023-01-16 14:27:40 +05:30 committed by GitHub
parent 9d08cf7eb9
commit e6b85791ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 295 additions and 197 deletions

View File

@ -128,9 +128,10 @@ describe('RedShift Ingestion', () => {
cy.get('[data-testid="list-item"]').contains('Add dbt Ingestion').click();
// Add DBT ingestion
cy.contains('Add dbt Ingestion').should('be.visible');
cy.get('[data-testid="dbt-source"]')
.should('be.visible')
.select('HTTP Config Source');
cy.get('[data-testid="dbt-source"]').should('be.visible').click();
cy.get('.ant-select-item-option-content')
.contains('HTTP Config Source')
.click();
cy.get('[data-testid="catalog-url"]')
.scrollIntoView()
.should('be.visible')

View File

@ -191,6 +191,8 @@ const AddIngestion = ({
stageFileLocation: sourceConfig?.stageFileLocation ?? '/tmp/query_log',
resultLimit: sourceConfig?.resultLimit ?? 1000,
metadataToESConfig: undefined,
dbtUpdateDescriptions: sourceConfig?.dbtUpdateDescriptions ?? false,
dbtClassificationName: sourceConfig?.dbtClassificationName ?? '',
}),
[]
);
@ -459,10 +461,14 @@ const AddIngestion = ({
case PipelineType.Dbt: {
return {
...escapeBackwardSlashChar({
dbtConfigSource: omit(dbtConfigSource, 'dbtUpdateDescriptions'),
dbtConfigSource: omit(dbtConfigSource, [
'dbtUpdateDescriptions',
'dbtClassificationName',
]),
} as ConfigClass),
type: ConfigType.Dbt,
dbtUpdateDescriptions: dbtConfigSource?.dbtUpdateDescriptions,
dbtClassificationName: dbtConfigSource?.dbtClassificationName,
};
}

View File

@ -87,13 +87,15 @@ export type ScheduleIntervalProps = {
// Todo: Need to refactor below type, as per schema change #9575
export type ModifiedDbtConfig = DbtConfig &
Pick<DbtPipelineClass, 'dbtUpdateDescriptions'>;
Pick<DbtPipelineClass, 'dbtUpdateDescriptions' | 'dbtClassificationName'>;
export interface AddIngestionState {
chartFilterPattern: FilterPattern;
dashboardFilterPattern: FilterPattern;
databaseFilterPattern: FilterPattern;
databaseServiceNames: string[];
dbtClassificationName: string;
dbtUpdateDescriptions: boolean;
dbtConfigSource: ModifiedDbtConfig;
dbtConfigSourceType: DBT_SOURCES;
description: string;

View File

@ -21,6 +21,7 @@ const mockAccountIdChange = jest.fn();
const mockAuthTokenChange = jest.fn();
const mockUpdateDescriptions = jest.fn();
const mockDbtCloudProjectId = jest.fn();
const mockUpdateDBTClassification = jest.fn();
const mockProps = {
dbtCloudAccountId: '',
@ -34,10 +35,11 @@ const mockProps = {
handleCloudAuthTokenChange: mockAuthTokenChange,
handleUpdateDescriptions: mockUpdateDescriptions,
handleDbtCloudProjectId: mockDbtCloudProjectId,
handleUpdateDBTClassification: mockUpdateDBTClassification,
};
jest.mock('./SwitchField.component', () =>
jest.fn().mockImplementation(() => <div>UpdateDescriptionSwitch</div>)
jest.mock('./DBTCommonFields.component', () =>
jest.fn().mockImplementation(() => <div>DBT Common Fields</div>)
);
describe('Test DBT Cloud Config Form', () => {

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { Input } from 'antd';
import { Button, Input } from 'antd';
import React, { Fragment, FunctionComponent, useState } from 'react';
import { DbtConfig } from '../../../generated/metadataIngestion/dbtPipeline';
import {
@ -20,20 +20,20 @@ import {
requiredField,
} from '../../../utils/CommonUtils';
import { validateDbtCloudConfig } from '../../../utils/DBTConfigFormUtil';
import { Button } from '../../buttons/Button/Button';
import { Field } from '../../Field/Field';
import DBTCommonFields from './DBTCommonFields.component';
import {
DbtConfigCloud,
DBTFormCommonProps,
ErrorDbtCloud,
} from './DBTConfigForm.interface';
import SwitchField from './SwitchField.component';
interface Props extends DBTFormCommonProps, DbtConfigCloud {
handleCloudAccountIdChange: (value: string) => void;
handleCloudAuthTokenChange: (value: string) => void;
handleUpdateDescriptions: (value: boolean) => void;
handleDbtCloudProjectId: (value: string) => void;
handleUpdateDBTClassification: (value: string) => void;
}
export const DBTCloudConfig: FunctionComponent<Props> = ({
@ -49,6 +49,8 @@ export const DBTCloudConfig: FunctionComponent<Props> = ({
handleCloudAuthTokenChange,
handleUpdateDescriptions,
handleDbtCloudProjectId,
dbtClassificationName,
handleUpdateDBTClassification,
}: Props) => {
const [errors, setErrors] = useState<ErrorDbtCloud>();
@ -65,6 +67,7 @@ export const DBTCloudConfig: FunctionComponent<Props> = ({
dbtCloudAuthToken,
dbtUpdateDescriptions,
dbtCloudProjectId,
dbtClassificationName,
};
if (validate(submitData)) {
onSubmit(submitData);
@ -135,32 +138,31 @@ export const DBTCloudConfig: FunctionComponent<Props> = ({
</Field>
{getSeparator('')}
<SwitchField
<DBTCommonFields
dbtClassificationName={dbtClassificationName}
dbtUpdateDescriptions={dbtUpdateDescriptions}
descriptionId="cloud-update-description"
handleUpdateDBTClassification={handleUpdateDBTClassification}
handleUpdateDescriptions={handleUpdateDescriptions}
id="cloud-update-description"
/>
{getSeparator('')}
<Field className="tw-flex tw-justify-end">
<Field className="d-flex justify-end">
<Button
className="tw-mr-2"
className="m-r-xs"
data-testid="back-button"
size="regular"
theme="primary"
variant="text"
type="link"
onClick={onCancel}>
<span>{cancelText}</span>
{cancelText}
</Button>
<Button
className="font-medium p-x-md p-y-xxs h-auto rounded-6"
data-testid="submit-btn"
size="regular"
theme="primary"
variant="contained"
type="primary"
onClick={handleSubmit}>
<span>{okText}</span>
{okText}
</Button>
</Field>
</Fragment>

View File

@ -0,0 +1,87 @@
/*
* Copyright 2022 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 { Input, Space, Switch, Typography } from 'antd';
import React, { Fragment } from 'react';
import { useTranslation } from 'react-i18next';
import { Field } from '../../Field/Field';
interface Props {
dbtClassificationName: string | undefined;
descriptionId: string;
handleUpdateDBTClassification: (value: string) => void;
dbtUpdateDescriptions: boolean;
handleUpdateDescriptions: (value: boolean) => void;
}
function DBTCommonFields({
descriptionId,
dbtUpdateDescriptions,
dbtClassificationName,
handleUpdateDescriptions,
handleUpdateDBTClassification,
}: Props) {
const { t } = useTranslation();
return (
<Fragment>
<Field>
<Space align="end" className="m-b-xs">
<label
className="tw-form-label m-b-0 tw-mb-1"
data-testid={descriptionId}
htmlFor={descriptionId}>
{t('label.update-description')}
</label>
<Switch
checked={dbtUpdateDescriptions}
data-testid="description-switch"
id={descriptionId}
onChange={handleUpdateDescriptions}
/>
</Space>
<Typography.Text
className="d-block text-grey-muted m-b-xs text-xs"
data-testid="switch-description">
{t('message.optional-configuration-update-description-dbt')}
</Typography.Text>
</Field>
<Field>
<label
className="tw-form-label tw-mb-1"
data-testid="dbt-classification-label"
htmlFor="dbt-object-prefix">
{t('label.dbt-classification-name')}
</label>
<Typography.Text
className="d-block text-grey-muted m-b-xs text-xs"
data-testid="dbt-classification-description">
{t('message.custom-classification-name-dbt-tags')}
</Typography.Text>
<Input
className="tw-form-inputs"
data-testid="dbt-classification-name"
id="dbt-classification-name"
name="dbt-classification-name"
value={dbtClassificationName}
onChange={(e) => handleUpdateDBTClassification(e.target.value)}
/>
</Field>
</Fragment>
);
}
export default DBTCommonFields;

View File

@ -13,31 +13,43 @@
import { getByTestId, render } from '@testing-library/react';
import React from 'react';
import SwitchField from './SwitchField.component';
import DBTCommonFields from './DBTCommonFields.component';
const mockProps = {
dbtUpdateDescriptions: false,
id: 'test-id',
descriptionId: 'test-id',
dbtClassificationName: 'DBT',
handleUpdateDescriptions: jest.fn(),
handleUpdateDBTClassification: jest.fn(),
};
jest.mock('antd', () => ({
Space: jest.fn().mockImplementation(({ children }) => <div>{children}</div>),
Switch: jest
.fn()
.mockImplementation(() => <div data-testid="switch">Switch</div>),
}));
describe('SwitchField', () => {
describe('DBTCommonFields', () => {
it('Component should render properly', () => {
const { container } = render(<SwitchField {...mockProps} />);
const { container } = render(<DBTCommonFields {...mockProps} />);
const switchLabel = getByTestId(container, 'test-id');
const switchButton = getByTestId(container, 'switch');
const switchButton = getByTestId(container, 'description-switch');
const switchDescription = getByTestId(container, 'switch-description');
expect(switchLabel).toBeInTheDocument();
expect(switchButton).toBeInTheDocument();
expect(switchDescription).toBeInTheDocument();
const classificationLabel = getByTestId(
container,
'dbt-classification-label'
);
const classificationInput = getByTestId(
container,
'dbt-classification-name'
);
const classificationDescription = getByTestId(
container,
'dbt-classification-description'
);
expect(classificationLabel).toBeInTheDocument();
expect(classificationInput).toBeInTheDocument();
expect(classificationDescription).toBeInTheDocument();
});
});

View File

@ -43,6 +43,7 @@ export type DbtConfigCloud = Pick<
| 'dbtCloudAuthToken'
| 'dbtUpdateDescriptions'
| 'dbtCloudProjectId'
| 'dbtClassificationName'
>;
export type DbtConfigLocal = Pick<
@ -51,6 +52,7 @@ export type DbtConfigLocal = Pick<
| 'dbtManifestFilePath'
| 'dbtRunResultsFilePath'
| 'dbtUpdateDescriptions'
| 'dbtClassificationName'
>;
export type DbtConfigHttp = Pick<
@ -59,11 +61,15 @@ export type DbtConfigHttp = Pick<
| 'dbtManifestHttpPath'
| 'dbtRunResultsHttpPath'
| 'dbtUpdateDescriptions'
| 'dbtClassificationName'
>;
export type DbtConfigS3GCS = Pick<
ModifiedDbtConfig,
'dbtSecurityConfig' | 'dbtPrefixConfig' | 'dbtUpdateDescriptions'
| 'dbtSecurityConfig'
| 'dbtPrefixConfig'
| 'dbtUpdateDescriptions'
| 'dbtClassificationName'
>;
export type DbtS3Creds = Pick<

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { Button } from 'antd';
import { Button, Input, Select } from 'antd';
import React, {
Fragment,
FunctionComponent,
@ -55,7 +55,11 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
ingestionName: data.ingestionName,
gcsConfigType: data.gcsConfigType,
dbtConfigSourceType: data.dbtConfigSourceType,
dbtConfigSource: data.dbtConfigSource,
dbtConfigSource: {
...data.dbtConfigSource,
dbtClassificationName: data.dbtClassificationName,
dbtUpdateDescriptions: data.dbtUpdateDescriptions,
},
}),
[
data.ingestionName,
@ -81,6 +85,7 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
return (
<DBTCloudConfig
cancelText={cancelText}
dbtClassificationName={dbtConfig?.dbtClassificationName}
dbtCloudAccountId={dbtConfig?.dbtCloudAccountId}
dbtCloudAuthToken={dbtConfig?.dbtCloudAuthToken}
dbtCloudProjectId={dbtConfig?.dbtCloudProjectId}
@ -94,6 +99,9 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
handleDbtCloudProjectId={(val) => {
updateDbtConfig('dbtCloudProjectId', val);
}}
handleUpdateDBTClassification={(val) => {
updateDbtConfig('dbtClassificationName', val);
}}
handleUpdateDescriptions={(val) => {
updateDbtConfig('dbtUpdateDescriptions', val);
}}
@ -109,6 +117,7 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
<DBTLocalConfig
cancelText={cancelText}
dbtCatalogFilePath={dbtConfig?.dbtCatalogFilePath}
dbtClassificationName={dbtConfig?.dbtClassificationName}
dbtManifestFilePath={dbtConfig?.dbtManifestFilePath}
dbtRunResultsFilePath={dbtConfig?.dbtRunResultsFilePath}
dbtUpdateDescriptions={dbtConfig?.dbtUpdateDescriptions}
@ -121,6 +130,9 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
handleRunResultsFilePathChange={(val) => {
updateDbtConfig('dbtRunResultsFilePath', val);
}}
handleUpdateDBTClassification={(val) => {
updateDbtConfig('dbtClassificationName', val);
}}
handleUpdateDescriptions={(val) => {
updateDbtConfig('dbtUpdateDescriptions', val);
}}
@ -136,6 +148,7 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
<DBTHttpConfig
cancelText={cancelText}
dbtCatalogHttpPath={dbtConfig?.dbtCatalogHttpPath}
dbtClassificationName={dbtConfig?.dbtClassificationName}
dbtManifestHttpPath={dbtConfig?.dbtManifestHttpPath}
dbtRunResultsHttpPath={dbtConfig?.dbtRunResultsHttpPath}
dbtUpdateDescriptions={dbtConfig?.dbtUpdateDescriptions}
@ -148,6 +161,9 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
handleRunResultsHttpPathChange={(val) => {
updateDbtConfig('dbtRunResultsHttpPath', val);
}}
handleUpdateDBTClassification={(val) => {
updateDbtConfig('dbtClassificationName', val);
}}
handleUpdateDescriptions={(val) => {
updateDbtConfig('dbtUpdateDescriptions', val);
}}
@ -162,6 +178,7 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
return (
<DBTS3Config
cancelText={cancelText}
dbtClassificationName={dbtConfig?.dbtClassificationName}
dbtPrefixConfig={dbtConfig?.dbtPrefixConfig}
dbtSecurityConfig={dbtConfig?.dbtSecurityConfig}
dbtUpdateDescriptions={dbtConfig?.dbtUpdateDescriptions}
@ -171,6 +188,9 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
handleSecurityConfigChange={(val) => {
updateDbtConfig('dbtSecurityConfig', val);
}}
handleUpdateDBTClassification={(val) => {
updateDbtConfig('dbtClassificationName', val);
}}
handleUpdateDescriptions={(val) => {
updateDbtConfig('dbtUpdateDescriptions', val);
}}
@ -191,11 +211,9 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
ingestionName: event.target.value,
});
const handleDbtConfigSourceType = (
event: React.ChangeEvent<HTMLSelectElement>
) => {
const handleDbtConfigSourceType = (value: DBT_SOURCES) => {
onChange({
dbtConfigSourceType: event.target.value as DBT_SOURCES,
dbtConfigSourceType: value as DBT_SOURCES,
});
};
@ -203,6 +221,7 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
return (
<DBTGCSConfig
cancelText={cancelText}
dbtClassificationName={dbtConfig?.dbtClassificationName}
dbtPrefixConfig={dbtConfig?.dbtPrefixConfig}
dbtSecurityConfig={dbtConfig?.dbtSecurityConfig}
dbtUpdateDescriptions={dbtConfig?.dbtUpdateDescriptions}
@ -214,6 +233,9 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
handleSecurityConfigChange={(val) => {
updateDbtConfig('dbtSecurityConfig', val);
}}
handleUpdateDBTClassification={(val) => {
updateDbtConfig('dbtClassificationName', val);
}}
handleUpdateDescriptions={(val) => {
updateDbtConfig('dbtUpdateDescriptions', val);
}}
@ -284,13 +306,12 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
<p className="tw-text-grey-muted tw-mt-1 tw-mb-2 tw-text-sm">
{t('message.instance-identifier')}
</p>
<input
className="tw-form-inputs tw-form-inputs-padding"
data-testid="name"
<Input
className="w-full"
data-testid="profile-sample"
disabled={formType === FormSubmitType.EDIT}
id="name"
name="name"
type="text"
value={ingestionName}
onChange={handleOnchange}
/>
@ -303,22 +324,17 @@ const DBTConfigFormBuilder: FunctionComponent<DBTConfigFormProps> = ({
<p className="tw-text-grey-muted tw-mt-1 tw-mb-2 tw-text-sm">
{t('message.fetch-dbt-files')}
</p>
<select
className="tw-form-inputs tw-form-inputs-padding"
<Select
className="w-full"
data-testid="dbt-source"
id="dbt-source"
name="dbt-source"
options={DBTSources}
placeholder={t('label.select-field', {
field: t('label.dbt-source'),
})}
value={dbtConfigSourceType}
onChange={handleDbtConfigSourceType}>
{DBTSources.map((option, i) => (
<option key={i} value={option.value}>
{option.name}
</option>
))}
</select>
onChange={handleDbtConfigSourceType}
/>
</Field>
{getSeparator('')}
{getFields()}

View File

@ -24,34 +24,34 @@ import { DBT_SOURCES, GCS_CONFIG } from './DBTFormEnum';
export const DBTSources: Array<DropDownListItem> = [
{
name: 'Local Config Source',
label: 'Local Config Source',
value: DBT_SOURCES.local,
},
{
name: 'HTTP Config Source',
label: 'HTTP Config Source',
value: DBT_SOURCES.http,
},
{
name: 'Cloud Config Source',
label: 'Cloud Config Source',
value: DBT_SOURCES.cloud,
},
{
name: 'S3 Config Source',
label: 'S3 Config Source',
value: DBT_SOURCES.s3,
},
{
name: 'GCS Config Source',
label: 'GCS Config Source',
value: DBT_SOURCES.gcs,
},
];
export const GCSCreds: Array<DropDownListItem> = [
{
name: 'GCS Credentials Values',
label: 'GCS Credentials Values',
value: GCS_CONFIG.GCSValues,
},
{
name: 'GCS Credentials Path',
label: 'GCS Credentials Path',
value: GCS_CONFIG.GCSCredentialsPath,
},
];

View File

@ -21,6 +21,7 @@ const mockSubmit = jest.fn();
const mockPrefixConfigChange = jest.fn();
const mockSecurityConfigChange = jest.fn();
const mockUpdateDescriptions = jest.fn();
const mockUpdateDBTClassification = jest.fn();
const gsConfig = {
authProviderX509CertUrl: 'url',
@ -54,10 +55,11 @@ const mockProps = {
handlePrefixConfigChange: mockPrefixConfigChange,
handleSecurityConfigChange: mockSecurityConfigChange,
handleUpdateDescriptions: mockUpdateDescriptions,
handleUpdateDBTClassification: mockUpdateDBTClassification,
};
jest.mock('./SwitchField.component', () =>
jest.fn().mockImplementation(() => <div>UpdateDescriptionSwitch</div>)
jest.mock('./DBTCommonFields.component', () =>
jest.fn().mockImplementation(() => <div>DBT Common Fields</div>)
);
describe('Test DBT GCS Config Form', () => {

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { Input } from 'antd';
import { Button, Input, Select } from 'antd';
import { isEmpty, isObject, isString } from 'lodash';
import React, {
Fragment,
@ -28,8 +28,8 @@ import {
} from '../../../generated/metadataIngestion/dbtPipeline';
import jsonData from '../../../jsons/en';
import { errorMsg, getSeparator } from '../../../utils/CommonUtils';
import { Button } from '../../buttons/Button/Button';
import { Field } from '../../Field/Field';
import DBTCommonFields from './DBTCommonFields.component';
import {
DbtConfigS3GCS,
DBTFormCommonProps,
@ -37,7 +37,6 @@ import {
} from './DBTConfigForm.interface';
import { GCSCreds } from './DBTFormConstants';
import { GCS_CONFIG } from './DBTFormEnum';
import SwitchField from './SwitchField.component';
interface Props extends DBTFormCommonProps, DbtConfigS3GCS {
gcsType?: GCS_CONFIG;
@ -45,6 +44,7 @@ interface Props extends DBTFormCommonProps, DbtConfigS3GCS {
handleSecurityConfigChange: (value?: SCredentials) => void;
handlePrefixConfigChange: (value: DBTBucketDetails) => void;
handleUpdateDescriptions: (value: boolean) => void;
handleUpdateDBTClassification: (value: string) => void;
}
export const DBTGCSConfig: FunctionComponent<Props> = ({
@ -60,6 +60,8 @@ export const DBTGCSConfig: FunctionComponent<Props> = ({
handleSecurityConfigChange,
handlePrefixConfigChange,
handleUpdateDescriptions,
dbtClassificationName,
handleUpdateDBTClassification,
}: Props) => {
const isMounted = useRef<boolean>(false);
const updateGCSCredsConfig = (
@ -116,6 +118,7 @@ export const DBTGCSConfig: FunctionComponent<Props> = ({
dbtSecurityConfig,
dbtPrefixConfig,
dbtUpdateDescriptions,
dbtClassificationName,
};
if (validate(submitData)) {
onSubmit(submitData);
@ -375,23 +378,17 @@ export const DBTGCSConfig: FunctionComponent<Props> = ({
<p className="tw-text-grey-muted tw-mt-1 tw-mb-2 tw-text-sm">
Available sources to fetch dbt catalog and manifest files.
</p>
<select
className="tw-form-inputs tw-form-inputs-padding"
<Select
className="tw-form-inputs"
data-testid="gcs-config"
id="gcs-config"
name="gcs-config"
options={GCSCreds}
placeholder="Select GCS Config Type"
value={gcsType}
onChange={(e) => {
handleGcsTypeChange &&
handleGcsTypeChange(e.target.value as GCS_CONFIG);
}}>
{GCSCreds.map((option, i) => (
<option key={i} value={option.value}>
{option.name}
</option>
))}
</select>
onChange={(value) => {
handleGcsTypeChange && handleGcsTypeChange(value as GCS_CONFIG);
}}
/>
</Field>
{gcsType === GCS_CONFIG.GCSValues
? gcsCredConfigs(dbtSecurityConfig?.gcsConfig as GCSCredentialsValues)
@ -437,32 +434,31 @@ export const DBTGCSConfig: FunctionComponent<Props> = ({
{getSeparator('')}
<SwitchField
<DBTCommonFields
dbtClassificationName={dbtClassificationName}
dbtUpdateDescriptions={dbtUpdateDescriptions}
descriptionId="gcs-update-description"
handleUpdateDBTClassification={handleUpdateDBTClassification}
handleUpdateDescriptions={handleUpdateDescriptions}
id="gcs-update-description"
/>
{getSeparator('')}
<Field className="tw-flex tw-justify-end">
<Field className="d-flex justify-end">
<Button
className="tw-mr-2"
className="m-r-xs"
data-testid="back-button"
size="regular"
theme="primary"
variant="text"
type="link"
onClick={onCancel}>
<span>{cancelText}</span>
{cancelText}
</Button>
<Button
className="font-medium p-x-md p-y-xxs h-auto rounded-6"
data-testid="submit-btn"
size="regular"
theme="primary"
variant="contained"
type="primary"
onClick={handleSubmit}>
<span>{okText}</span>
{okText}
</Button>
</Field>
</Fragment>

View File

@ -21,6 +21,11 @@ const mockCatalogChange = jest.fn();
const mockManifestChange = jest.fn();
const mockRunResultsHttpPathChange = jest.fn();
const mockUpdateDescriptions = jest.fn();
const mockUpdateDBTClassification = jest.fn();
jest.mock('./DBTCommonFields.component', () =>
jest.fn().mockImplementation(() => <div>DBT Common Fields</div>)
);
const mockProps = {
dbtCatalogHttpPath: '',
@ -35,12 +40,9 @@ const mockProps = {
handleManifestHttpPathChange: mockManifestChange,
handleRunResultsHttpPathChange: mockRunResultsHttpPathChange,
handleUpdateDescriptions: mockUpdateDescriptions,
handleUpdateDBTClassification: mockUpdateDBTClassification,
};
jest.mock('./SwitchField.component', () =>
jest.fn().mockImplementation(() => <div>UpdateDescriptionSwitch</div>)
);
describe('Test DBT Http Config Form', () => {
it('Fields should render', async () => {
const { container } = render(<DBTHttpConfig {...mockProps} />);

View File

@ -11,6 +11,7 @@
* limitations under the License.
*/
import { Button } from 'antd';
import React, { Fragment, FunctionComponent, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { DbtConfig } from '../../../generated/metadataIngestion/dbtPipeline';
@ -20,20 +21,20 @@ import {
requiredField,
} from '../../../utils/CommonUtils';
import { validateDbtHttpConfig } from '../../../utils/DBTConfigFormUtil';
import { Button } from '../../buttons/Button/Button';
import { Field } from '../../Field/Field';
import DBTCommonFields from './DBTCommonFields.component';
import {
DbtConfigHttp,
DBTFormCommonProps,
ErrorDbtHttp,
} from './DBTConfigForm.interface';
import SwitchField from './SwitchField.component';
interface Props extends DBTFormCommonProps, DbtConfigHttp {
handleCatalogHttpPathChange: (value: string) => void;
handleManifestHttpPathChange: (value: string) => void;
handleRunResultsHttpPathChange: (value: string) => void;
handleUpdateDescriptions: (value: boolean) => void;
handleUpdateDBTClassification: (value: string) => void;
}
export const DBTHttpConfig: FunctionComponent<Props> = ({
@ -49,6 +50,8 @@ export const DBTHttpConfig: FunctionComponent<Props> = ({
handleManifestHttpPathChange,
handleRunResultsHttpPathChange,
handleUpdateDescriptions,
dbtClassificationName,
handleUpdateDBTClassification,
}: Props) => {
const [errors, setErrors] = useState<ErrorDbtHttp>();
const { t } = useTranslation();
@ -66,6 +69,7 @@ export const DBTHttpConfig: FunctionComponent<Props> = ({
dbtManifestHttpPath,
dbtRunResultsHttpPath,
dbtUpdateDescriptions,
dbtClassificationName,
};
if (validate(submitData)) {
onSubmit(submitData);
@ -136,32 +140,31 @@ export const DBTHttpConfig: FunctionComponent<Props> = ({
</Field>
{getSeparator('')}
<SwitchField
<DBTCommonFields
dbtClassificationName={dbtClassificationName}
dbtUpdateDescriptions={dbtUpdateDescriptions}
descriptionId="http-update-description"
handleUpdateDBTClassification={handleUpdateDBTClassification}
handleUpdateDescriptions={handleUpdateDescriptions}
id="http-update-description"
/>
{getSeparator('')}
<Field className="tw-flex tw-justify-end">
<Field className="d-flex justify-end">
<Button
className="tw-mr-2"
className="m-r-xs"
data-testid="back-button"
size="regular"
theme="primary"
variant="text"
type="link"
onClick={onCancel}>
<span>{cancelText}</span>
{cancelText}
</Button>
<Button
className="font-medium p-x-md p-y-xxs h-auto rounded-6"
data-testid="submit-btn"
size="regular"
theme="primary"
variant="contained"
type="primary"
onClick={handleSubmit}>
<span>{okText}</span>
{okText}
</Button>
</Field>
</Fragment>

View File

@ -21,6 +21,7 @@ const mockCatalogChange = jest.fn();
const mockManifestChange = jest.fn();
const mockRunResultsFilePathChange = jest.fn();
const mockUpdateDescriptions = jest.fn();
const mockUpdateDBTClassification = jest.fn();
const mockProps = {
dbtCatalogFilePath: '',
@ -35,10 +36,11 @@ const mockProps = {
handleManifestFilePathChange: mockManifestChange,
handleRunResultsFilePathChange: mockRunResultsFilePathChange,
handleUpdateDescriptions: mockUpdateDescriptions,
handleUpdateDBTClassification: mockUpdateDBTClassification,
};
jest.mock('./SwitchField.component', () =>
jest.fn().mockImplementation(() => <div>UpdateDescriptionSwitch</div>)
jest.mock('./DBTCommonFields.component', () =>
jest.fn().mockImplementation(() => <div>DBT Common Fields</div>)
);
describe('Test DBT Local Config Form', () => {

View File

@ -11,6 +11,7 @@
* limitations under the License.
*/
import { Button } from 'antd';
import React, { Fragment, FunctionComponent, useState } from 'react';
import { DbtConfig } from '../../../generated/metadataIngestion/dbtPipeline';
import {
@ -19,20 +20,20 @@ import {
requiredField,
} from '../../../utils/CommonUtils';
import { validateDbtLocalConfig } from '../../../utils/DBTConfigFormUtil';
import { Button } from '../../buttons/Button/Button';
import { Field } from '../../Field/Field';
import DBTCommonFields from './DBTCommonFields.component';
import {
DbtConfigLocal,
DBTFormCommonProps,
ErrorDbtLocal,
} from './DBTConfigForm.interface';
import SwitchField from './SwitchField.component';
interface Props extends DBTFormCommonProps, DbtConfigLocal {
handleCatalogFilePathChange: (value: string) => void;
handleManifestFilePathChange: (value: string) => void;
handleRunResultsFilePathChange: (value: string) => void;
handleUpdateDescriptions: (value: boolean) => void;
handleUpdateDBTClassification: (value: string) => void;
}
export const DBTLocalConfig: FunctionComponent<Props> = ({
@ -48,6 +49,8 @@ export const DBTLocalConfig: FunctionComponent<Props> = ({
handleManifestFilePathChange,
handleRunResultsFilePathChange,
handleUpdateDescriptions,
dbtClassificationName,
handleUpdateDBTClassification,
}: Props) => {
const [errors, setErrors] = useState<ErrorDbtLocal>();
@ -64,6 +67,7 @@ export const DBTLocalConfig: FunctionComponent<Props> = ({
dbtManifestFilePath,
dbtRunResultsFilePath,
dbtUpdateDescriptions,
dbtClassificationName,
};
if (validate(submitData)) {
onSubmit(submitData);
@ -136,32 +140,31 @@ export const DBTLocalConfig: FunctionComponent<Props> = ({
</Field>
{getSeparator('')}
<SwitchField
<DBTCommonFields
dbtClassificationName={dbtClassificationName}
dbtUpdateDescriptions={dbtUpdateDescriptions}
descriptionId="local-update-description"
handleUpdateDBTClassification={handleUpdateDBTClassification}
handleUpdateDescriptions={handleUpdateDescriptions}
id="local-update-description"
/>
{getSeparator('')}
<Field className="tw-flex tw-justify-end">
<Field className="d-flex justify-end">
<Button
className="tw-mr-2"
className="m-r-xs"
data-testid="back-button"
size="regular"
theme="primary"
variant="text"
type="link"
onClick={onCancel}>
<span>{cancelText}</span>
{cancelText}
</Button>
<Button
className="font-medium p-x-md p-y-xxs h-auto rounded-6"
data-testid="submit-btn"
size="regular"
theme="primary"
variant="contained"
type="primary"
onClick={handleSubmit}>
<span>{okText}</span>
{okText}
</Button>
</Field>
</Fragment>

View File

@ -20,6 +20,7 @@ const mockSubmit = jest.fn();
const mockPrefixConfigChange = jest.fn();
const mockSecurityConfigChange = jest.fn();
const mockUpdateDescriptions = jest.fn();
const mockUpdateDBTClassification = jest.fn();
const mockProps = {
okText: 'Next',
@ -30,10 +31,11 @@ const mockProps = {
handlePrefixConfigChange: mockPrefixConfigChange,
handleSecurityConfigChange: mockSecurityConfigChange,
handleUpdateDescriptions: mockUpdateDescriptions,
handleUpdateDBTClassification: mockUpdateDBTClassification,
};
jest.mock('./SwitchField.component', () =>
jest.fn().mockImplementation(() => <div>UpdateDescriptionSwitch</div>)
jest.mock('./DBTCommonFields.component', () =>
jest.fn().mockImplementation(() => <div>DBT Common Fields</div>)
);
describe('Test DBT S3 Config Form', () => {

View File

@ -11,7 +11,7 @@
* limitations under the License.
*/
import { Input } from 'antd';
import { Button, Input } from 'antd';
import React, { Fragment, FunctionComponent, useState } from 'react';
import {
DBTBucketDetails,
@ -27,25 +27,26 @@ import {
checkDbtS3CredsConfigRules,
validateDbtS3Config,
} from '../../../utils/DBTConfigFormUtil';
import { Button } from '../../buttons/Button/Button';
import { Field } from '../../Field/Field';
import DBTCommonFields from './DBTCommonFields.component';
import {
DbtConfigS3GCS,
DBTFormCommonProps,
ErrorDbtS3,
} from './DBTConfigForm.interface';
import SwitchField from './SwitchField.component';
interface Props extends DBTFormCommonProps, DbtConfigS3GCS {
handleSecurityConfigChange: (value: SCredentials) => void;
handlePrefixConfigChange: (value: DBTBucketDetails) => void;
handleUpdateDescriptions: (value: boolean) => void;
handleUpdateDBTClassification: (value: string) => void;
}
export const DBTS3Config: FunctionComponent<Props> = ({
dbtSecurityConfig,
dbtPrefixConfig,
dbtUpdateDescriptions = false,
dbtClassificationName,
okText,
cancelText,
onCancel,
@ -53,6 +54,7 @@ export const DBTS3Config: FunctionComponent<Props> = ({
handleSecurityConfigChange,
handlePrefixConfigChange,
handleUpdateDescriptions,
handleUpdateDBTClassification,
}: Props) => {
const updateS3Creds = (key: keyof SCredentials, val: string) => {
const updatedCreds: SCredentials = {
@ -89,6 +91,7 @@ export const DBTS3Config: FunctionComponent<Props> = ({
dbtSecurityConfig,
dbtPrefixConfig,
dbtUpdateDescriptions,
dbtClassificationName,
};
if (validate(submitData)) {
onSubmit(submitData);
@ -231,32 +234,31 @@ export const DBTS3Config: FunctionComponent<Props> = ({
</Field>
{getSeparator('')}
<SwitchField
<DBTCommonFields
dbtClassificationName={dbtClassificationName}
dbtUpdateDescriptions={dbtUpdateDescriptions}
descriptionId="s3-update-description"
handleUpdateDBTClassification={handleUpdateDBTClassification}
handleUpdateDescriptions={handleUpdateDescriptions}
id="s3-update-description"
/>
{getSeparator('')}
<Field className="tw-flex tw-justify-end">
<Field className="d-flex justify-end">
<Button
className="tw-mr-2"
className="m-r-xs"
data-testid="back-button"
size="regular"
theme="primary"
variant="text"
type="link"
onClick={onCancel}>
<span>{cancelText}</span>
{cancelText}
</Button>
<Button
className="font-medium p-x-md p-y-xxs h-auto rounded-6"
data-testid="submit-btn"
size="regular"
theme="primary"
variant="contained"
type="primary"
onClick={handleSubmit}>
<span>{okText}</span>
{okText}
</Button>
</Field>
</Fragment>

View File

@ -1,53 +0,0 @@
/*
* Copyright 2022 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 { Space, Switch } from 'antd';
import React from 'react';
import { Field } from '../../Field/Field';
interface Props {
dbtUpdateDescriptions: boolean;
id: string;
handleUpdateDescriptions: (value: boolean) => void;
}
function SwitchField({
dbtUpdateDescriptions,
id,
handleUpdateDescriptions,
}: Props) {
return (
<Field>
<Space align="end" className="m-b-xs">
<label
className="tw-block tw-form-label m-b-0"
data-testid={id}
htmlFor={id}>
Update Description
</label>
<Switch
checked={dbtUpdateDescriptions}
id={id}
onChange={handleUpdateDescriptions}
/>
</Space>
<p
className="tw-text-grey-muted tw-mt-1 tw-mb-2 tw-text-xs"
data-testid="switch-description">
Optional configuration to update the description from dbt or not
</p>
</Field>
);
}
export default SwitchField;

View File

@ -20,7 +20,8 @@ export enum DropDownType {
}
export type DropDownListItem = {
name: string | React.ReactElement;
label?: string;
name?: string | React.ReactElement;
value?: string;
group?: string;
to?: string;

View File

@ -145,6 +145,7 @@
"date-filter": "Date Filter",
"day-left": "{{day}} left",
"days-change-lowercase": "{{days}}-days change",
"dbt-classification-name": "dbt Classification Name",
"dbt-configuration-source": "dbt Configuration Source",
"dbt-ingestion": "DBT Ingestion",
"dbt-lowercase": "dbt",
@ -543,6 +544,7 @@
"unique": "Unique",
"unpause": "UnPause",
"update": "Update",
"update-description": "Update Description",
"update-password": "Update Password",
"update-request-tag-plural": "Update Request Tags",
"updated": "Updated",
@ -622,6 +624,7 @@
"create-new-glossary-guide": "A Glossary is a controlled vocabulary used to define the concepts and terminology in an organization. Glossaries can be specific to a certain domain (for e.g., Business Glossary, Technical Glossary). In the glossary, the standard terms and concepts can be defined along with the synonyms, and related terms. Control can be established over how and who can add the terms in the glossary.",
"create-or-update-email-account-for-bot": "Changing the account email will update or create a new bot user.",
"created-this-task-lowercase": "created this task",
"custom-classification-name-dbt-tags": "Custom OpenMetadata Classification name for dbt tags ",
"data-asset-has-been-action-type": "Data Asset has been {{actionType}}",
"data-insight-page-views": "Displays the number of times a dataset type was viewed.",
"data-insight-subtitle": "Get a single pane view of the health of all your data assets over time.",
@ -734,6 +737,7 @@
"no-version-type-available": "No {{type}} version available",
"not-followed-anything": "You have not followed anything yet.",
"om-description": "Centralized metadata store, to discover, collaborate and get your data right.",
"optional-configuration-update-description-dbt": "Optional configuration to update the description from dbt or not",
"permanently-delete-metadata": "Permanently deleting this {{entityName}} will remove its metadata from OpenMetadata permanently.",
"permanently-delete-metadata-and-dependents": "Permanently deleting this {{entityName}} will remove its metadata, as well as the metadata of {{dependents}} from OpenMetadata permanently.",
"pipeline-description-message": "Description of the pipeline.",