mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-30 20:06:19 +00:00
refactor: configure service form (#11734)
* refactor: configure service form * improve unit test * address comments
This commit is contained in:
parent
ef2869cd9a
commit
c68d85ebd5
@ -17,6 +17,7 @@ import {
|
|||||||
CUSTOM_PROPERTY_INVALID_NAMES,
|
CUSTOM_PROPERTY_INVALID_NAMES,
|
||||||
CUSTOM_PROPERTY_NAME_VALIDATION_ERROR,
|
CUSTOM_PROPERTY_NAME_VALIDATION_ERROR,
|
||||||
DELETE_TERM,
|
DELETE_TERM,
|
||||||
|
NAME_VALIDATION_ERROR,
|
||||||
SEARCH_INDEX,
|
SEARCH_INDEX,
|
||||||
} from '../constants/constants';
|
} from '../constants/constants';
|
||||||
|
|
||||||
@ -213,7 +214,20 @@ export const testServiceCreationAndIngestion = ({
|
|||||||
cy.get('[data-testid="next-button"]').should('exist').click();
|
cy.get('[data-testid="next-button"]').should('exist').click();
|
||||||
|
|
||||||
// Enter service name in step 2
|
// Enter service name in step 2
|
||||||
cy.get('[data-testid="service-name"]').should('exist').type(serviceName);
|
|
||||||
|
// validation should work
|
||||||
|
cy.get('[data-testid="next-button"]').should('exist').click();
|
||||||
|
|
||||||
|
cy.get('#name_help').should('be.visible').contains('name is required');
|
||||||
|
|
||||||
|
// invalid name validation should work
|
||||||
|
cy.get('[data-testid="service-name"]').should('exist').type('!@#$%^&*()');
|
||||||
|
cy.get('#name_help').should('be.visible').contains(NAME_VALIDATION_ERROR);
|
||||||
|
|
||||||
|
cy.get('[data-testid="service-name"]')
|
||||||
|
.should('exist')
|
||||||
|
.clear()
|
||||||
|
.type(serviceName);
|
||||||
interceptURL('GET', '/api/v1/services/ingestionPipelines/ip', 'ipApi');
|
interceptURL('GET', '/api/v1/services/ingestionPipelines/ip', 'ipApi');
|
||||||
interceptURL(
|
interceptURL(
|
||||||
'GET',
|
'GET',
|
||||||
|
@ -28,16 +28,11 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import { showErrorToast } from 'utils/ToastUtils';
|
import { showErrorToast } from 'utils/ToastUtils';
|
||||||
import { getServiceDetailsPath } from '../../constants/constants';
|
import { getServiceDetailsPath } from '../../constants/constants';
|
||||||
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
|
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
|
||||||
import { delimiterRegex, nameWithSpace } from '../../constants/regex.constants';
|
|
||||||
import { FormSubmitType } from '../../enums/form.enum';
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
import { PipelineType } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
import { PipelineType } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import { ConfigData } from '../../interface/service.interface';
|
import { ConfigData } from '../../interface/service.interface';
|
||||||
import {
|
import { getCurrentUserId, getServiceLogo } from '../../utils/CommonUtils';
|
||||||
getCurrentUserId,
|
|
||||||
getServiceLogo,
|
|
||||||
isUrlFriendlyName,
|
|
||||||
} from '../../utils/CommonUtils';
|
|
||||||
import { getAddServicePath, getSettingPath } from '../../utils/RouterUtils';
|
import { getAddServicePath, getSettingPath } from '../../utils/RouterUtils';
|
||||||
import {
|
import {
|
||||||
getServiceCreatedLabel,
|
getServiceCreatedLabel,
|
||||||
@ -50,7 +45,7 @@ import SuccessScreen from '../common/success-screen/SuccessScreen';
|
|||||||
import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component';
|
import TitleBreadcrumb from '../common/title-breadcrumb/title-breadcrumb.component';
|
||||||
import IngestionStepper from '../IngestionStepper/IngestionStepper.component';
|
import IngestionStepper from '../IngestionStepper/IngestionStepper.component';
|
||||||
import ConnectionConfigForm from '../ServiceConfig/ConnectionConfigForm';
|
import ConnectionConfigForm from '../ServiceConfig/ConnectionConfigForm';
|
||||||
import { AddServiceProps } from './AddService.interface';
|
import { AddServiceProps, ServiceConfig } from './AddService.interface';
|
||||||
import ConfigureService from './Steps/ConfigureService';
|
import ConfigureService from './Steps/ConfigureService';
|
||||||
import SelectServiceType from './Steps/SelectServiceType';
|
import SelectServiceType from './Steps/SelectServiceType';
|
||||||
|
|
||||||
@ -78,16 +73,21 @@ const AddService = ({
|
|||||||
const [activeServiceStep, setActiveServiceStep] = useState(1);
|
const [activeServiceStep, setActiveServiceStep] = useState(1);
|
||||||
const [activeIngestionStep, setActiveIngestionStep] = useState(1);
|
const [activeIngestionStep, setActiveIngestionStep] = useState(1);
|
||||||
const [selectServiceType, setSelectServiceType] = useState('');
|
const [selectServiceType, setSelectServiceType] = useState('');
|
||||||
const [serviceName, setServiceName] = useState('');
|
const [serviceConfig, setServiceConfig] = useState<ServiceConfig>({
|
||||||
const [description, setDescription] = useState('');
|
serviceName: '',
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
|
|
||||||
const [saveServiceState, setSaveServiceState] =
|
const [saveServiceState, setSaveServiceState] =
|
||||||
useState<LoadingState>('initial');
|
useState<LoadingState>('initial');
|
||||||
const [activeField, setActiveField] = useState<string>('');
|
const [activeField, setActiveField] = useState<string>('');
|
||||||
|
|
||||||
const handleServiceTypeClick = (type: string) => {
|
const handleServiceTypeClick = (type: string) => {
|
||||||
setShowErrorMessage({ ...showErrorMessage, serviceType: false });
|
setShowErrorMessage({ ...showErrorMessage, serviceType: false });
|
||||||
setServiceName('');
|
setServiceConfig({
|
||||||
setDescription('');
|
serviceName: '',
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
setSelectServiceType(type);
|
setSelectServiceType(type);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,47 +117,18 @@ const AddService = ({
|
|||||||
|
|
||||||
// Configure service name
|
// Configure service name
|
||||||
const handleConfigureServiceBackClick = () => setActiveServiceStep(1);
|
const handleConfigureServiceBackClick = () => setActiveServiceStep(1);
|
||||||
const handleConfigureServiceNextClick = (descriptionValue: string) => {
|
const handleConfigureServiceNextClick = (value: ServiceConfig) => {
|
||||||
setDescription(descriptionValue.trim());
|
setServiceConfig(value);
|
||||||
|
setActiveServiceStep(3);
|
||||||
if (!serviceName.trim()) {
|
|
||||||
setShowErrorMessage({ ...showErrorMessage, name: true, isError: true });
|
|
||||||
} else if (nameWithSpace.test(serviceName)) {
|
|
||||||
setShowErrorMessage({
|
|
||||||
...showErrorMessage,
|
|
||||||
nameWithSpace: true,
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
} else if (delimiterRegex.test(serviceName)) {
|
|
||||||
setShowErrorMessage({
|
|
||||||
...showErrorMessage,
|
|
||||||
delimit: true,
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
} else if (!isUrlFriendlyName(serviceName.trim())) {
|
|
||||||
setShowErrorMessage({
|
|
||||||
...showErrorMessage,
|
|
||||||
specialChar: true,
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
} else if (serviceName.length < 1 || serviceName.length > 128) {
|
|
||||||
setShowErrorMessage({
|
|
||||||
...showErrorMessage,
|
|
||||||
nameLength: true,
|
|
||||||
isError: true,
|
|
||||||
});
|
|
||||||
} else if (!showErrorMessage.isError) {
|
|
||||||
setActiveServiceStep(3);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Service connection
|
// Service connection
|
||||||
const handleConnectionDetailsBackClick = () => setActiveServiceStep(2);
|
const handleConnectionDetailsBackClick = () => setActiveServiceStep(2);
|
||||||
const handleConfigUpdate = async (newConfigData: ConfigData) => {
|
const handleConfigUpdate = async (newConfigData: ConfigData) => {
|
||||||
const data = {
|
const data = {
|
||||||
name: serviceName,
|
name: serviceConfig.serviceName,
|
||||||
serviceType: selectServiceType,
|
serviceType: selectServiceType,
|
||||||
description: description,
|
description: serviceConfig.description,
|
||||||
owner: {
|
owner: {
|
||||||
id: getCurrentUserId(),
|
id: getCurrentUserId(),
|
||||||
type: 'user',
|
type: 'user',
|
||||||
@ -183,7 +154,7 @@ const AddService = ({
|
|||||||
showErrorToast(
|
showErrorToast(
|
||||||
t('server.entity-already-exist', {
|
t('server.entity-already-exist', {
|
||||||
entity: t('label.service'),
|
entity: t('label.service'),
|
||||||
name: serviceName,
|
name: serviceConfig.serviceName,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -203,24 +174,6 @@ const AddService = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Service name validation
|
|
||||||
const handleServiceNameValidation = (
|
|
||||||
event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
|
|
||||||
) => {
|
|
||||||
const value = event.target.value;
|
|
||||||
setServiceName(value);
|
|
||||||
if (value) {
|
|
||||||
setShowErrorMessage({
|
|
||||||
...showErrorMessage,
|
|
||||||
name: false,
|
|
||||||
delimit: false,
|
|
||||||
specialChar: false,
|
|
||||||
nameLength: false,
|
|
||||||
isError: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Service focused field
|
// Service focused field
|
||||||
const handleFieldFocus = (fieldName: string) => {
|
const handleFieldFocus = (fieldName: string) => {
|
||||||
if (isEmpty(fieldName)) {
|
if (isEmpty(fieldName)) {
|
||||||
@ -267,18 +220,7 @@ const AddService = ({
|
|||||||
|
|
||||||
{activeServiceStep === 2 && (
|
{activeServiceStep === 2 && (
|
||||||
<ConfigureService
|
<ConfigureService
|
||||||
description={description}
|
serviceName={serviceConfig.serviceName}
|
||||||
handleValidation={handleServiceNameValidation}
|
|
||||||
serviceName={serviceName}
|
|
||||||
showError={{
|
|
||||||
name: showErrorMessage.name,
|
|
||||||
duplicateName: showErrorMessage.duplicateName,
|
|
||||||
nameWithSpace: showErrorMessage.nameWithSpace,
|
|
||||||
delimit: showErrorMessage.delimit,
|
|
||||||
specialChar: showErrorMessage.specialChar,
|
|
||||||
nameLength: showErrorMessage.nameLength,
|
|
||||||
allowChar: showErrorMessage.allowChar,
|
|
||||||
}}
|
|
||||||
onBack={handleConfigureServiceBackClick}
|
onBack={handleConfigureServiceBackClick}
|
||||||
onNext={handleConfigureServiceNextClick}
|
onNext={handleConfigureServiceNextClick}
|
||||||
/>
|
/>
|
||||||
@ -303,7 +245,7 @@ const AddService = ({
|
|||||||
showIngestionButton
|
showIngestionButton
|
||||||
handleIngestionClick={() => handleAddIngestion(true)}
|
handleIngestionClick={() => handleAddIngestion(true)}
|
||||||
handleViewServiceClick={handleViewServiceClick}
|
handleViewServiceClick={handleViewServiceClick}
|
||||||
name={serviceName}
|
name={serviceConfig.serviceName}
|
||||||
state={FormSubmitType.ADD}
|
state={FormSubmitType.ADD}
|
||||||
suffix={getServiceCreatedLabel(serviceCategory)}
|
suffix={getServiceCreatedLabel(serviceCategory)}
|
||||||
/>
|
/>
|
||||||
|
@ -31,3 +31,8 @@ export interface AddServiceProps {
|
|||||||
slashedBreadcrumb: TitleBreadcrumbProps['titleLinks'];
|
slashedBreadcrumb: TitleBreadcrumbProps['titleLinks'];
|
||||||
onIngestionDeploy?: () => Promise<void>;
|
onIngestionDeploy?: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ServiceConfig {
|
||||||
|
serviceName: string;
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
@ -11,83 +11,63 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { act, render, screen } from '@testing-library/react';
|
||||||
findByTestId,
|
import userEvent from '@testing-library/user-event';
|
||||||
findByText,
|
import React from 'react';
|
||||||
fireEvent,
|
|
||||||
render,
|
|
||||||
} from '@testing-library/react';
|
|
||||||
import React, { forwardRef } from 'react';
|
|
||||||
import ConfigureService from './ConfigureService';
|
import ConfigureService from './ConfigureService';
|
||||||
import { ConfigureServiceProps } from './Steps.interface';
|
import { ConfigureServiceProps } from './Steps.interface';
|
||||||
|
|
||||||
const mockConfigureServiceProps: ConfigureServiceProps = {
|
const mockConfigureServiceProps: ConfigureServiceProps = {
|
||||||
serviceName: 'testService',
|
serviceName: 'testService',
|
||||||
description: '',
|
|
||||||
showError: {
|
|
||||||
name: false,
|
|
||||||
duplicateName: false,
|
|
||||||
nameWithSpace: false,
|
|
||||||
delimit: false,
|
|
||||||
specialChar: false,
|
|
||||||
nameLength: false,
|
|
||||||
allowChar: false,
|
|
||||||
},
|
|
||||||
handleValidation: jest.fn(),
|
|
||||||
onBack: jest.fn(),
|
onBack: jest.fn(),
|
||||||
onNext: jest.fn(),
|
onNext: jest.fn(),
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.mock('../../common/rich-text-editor/RichTextEditor', () => {
|
|
||||||
return forwardRef(
|
|
||||||
jest.fn().mockImplementation(({ initialValue }) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={(input) => {
|
|
||||||
return {
|
|
||||||
getEditorContent: input,
|
|
||||||
};
|
|
||||||
}}>
|
|
||||||
{initialValue}RichTextEditor.component
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Test ConfigureService component', () => {
|
describe('Test ConfigureService component', () => {
|
||||||
it('ConfigureService component should render', async () => {
|
it('ConfigureService component should render', async () => {
|
||||||
const { container } = render(
|
render(<ConfigureService {...mockConfigureServiceProps} />);
|
||||||
<ConfigureService {...mockConfigureServiceProps} />
|
|
||||||
);
|
|
||||||
|
|
||||||
const configureServiceContainer = await findByTestId(
|
const configureServiceContainer = screen.getByTestId(
|
||||||
container,
|
|
||||||
'configure-service-container'
|
'configure-service-container'
|
||||||
);
|
);
|
||||||
const serviceName = await findByTestId(container, 'service-name');
|
const serviceName = screen.getByTestId('service-name');
|
||||||
const backButton = await findByTestId(container, 'back-button');
|
const backButton = screen.getByTestId('back-button');
|
||||||
const nextButton = await findByTestId(container, 'next-button');
|
const nextButton = screen.getByTestId('next-button');
|
||||||
const richTextEditor = await findByText(
|
const richTextEditor = screen.getByTestId('editor');
|
||||||
container,
|
|
||||||
'RichTextEditor.component'
|
|
||||||
);
|
|
||||||
|
|
||||||
fireEvent.change(serviceName, {
|
|
||||||
target: {
|
|
||||||
value: 'newName',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
fireEvent.click(backButton);
|
|
||||||
fireEvent.click(nextButton);
|
|
||||||
|
|
||||||
expect(configureServiceContainer).toBeInTheDocument();
|
expect(configureServiceContainer).toBeInTheDocument();
|
||||||
expect(richTextEditor).toBeInTheDocument();
|
expect(richTextEditor).toBeInTheDocument();
|
||||||
expect(serviceName).toBeInTheDocument();
|
expect(serviceName).toBeInTheDocument();
|
||||||
expect(backButton).toBeInTheDocument();
|
expect(backButton).toBeInTheDocument();
|
||||||
expect(nextButton).toBeInTheDocument();
|
expect(nextButton).toBeInTheDocument();
|
||||||
expect(mockConfigureServiceProps.handleValidation).toHaveBeenCalled();
|
});
|
||||||
|
|
||||||
|
it('Back button should work', () => {
|
||||||
|
render(<ConfigureService {...mockConfigureServiceProps} />);
|
||||||
|
const backButton = screen.getByTestId('back-button');
|
||||||
|
|
||||||
|
userEvent.click(backButton);
|
||||||
|
|
||||||
expect(mockConfigureServiceProps.onBack).toHaveBeenCalled();
|
expect(mockConfigureServiceProps.onBack).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Next button should work', async () => {
|
||||||
|
render(<ConfigureService {...mockConfigureServiceProps} />);
|
||||||
|
const serviceName = screen.getByTestId('service-name');
|
||||||
|
const nextButton = screen.getByTestId('next-button');
|
||||||
|
|
||||||
|
userEvent.type(serviceName, 'newName');
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
userEvent.click(nextButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(serviceName).toHaveValue('newName');
|
||||||
|
|
||||||
expect(mockConfigureServiceProps.onNext).toHaveBeenCalled();
|
expect(mockConfigureServiceProps.onNext).toHaveBeenCalled();
|
||||||
|
expect(mockConfigureServiceProps.onNext).toHaveBeenCalledWith({
|
||||||
|
description: '',
|
||||||
|
serviceName: 'newName',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,96 +11,79 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Button } from 'antd';
|
import { Button, Form, FormProps, Space } from 'antd';
|
||||||
|
import { ENTITY_NAME_REGEX } from 'constants/regex.constants';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import React, { useRef } from 'react';
|
import React from 'react';
|
||||||
import { errorMsg, requiredField } from '../../../utils/CommonUtils';
|
import { FieldProp, FieldTypes, generateFormFields } from 'utils/formUtils';
|
||||||
import RichTextEditor from '../../common/rich-text-editor/RichTextEditor';
|
|
||||||
import { EditorContentRef } from '../../common/rich-text-editor/RichTextEditor.interface';
|
|
||||||
import { Field } from '../../Field/Field';
|
|
||||||
import { ConfigureServiceProps } from './Steps.interface';
|
import { ConfigureServiceProps } from './Steps.interface';
|
||||||
|
|
||||||
const ConfigureService = ({
|
const ConfigureService = ({
|
||||||
serviceName,
|
serviceName,
|
||||||
description,
|
|
||||||
showError,
|
|
||||||
handleValidation,
|
|
||||||
onBack,
|
onBack,
|
||||||
onNext,
|
onNext,
|
||||||
}: ConfigureServiceProps) => {
|
}: ConfigureServiceProps) => {
|
||||||
const markdownRef = useRef<EditorContentRef>();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const validationErrorMsg = (): string => {
|
const formFields: FieldProp[] = [
|
||||||
if (showError.name) {
|
{
|
||||||
return t('message.field-text-is-required', {
|
name: 'name',
|
||||||
fieldText: t('label.service-name'),
|
id: 'root/name',
|
||||||
});
|
required: true,
|
||||||
}
|
label: t('label.service-name'),
|
||||||
if (showError.duplicateName) {
|
type: FieldTypes.TEXT,
|
||||||
return t('message.entity-already-exists', {
|
rules: [
|
||||||
entity: t('label.service-name'),
|
{
|
||||||
});
|
pattern: ENTITY_NAME_REGEX,
|
||||||
}
|
message: t('message.entity-name-validation'),
|
||||||
if (showError.delimit) {
|
},
|
||||||
return t('message.service-with-delimiters-not-allowed');
|
],
|
||||||
}
|
props: {
|
||||||
if (showError.nameWithSpace) {
|
'data-testid': 'service-name',
|
||||||
return t('message.service-with-space-not-allowed');
|
},
|
||||||
}
|
placeholder: t('label.service-name'),
|
||||||
if (showError.nameLength) {
|
formItemProps: {
|
||||||
return t('message.service-name-length');
|
initialValue: serviceName,
|
||||||
}
|
},
|
||||||
if (showError.specialChar) {
|
},
|
||||||
return t('message.special-character-not-allowed');
|
{
|
||||||
}
|
name: 'description',
|
||||||
|
required: false,
|
||||||
|
label: t('label.description'),
|
||||||
|
id: 'root/description',
|
||||||
|
type: FieldTypes.DESCRIPTION,
|
||||||
|
props: {
|
||||||
|
'data-testid': 'description',
|
||||||
|
initialValue: '',
|
||||||
|
},
|
||||||
|
formItemProps: {
|
||||||
|
trigger: 'onTextChange',
|
||||||
|
valuePropName: 'initialValue',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return '';
|
const handleSubmit: FormProps['onFinish'] = (data) => {
|
||||||
|
onNext({ serviceName: data.name, description: data.description ?? '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="configure-service-container">
|
<Form
|
||||||
<Field>
|
data-testid="configure-service-container"
|
||||||
<label className="tw-block tw-form-label" htmlFor="serviceName">
|
form={form}
|
||||||
{requiredField(`${t('label.service-name')}:`)}
|
layout="vertical"
|
||||||
</label>
|
onFinish={handleSubmit}>
|
||||||
|
{generateFormFields(formFields)}
|
||||||
<input
|
<Space className="w-full justify-end">
|
||||||
className="tw-form-inputs tw-form-inputs-padding"
|
<Button data-testid="back-button" type="link" onClick={onBack}>
|
||||||
data-testid="service-name"
|
|
||||||
id="serviceName"
|
|
||||||
name="serviceName"
|
|
||||||
placeholder={t('label.service-name')}
|
|
||||||
type="text"
|
|
||||||
value={serviceName}
|
|
||||||
onChange={handleValidation}
|
|
||||||
/>
|
|
||||||
{errorMsg(validationErrorMsg())}
|
|
||||||
</Field>
|
|
||||||
<Field>
|
|
||||||
<label className="tw-block tw-form-label" htmlFor="description">
|
|
||||||
{`${t('label.description')}:`}
|
|
||||||
</label>
|
|
||||||
<RichTextEditor initialValue={description} ref={markdownRef} />
|
|
||||||
</Field>
|
|
||||||
|
|
||||||
<Field className="d-flex tw-justify-end tw-mt-10">
|
|
||||||
<Button
|
|
||||||
className="m-r-xs"
|
|
||||||
data-testid="back-button"
|
|
||||||
type="link"
|
|
||||||
onClick={onBack}>
|
|
||||||
{t('label.back')}
|
{t('label.back')}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button data-testid="next-button" htmlType="submit" type="primary">
|
||||||
className="font-medium p-x-md p-y-xxs h-auto rounded-6"
|
|
||||||
data-testid="next-button"
|
|
||||||
type="primary"
|
|
||||||
onClick={() => onNext(markdownRef.current?.getEditorContent() || '')}>
|
|
||||||
{t('label.next')}
|
{t('label.next')}
|
||||||
</Button>
|
</Button>
|
||||||
</Field>
|
</Space>
|
||||||
</div>
|
</Form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
import { DynamicFormFieldType } from 'Models';
|
import { DynamicFormFieldType } from 'Models';
|
||||||
import { ServiceCategory } from '../../../enums/service.enum';
|
import { ServiceCategory } from '../../../enums/service.enum';
|
||||||
|
import { ServiceConfig } from '../AddService.interface';
|
||||||
|
|
||||||
export type SelectServiceTypeProps = {
|
export type SelectServiceTypeProps = {
|
||||||
showError: boolean;
|
showError: boolean;
|
||||||
@ -26,21 +27,8 @@ export type SelectServiceTypeProps = {
|
|||||||
|
|
||||||
export type ConfigureServiceProps = {
|
export type ConfigureServiceProps = {
|
||||||
serviceName: string;
|
serviceName: string;
|
||||||
description: string;
|
|
||||||
showError: {
|
|
||||||
name: boolean;
|
|
||||||
duplicateName: boolean;
|
|
||||||
nameWithSpace: boolean;
|
|
||||||
delimit: boolean;
|
|
||||||
specialChar: boolean;
|
|
||||||
nameLength: boolean;
|
|
||||||
allowChar: boolean;
|
|
||||||
};
|
|
||||||
handleValidation: (
|
|
||||||
event: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
|
|
||||||
) => void;
|
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
onNext: (description: string) => void;
|
onNext: (data: ServiceConfig) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ConnectionDetailsProps = {
|
export type ConnectionDetailsProps = {
|
||||||
|
@ -307,14 +307,6 @@ export const STEPS_FOR_ADD_SERVICE: Array<StepperStepType> = [
|
|||||||
|
|
||||||
export const SERVICE_DEFAULT_ERROR_MAP = {
|
export const SERVICE_DEFAULT_ERROR_MAP = {
|
||||||
serviceType: false,
|
serviceType: false,
|
||||||
name: false,
|
|
||||||
duplicateName: false,
|
|
||||||
nameWithSpace: false,
|
|
||||||
delimit: false,
|
|
||||||
specialChar: false,
|
|
||||||
nameLength: false,
|
|
||||||
allowChar: false,
|
|
||||||
isError: false,
|
|
||||||
};
|
};
|
||||||
// 2 minutes
|
// 2 minutes
|
||||||
export const FETCHING_EXPIRY_TIME = 2 * 60 * 1000;
|
export const FETCHING_EXPIRY_TIME = 2 * 60 * 1000;
|
||||||
|
@ -137,10 +137,6 @@
|
|||||||
@apply tw-font-normal tw-px-2;
|
@apply tw-font-normal tw-px-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tw-form-label {
|
|
||||||
@apply tw-block tw-text-body tw-font-normal tw-text-grey-body tw-mb-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeCategory .label-category {
|
.activeCategory .label-category {
|
||||||
@apply tw-text-primary;
|
@apply tw-text-primary;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user