Addressing service page changes (#2421)

* Addressing service page changes

* Reverting unnecessary change

* Minor change
This commit is contained in:
darth-coder00 2022-01-25 18:41:17 +05:30 committed by GitHub
parent 3aefe3636b
commit e7e5a4dd2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 272 deletions

View File

@ -24,7 +24,7 @@ export const getAirflowPipelines = (
serviceFilter?: string, serviceFilter?: string,
paging?: string paging?: string
): Promise<AxiosResponse> => { ): Promise<AxiosResponse> => {
const service = `"service="${serviceFilter}`; const service = `service=${serviceFilter}`;
const url = `${getURLWithQueryFields( const url = `${getURLWithQueryFields(
'/airflowPipeline', '/airflowPipeline',
arrQueryFields, arrQueryFields,

View File

@ -15,13 +15,7 @@ import classNames from 'classnames';
import cronstrue from 'cronstrue'; import cronstrue from 'cronstrue';
import { capitalize, isNil, lowerCase } from 'lodash'; import { capitalize, isNil, lowerCase } from 'lodash';
import React, { Fragment, useCallback, useState } from 'react'; import React, { Fragment, useCallback, useState } from 'react';
import { Link } from 'react-router-dom'; import { TITLE_FOR_NON_ADMIN_ACTION } from '../../constants/constants';
import {
getServiceDetailsPath,
TITLE_FOR_NON_ADMIN_ACTION,
} from '../../constants/constants';
import { NoDataFoundPlaceHolder } from '../../constants/services.const';
import { ServiceCategory } from '../../enums/service.enum';
import { import {
AirflowPipeline, AirflowPipeline,
ConfigObject, ConfigObject,
@ -42,6 +36,7 @@ import { Props } from './ingestion.interface';
const Ingestion: React.FC<Props> = ({ const Ingestion: React.FC<Props> = ({
serviceType = '', serviceType = '',
serviceName,
ingestionList, ingestionList,
serviceList, serviceList,
deleteIngestion, deleteIngestion,
@ -183,13 +178,6 @@ const Ingestion: React.FC<Props> = ({
setIsConfirmationModalOpen(true); setIsConfirmationModalOpen(true);
}; };
const getServiceTypeFromName = (serviceName = ''): string => {
return (
serviceList.find((service) => service.name === serviceName)
?.serviceType || ''
);
};
const getSearchedIngestions = useCallback(() => { const getSearchedIngestions = useCallback(() => {
const sText = lowerCase(searchText); const sText = lowerCase(searchText);
@ -290,7 +278,6 @@ const Ingestion: React.FC<Props> = ({
<tr className="tableHead-row" data-testid="table-header"> <tr className="tableHead-row" data-testid="table-header">
<th className="tableHead-cell">Name</th> <th className="tableHead-cell">Name</th>
<th className="tableHead-cell">Type</th> <th className="tableHead-cell">Type</th>
<th className="tableHead-cell">Service</th>
<th className="tableHead-cell">Schedule</th> <th className="tableHead-cell">Schedule</th>
<th className="tableHead-cell">Recent Runs</th> <th className="tableHead-cell">Recent Runs</th>
{/* <th className="tableHead-cell">Next Run</th> */} {/* <th className="tableHead-cell">Next Run</th> */}
@ -307,17 +294,6 @@ const Ingestion: React.FC<Props> = ({
key={index}> key={index}>
<td className="tableBody-cell">{ingestion.name}</td> <td className="tableBody-cell">{ingestion.name}</td>
<td className="tableBody-cell">{ingestion.pipelineType}</td> <td className="tableBody-cell">{ingestion.pipelineType}</td>
<td className="tableBody-cell">
<Link
to={getServiceDetailsPath(
ingestion.service.name as string,
getServiceTypeFromName(ingestion.service.name),
// TODO: Add logic below to select service-cat if necessary
ServiceCategory.DATABASE_SERVICES
)}>
{ingestion.service.name}
</Link>
</td>
<td className="tableBody-cell"> <td className="tableBody-cell">
<PopOver <PopOver
html={ html={
@ -414,9 +390,6 @@ const Ingestion: React.FC<Props> = ({
) : ( ) : (
<div className="tw-flex tw-items-center tw-flex-col"> <div className="tw-flex tw-items-center tw-flex-col">
<div className="tw-mt-24"> <div className="tw-mt-24">
<img alt="No Service" src={NoDataFoundPlaceHolder} width={250} />
</div>
<div className="tw-mt-11">
<p className="tw-text-lg tw-text-center"> <p className="tw-text-lg tw-text-center">
{`No ingestion workflows found ${ {`No ingestion workflows found ${
searchText ? `for "${searchText}"` : '' searchText ? `for "${searchText}"` : ''
@ -436,7 +409,7 @@ const Ingestion: React.FC<Props> = ({
ingestionList={ingestionList} ingestionList={ingestionList}
ingestionTypes={getAirflowPipelineTypeOption()} ingestionTypes={getAirflowPipelineTypeOption()}
name="" name=""
service="" service={serviceName}
serviceList={serviceList.map((s) => ({ serviceList={serviceList.map((s) => ({
name: s.name, name: s.name,
serviceType: s.serviceType, serviceType: s.serviceType,
@ -452,6 +425,7 @@ const Ingestion: React.FC<Props> = ({
ingestionList={ingestionList} ingestionList={ingestionList}
ingestionTypes={getAirflowPipelineTypes(serviceType) || []} ingestionTypes={getAirflowPipelineTypes(serviceType) || []}
selectedIngestion={updateSelection.ingestion} selectedIngestion={updateSelection.ingestion}
service={serviceName}
serviceList={serviceList.map((s) => ({ serviceList={serviceList.map((s) => ({
name: s.name, name: s.name,
serviceType: s.serviceType, serviceType: s.serviceType,

View File

@ -50,6 +50,7 @@ export interface IngestionData {
export interface Props { export interface Props {
serviceType?: string; serviceType?: string;
serviceName?: string;
paging: Paging; paging: Paging;
ingestionList: Array<AirflowPipeline>; ingestionList: Array<AirflowPipeline>;
serviceList: Array<DatabaseService>; serviceList: Array<DatabaseService>;

View File

@ -27,7 +27,6 @@ import {
getCurrentUserId, getCurrentUserId,
getSeparator, getSeparator,
} from '../../utils/CommonUtils'; } from '../../utils/CommonUtils';
import { getIngestionTypeList } from '../../utils/ServiceUtils';
import SVGIcons from '../../utils/SvgUtils'; import SVGIcons from '../../utils/SvgUtils';
import { Button } from '../buttons/Button/Button'; import { Button } from '../buttons/Button/Button';
import CronEditor from '../common/CronEditor/CronEditor'; import CronEditor from '../common/CronEditor/CronEditor';
@ -87,10 +86,6 @@ const PreviewSection = ({
); );
}; };
const getServiceName = (service: string) => {
return service.split('$$').splice(1).join('$$');
};
const getIngestionName = (name: string) => { const getIngestionName = (name: string) => {
const nameString = name.trim().replace(/\s+/g, '_'); const nameString = name.trim().replace(/\s+/g, '_');
@ -100,7 +95,7 @@ const getIngestionName = (name: string) => {
const IngestionModal: React.FC<IngestionModalProps> = ({ const IngestionModal: React.FC<IngestionModalProps> = ({
isUpdating, isUpdating,
header, header,
serviceList = [], // TODO: remove default assignment after resolving prop validation warning service,
ingestionTypes, ingestionTypes,
ingestionList, ingestionList,
onCancel, onCancel,
@ -121,14 +116,11 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
); );
const [ingestionName, setIngestionName] = useState<string>( const [ingestionName, setIngestionName] = useState<string>(
selectedIngestion?.name || '' selectedIngestion?.name || service || ''
); );
const [ingestionType, setIngestionType] = useState<string>( const [ingestionType, setIngestionType] = useState<string>(
selectedIngestion?.pipelineType || '' selectedIngestion?.pipelineType || ''
); );
const [ingestionService, setIngestionService] = useState<string>(
selectedIngestion?.service.name || ''
);
const [pipelineConfig] = useState( const [pipelineConfig] = useState(
(selectedIngestion?.pipelineConfig.config || {}) as ConfigObject (selectedIngestion?.pipelineConfig.config || {}) as ConfigObject
); );
@ -171,16 +163,6 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
isPipelineNameExists: false, isPipelineNameExists: false,
}); });
const isPipelineExists = () => {
return ingestionList.some(
(i) =>
i.service.name === getServiceName(ingestionService) &&
i.pipelineType === ingestionType &&
i.service.name !== selectedIngestion?.name &&
i.service.displayName === selectedIngestion?.pipelineType
);
};
const isPipeLineNameExists = () => { const isPipeLineNameExists = () => {
return ingestionList.some( return ingestionList.some(
(i) => (i) =>
@ -196,17 +178,9 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
const name = event.target.name; const name = event.target.name;
switch (name) { switch (name) {
case 'name':
setIngestionName(value);
break;
case 'selectService':
setIngestionService(value);
setIngestionType('');
break;
case 'ingestionType': case 'ingestionType':
setIngestionType(value); setIngestionType(value);
setIngestionName(`${service}_${value}`);
break; break;
@ -228,28 +202,14 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
let isValid = false; let isValid = false;
switch (activeStep) { switch (activeStep) {
case 1: case 1:
isValid = Boolean( isValid = Boolean(ingestionName && ingestionType);
ingestionName && ingestionType && !isPipelineExists()
);
setShowErrorMsg({ setShowErrorMsg({
...showErrorMsg, ...showErrorMsg,
name: !ingestionName, name: !ingestionName,
ingestionType: !ingestionType, ingestionType: !ingestionType,
selectService: !ingestionService,
}); });
break; break;
// case 2:
// isValid = Boolean(username && password && host && database);
// setShowErrorMsg({
// ...showErrorMsg,
// username: !username,
// password: !password,
// host: !host,
// database: !database,
// });
// break;
case 2: case 2:
isValid = Boolean(ingestionSchedule); isValid = Boolean(ingestionSchedule);
setShowErrorMsg({ setShowErrorMsg({
@ -267,91 +227,6 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
const getActiveStepFields = (activeStep: number) => { const getActiveStepFields = (activeStep: number) => {
switch (activeStep) { switch (activeStep) {
case 10:
return (
<Fragment>
<Field>
<label className="tw-block" htmlFor="name">
{requiredField('Name:')}
</label>
<input
className={classNames('tw-form-inputs tw-px-3 tw-py-1', {
'tw-cursor-not-allowed': isUpdating,
})}
data-testid="name"
id="name"
name="name"
placeholder="Ingestion name"
readOnly={isUpdating}
type="text"
value={ingestionName}
onChange={handleValidation}
/>
{showErrorMsg.name && errorMsg('Ingestion Name is required')}
{showErrorMsg.isPipelineNameExists &&
errorMsg(`Ingestion with similar name already exists.`)}
</Field>
<Field>
<label className="tw-block" htmlFor="selectService">
{requiredField('Select Service:')}
</label>
<select
className={classNames('tw-form-inputs tw-px-3 tw-py-1', {
'tw-cursor-not-allowed': isUpdating,
})}
data-testid="select-service"
disabled={isUpdating}
id="selectService"
name="selectService"
value={ingestionService}
onChange={handleValidation}>
<option value="">Select Service</option>
{serviceList.map((service, index) => (
<option
key={index}
value={`${service.serviceType}$$${service.name}`}>
{service.name}
</option>
))}
</select>
{showErrorMsg.selectService && errorMsg('Service is required')}
</Field>
<Field>
<label className="tw-block " htmlFor="ingestionType">
{requiredField('Type of ingestion:')}
</label>
<select
className={classNames('tw-form-inputs tw-px-3 tw-py-1', {
'tw-cursor-not-allowed': !ingestionService,
})}
data-testid="ingestion-type"
disabled={!ingestionService || isUpdating}
id="ingestionType"
name="ingestionType"
value={ingestionType}
onChange={handleValidation}>
<option value="">Select ingestion type</option>
{(
getIngestionTypeList(ingestionService?.split('$$')?.[0]) || []
).map((service, index) => (
<option key={index} value={service}>
{service}
</option>
))}
</select>
{showErrorMsg.ingestionType &&
errorMsg('Ingestion Type is required')}
{showErrorMsg.isPipelineExists &&
errorMsg(
`Ingestion with service ${getServiceName(
ingestionService
)} and ingestion-type ${ingestionType} already exists `
)}
</Field>
</Fragment>
);
case 1: case 1:
return ( return (
<Fragment> <Fragment>
@ -360,17 +235,16 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
{requiredField('Name:')} {requiredField('Name:')}
</label> </label>
<input <input
className={classNames('tw-form-inputs tw-px-3 tw-py-1', { disabled
'tw-cursor-not-allowed': isUpdating, className={classNames(
})} 'tw-form-inputs tw-px-3 tw-py-1 tw-cursor-not-allowed'
)}
data-testid="name" data-testid="name"
id="name" id="name"
name="name" name="name"
placeholder="Ingestion name" placeholder="Ingestion name"
readOnly={isUpdating}
type="text" type="text"
value={ingestionName} value={ingestionName}
onChange={handleValidation}
/> />
{showErrorMsg.name && errorMsg('Ingestion Name is required')} {showErrorMsg.name && errorMsg('Ingestion Name is required')}
{showErrorMsg.isPipelineNameExists && {showErrorMsg.isPipelineNameExists &&
@ -400,12 +274,6 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
</select> </select>
{showErrorMsg.ingestionType && {showErrorMsg.ingestionType &&
errorMsg('Ingestion Type is required')} errorMsg('Ingestion Type is required')}
{showErrorMsg.isPipelineExists &&
errorMsg(
`Ingestion with service ${getServiceName(
ingestionService
)} and ingestion-type ${ingestionType} already exists `
)}
</Field> </Field>
<Field> <Field>
@ -679,27 +547,6 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
}; };
const onSaveHandler = (triggerIngestion = false) => { const onSaveHandler = (triggerIngestion = false) => {
// const ingestionData = {
// ingestionType: ingestionType,
// displayName: ingestionName,
// name: getIngestionName(ingestionName),
// service: { name: getServiceName(ingestionService), id: '', type: '' },
// startDate: startDate || getCurrentDate(),
// endDate: endDate || '',
// scheduleInterval: ingestionSchedule,
// forceDeploy: true,
// connectorConfig: {
// database: database,
// enableDataProfiler: excludeDataProfiler,
// excludeFilterPattern: excludeFilterPattern,
// host: host,
// includeFilterPattern: includeFilterPattern,
// includeViews: includeViews,
// password: password,
// username: username,
// },
// };
const ingestionObj: AirflowPipeline = { const ingestionObj: AirflowPipeline = {
name: ingestionName, name: ingestionName,
pipelineConfig: { pipelineConfig: {
@ -762,7 +609,7 @@ const IngestionModal: React.FC<IngestionModalProps> = ({
// isPipelineExists: isPipelineExists(), // isPipelineExists: isPipelineExists(),
isPipelineNameExists: isPipeLineNameExists(), isPipelineNameExists: isPipeLineNameExists(),
}); });
}, [ingestionType, ingestionService, ingestionName]); }, [ingestionType, ingestionName]);
useEffect(() => { useEffect(() => {
if (endDate) { if (endDate) {

View File

@ -23,6 +23,7 @@ import React, {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { ONLY_NUMBER_REGEX } from '../../../constants/constants';
import { serviceTypes } from '../../../constants/services.const'; import { serviceTypes } from '../../../constants/services.const';
import { import {
DashboardServiceType, DashboardServiceType,
@ -37,6 +38,7 @@ import {
import { DatabaseService } from '../../../generated/entity/services/databaseService'; import { DatabaseService } from '../../../generated/entity/services/databaseService';
import { MessagingService } from '../../../generated/entity/services/messagingService'; import { MessagingService } from '../../../generated/entity/services/messagingService';
import { PipelineService } from '../../../generated/entity/services/pipelineService'; import { PipelineService } from '../../../generated/entity/services/pipelineService';
import { PipelineType } from '../../../generated/operations/pipelines/airflowPipeline';
import { useAuth } from '../../../hooks/authHooks'; import { useAuth } from '../../../hooks/authHooks';
import { import {
errorMsg, errorMsg,
@ -146,6 +148,7 @@ type ErrorMsg = {
selectService: boolean; selectService: boolean;
name: boolean; name: boolean;
url?: boolean; url?: boolean;
port?: boolean;
driverClass?: boolean; driverClass?: boolean;
broker?: boolean; broker?: boolean;
dashboardUrl?: boolean; dashboardUrl?: boolean;
@ -296,7 +299,12 @@ export const AddServiceModal: FunctionComponent<Props> = ({
const [existingNames] = useState(generateName(serviceList)); const [existingNames] = useState(generateName(serviceList));
const [selectService, setSelectService] = useState(data?.serviceType || ''); const [selectService, setSelectService] = useState(data?.serviceType || '');
const [name, setName] = useState(data?.name || ''); const [name, setName] = useState(data?.name || '');
const [url, setUrl] = useState(data?.databaseConnection?.hostPort || ''); const [url, setUrl] = useState(
data?.databaseConnection?.hostPort.split(':')[0] || ''
);
const [port, setPort] = useState(
data?.databaseConnection?.hostPort.split(':')[1] || ''
);
const [database, setDatabase] = useState( const [database, setDatabase] = useState(
data?.databaseConnection?.database || '' data?.databaseConnection?.database || ''
); );
@ -329,6 +337,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
selectService: false, selectService: false,
name: false, name: false,
url: false, url: false,
port: false,
driverClass: false, driverClass: false,
broker: false, broker: false,
dashboardUrl: false, dashboardUrl: false,
@ -386,6 +395,14 @@ export const AddServiceModal: FunctionComponent<Props> = ({
case 'name': case 'name':
setName(value); setName(value);
setIngestionTypeList(
ingestionTypeList?.map((d) => {
return {
...d,
ingestionName: `${value}_${PipelineType.Metadata}`,
};
})
);
break; break;
@ -394,6 +411,13 @@ export const AddServiceModal: FunctionComponent<Props> = ({
break; break;
case 'port':
if (ONLY_NUMBER_REGEX.test(value) || value === '') {
setPort(value);
}
break;
default: default:
break; break;
} }
@ -452,7 +476,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
dataObj = { dataObj = {
...dataObj, ...dataObj,
databaseConnection: { databaseConnection: {
hostPort: url, hostPort: `${url}:${port}`,
connectionArguments: getKeyValueObject(connectionArguments), connectionArguments: getKeyValueObject(connectionArguments),
connectionOptions: getKeyValueObject(connectionOptions), connectionOptions: getKeyValueObject(connectionOptions),
database: database, database: database,
@ -556,7 +580,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
generateSampleData: value.ingestSampleData, generateSampleData: value.ingestSampleData,
enableDataProfiler: value.enableDataProfiler, enableDataProfiler: value.enableDataProfiler,
schemaFilterPattern: schemaFilterPattern:
!isEmpty(schemaIncludePattern) && !isEmpty(schemaIncludePattern) ||
!isEmpty(schemaExcludePattern) !isEmpty(schemaExcludePattern)
? { ? {
includes: !isEmpty(schemaIncludePattern) includes: !isEmpty(schemaIncludePattern)
@ -572,7 +596,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
} }
: undefined, : undefined,
tableFilterPattern: tableFilterPattern:
!isEmpty(tableIncludePattern) && !isEmpty(tableIncludePattern) ||
!isEmpty(tableExcludePattern) !isEmpty(tableExcludePattern)
? { ? {
includes: !isEmpty(tableIncludePattern) includes: !isEmpty(tableIncludePattern)
@ -625,10 +649,11 @@ export const AddServiceModal: FunctionComponent<Props> = ({
setMsg = { setMsg = {
...setMsg, ...setMsg,
url: !url, url: !url,
port: !port,
}; };
} }
isValid = Boolean(url); isValid = Boolean(url && port);
break; break;
case ServiceCategory.MESSAGING_SERVICES: case ServiceCategory.MESSAGING_SERVICES:
@ -759,21 +784,37 @@ export const AddServiceModal: FunctionComponent<Props> = ({
return ( return (
<> <>
<div className="tw-mt-4 tw-grid tw-grid-cols-3 tw-gap-2 "> <div className="tw-mt-4 tw-grid tw-grid-cols-3 tw-gap-2 ">
<div className="tw-col-span-3"> <div className="tw-col-span-2">
<label className="tw-block tw-form-label" htmlFor="url"> <label className="tw-block tw-form-label" htmlFor="url">
{requiredField('Host Port:')} {requiredField('Host:')}
</label> </label>
<input <input
className="tw-form-inputs tw-px-3 tw-py-1" className="tw-form-inputs tw-px-3 tw-py-1"
data-testid="url" data-testid="url"
id="url" id="url"
name="url" name="url"
placeholder="http(s)://hostname:port" placeholder="hostname"
type="text" type="text"
value={url} value={url}
onChange={handleValidation} onChange={handleValidation}
/> />
{showErrorMsg.url && errorMsg('Host port is required')} {showErrorMsg.url && errorMsg('Host name is required')}
</div>
<div className="">
<label className="tw-block tw-form-label" htmlFor="port">
{requiredField('Port:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
data-testid="port"
id="port"
name="port"
placeholder="port"
type="text"
value={port}
onChange={handleValidation}
/>
{showErrorMsg.port && errorMsg('Port is required')}
</div> </div>
</div> </div>
<Field> <Field>
@ -1271,9 +1312,13 @@ export const AddServiceModal: FunctionComponent<Props> = ({
case ServiceCategory.DATABASE_SERVICES: case ServiceCategory.DATABASE_SERVICES:
data = [ data = [
{ {
key: 'Host Port', key: 'Host',
value: url, value: url,
}, },
{
key: 'Port',
value: port,
},
]; ];
if (username) { if (username) {
@ -1553,7 +1598,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
if (ingestionTypeList) { if (ingestionTypeList) {
let noErrorListCount = 0; let noErrorListCount = 0;
const newFormValue = ingestionTypeList.map((value) => { const newFormValue = ingestionTypeList.map((value) => {
if (isEmpty(value.ingestionName)) { if (isEmpty(value.ingestionName) && value.isIngestionActive) {
isValid = false; isValid = false;
return { return {
@ -1707,11 +1752,9 @@ export const AddServiceModal: FunctionComponent<Props> = ({
{requiredField('Ingestion name:')} {requiredField('Ingestion name:')}
</label> </label>
<input <input
disabled
className={classNames( className={classNames(
'tw-form-inputs tw-px-3 tw-py-1', 'tw-form-inputs tw-px-3 tw-py-1 tw-cursor-not-allowed'
{
'tw-cursor-not-allowed': false,
}
)} )}
data-testid="ingestionName" data-testid="ingestionName"
id="ingestionName" id="ingestionName"
@ -1719,18 +1762,11 @@ export const AddServiceModal: FunctionComponent<Props> = ({
placeholder="Ingestion name" placeholder="Ingestion name"
type="text" type="text"
value={type.ingestionName} value={type.ingestionName}
onChange={(e) => {
const newFormValues = [...ingestionTypeList];
newFormValues[id].ingestionName = e.target.value;
newFormValues[id].showError = Boolean(e.target.value);
setIngestionTypeList(newFormValues);
}}
/> />
{type.showError && {type.showError &&
type.isIngestionActive &&
isEmpty(type.ingestionName) && isEmpty(type.ingestionName) &&
errorMsg('Ingestion Name is required')} errorMsg('Ingestion Name is required')}
{/* {showErrorMsg.isPipelineNameExists &&
errorMsg(`Ingestion with similar name already exists.`)} */}
</Field> </Field>
<Field> <Field>
{getSeparator('Table Filter Pattern')} {getSeparator('Table Filter Pattern')}
@ -1994,9 +2030,9 @@ export const AddServiceModal: FunctionComponent<Props> = ({
{Boolean(ingestionTypeList && ingestionTypeList.length) && ( {Boolean(ingestionTypeList && ingestionTypeList.length) && (
<Fragment> <Fragment>
{ingestionTypeList?.map((value) => { {ingestionTypeList?.map((value, i) => {
return value.isIngestionActive ? ( return value.isIngestionActive ? (
<> <Fragment key={i}>
<PreviewSection <PreviewSection
className="tw-mb-4 tw-mt-4" className="tw-mb-4 tw-mt-4"
data={[ data={[
@ -2082,10 +2118,8 @@ export const AddServiceModal: FunctionComponent<Props> = ({
header="Schema Filter Patterns" header="Schema Filter Patterns"
/> />
)} )}
</> </Fragment>
) : ( ) : null;
<></>
);
})} })}
</Fragment> </Fragment>
)} )}

View File

@ -39,7 +39,7 @@ const Description = ({
owner, owner,
hasEditAccess, hasEditAccess,
onDescriptionEdit, onDescriptionEdit,
description, description = '',
isEdit, isEdit,
onCancel, onCancel,
onDescriptionUpdate, onDescriptionUpdate,

View File

@ -51,6 +51,8 @@ const PLACEHOLDER_ROUTE_ENTITY_FQN = ':entityFQN';
export const pagingObject = { after: '', before: '' }; export const pagingObject = { after: '', before: '' };
export const ONLY_NUMBER_REGEX = /^[0-9\b]+$/;
/* eslint-disable @typescript-eslint/camelcase */ /* eslint-disable @typescript-eslint/camelcase */
export const tiers = [ export const tiers = [
{ key: 'Tier.Tier1', doc_count: 0 }, { key: 'Tier.Tier1', doc_count: 0 },

View File

@ -65,7 +65,6 @@ import { EntityReference } from '../../generated/type/entityReference';
import useToastContext from '../../hooks/useToastContext'; import useToastContext from '../../hooks/useToastContext';
import { isEven } from '../../utils/CommonUtils'; import { isEven } from '../../utils/CommonUtils';
import { import {
getFrequencyTime,
getIsIngestionEnable, getIsIngestionEnable,
getServiceCategoryFromType, getServiceCategoryFromType,
serviceTypeLogo, serviceTypeLogo,
@ -108,9 +107,23 @@ const ServicePage: FunctionComponent = () => {
const [ingestionPaging, setIngestionPaging] = useState<Paging>({} as Paging); const [ingestionPaging, setIngestionPaging] = useState<Paging>({} as Paging);
const showToast = useToastContext(); const showToast = useToastContext();
const getCountLabel = () => {
switch (serviceName) {
case ServiceCategory.DASHBOARD_SERVICES:
return 'Dashboards';
case ServiceCategory.MESSAGING_SERVICES:
return 'Topics';
case ServiceCategory.PIPELINE_SERVICES:
return 'Pipelines';
case ServiceCategory.DATABASE_SERVICES:
default:
return 'Databases';
}
};
const tabs = [ const tabs = [
{ {
name: 'Database', name: getCountLabel(),
icon: { icon: {
alt: 'schema', alt: 'schema',
name: 'icon-database', name: 'icon-database',
@ -119,6 +132,7 @@ const ServicePage: FunctionComponent = () => {
}, },
isProtected: false, isProtected: false,
position: 1, position: 1,
count: instanceCount,
}, },
{ {
name: 'Ingestions', name: 'Ingestions',
@ -131,6 +145,7 @@ const ServicePage: FunctionComponent = () => {
isHidden: !isIngestionEnable, isHidden: !isIngestionEnable,
isProtected: false, isProtected: false,
position: 2, position: 2,
count: ingestions.length,
}, },
]; ];
@ -152,7 +167,7 @@ const ServicePage: FunctionComponent = () => {
}; };
const getAllIngestionWorkflows = (paging?: string) => { const getAllIngestionWorkflows = (paging?: string) => {
getAirflowPipelines(['owner, tags, status'], serviceName, paging) getAirflowPipelines(['owner, tags, status'], serviceFQN, paging)
.then((res) => { .then((res) => {
if (res.data.data) { if (res.data.data) {
setIngestions(res.data.data); setIngestions(res.data.data);
@ -412,19 +427,6 @@ const ServicePage: FunctionComponent = () => {
const getOptionalFields = (): JSX.Element => { const getOptionalFields = (): JSX.Element => {
switch (serviceName) { switch (serviceName) {
case ServiceCategory.DATABASE_SERVICES: {
return (
<span>
<span className="tw-text-grey-muted tw-font-normal">
Driver Class :
</span>{' '}
<span className="tw-pl-1tw-font-normal ">
{serviceDetails?.jdbc?.driverClass || '--'}
</span>
<span className="tw-mx-3 tw-text-grey-muted"></span>
</span>
);
}
case ServiceCategory.MESSAGING_SERVICES: { case ServiceCategory.MESSAGING_SERVICES: {
return ( return (
<> <>
@ -613,6 +615,7 @@ const ServicePage: FunctionComponent = () => {
</span> </span>
); );
case ServiceCategory.DATABASE_SERVICES:
default: { default: {
return <></>; return <></>;
} }
@ -841,20 +844,6 @@ const ServicePage: FunctionComponent = () => {
getAllIngestionWorkflows(pagingString); getAllIngestionWorkflows(pagingString);
}; };
const getCountLabel = () => {
switch (serviceName) {
case ServiceCategory.DASHBOARD_SERVICES:
return 'Dashboards';
case ServiceCategory.MESSAGING_SERVICES:
return 'Topics';
case ServiceCategory.PIPELINE_SERVICES:
return 'Pipelines';
case ServiceCategory.DATABASE_SERVICES:
default:
return 'Databases';
}
};
return ( return (
<> <>
{isLoading ? ( {isLoading ? (
@ -866,7 +855,7 @@ const ServicePage: FunctionComponent = () => {
<div className="tw-flex tw-gap-1 tw-mb-2 tw-mt-1 tw-ml-7"> <div className="tw-flex tw-gap-1 tw-mb-2 tw-mt-1 tw-ml-7">
{getOptionalFields()} {getOptionalFields()}
<span> {/* <span>
<span className="tw-text-grey-muted tw-font-normal"> <span className="tw-text-grey-muted tw-font-normal">
Ingestion : Ingestion :
</span>{' '} </span>{' '}
@ -885,7 +874,7 @@ const ServicePage: FunctionComponent = () => {
{getCountLabel()} : {getCountLabel()} :
</span>{' '} </span>{' '}
<span className="tw-pl-1 tw-font-normal">{instanceCount}</span> <span className="tw-pl-1 tw-font-normal">{instanceCount}</span>
</span> </span> */}
</div> </div>
<div <div
@ -992,6 +981,7 @@ const ServicePage: FunctionComponent = () => {
paging={ingestionPaging} paging={ingestionPaging}
pagingHandler={ingestionPagingHandler} pagingHandler={ingestionPagingHandler}
serviceList={serviceList} serviceList={serviceList}
serviceName={serviceFQN}
serviceType={serviceDetails?.serviceType} serviceType={serviceDetails?.serviceType}
triggerIngestion={triggerIngestionById} triggerIngestion={triggerIngestionById}
updateIngestion={updateIngestion} updateIngestion={updateIngestion}

View File

@ -58,6 +58,7 @@ import {
import { DatabaseService } from '../../generated/entity/services/databaseService'; import { DatabaseService } from '../../generated/entity/services/databaseService';
import { MessagingService } from '../../generated/entity/services/messagingService'; import { MessagingService } from '../../generated/entity/services/messagingService';
import { PipelineService } from '../../generated/entity/services/pipelineService'; import { PipelineService } from '../../generated/entity/services/pipelineService';
import { PipelineType } from '../../generated/operations/pipelines/airflowPipeline';
import { useAuth } from '../../hooks/authHooks'; import { useAuth } from '../../hooks/authHooks';
import useToastContext from '../../hooks/useToastContext'; import useToastContext from '../../hooks/useToastContext';
import { import {
@ -65,7 +66,6 @@ import {
getCountBadge, getCountBadge,
getServiceLogo, getServiceLogo,
} from '../../utils/CommonUtils'; } from '../../utils/CommonUtils';
import { getFrequencyTime } from '../../utils/ServiceUtils';
import SVGIcons from '../../utils/SvgUtils'; import SVGIcons from '../../utils/SvgUtils';
type ServiceRecord = { type ServiceRecord = {
@ -261,13 +261,23 @@ const ServicesPage = () => {
...ingestion.service, ...ingestion.service,
id: serviceId, id: serviceId,
}, },
pipelineType: PipelineType.Metadata,
}); });
}); });
Promise.allSettled(promises).then(() => { Promise.allSettled(promises).then(
(response: PromiseSettledResult<AxiosResponse>[]) => {
response.map((data) => {
data.status === 'rejected' &&
showToast({
variant: 'error',
body: data.reason || 'Something went wrong!',
});
});
setIsModalOpen(false); setIsModalOpen(false);
setEditData(undefined); setEditData(undefined);
}); }
);
} else { } else {
setIsModalOpen(false); setIsModalOpen(false);
setEditData(undefined); setEditData(undefined);
@ -551,18 +561,7 @@ const ServicesPage = () => {
)} )}
</div> </div>
{getOptionalFields(service)} {getOptionalFields(service)}
<div
className="tw-mb-1"
data-testid="service-ingestion">
<label className="tw-mb-0">Ingestion:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.ingestionSchedule?.repeatFrequency
? getFrequencyTime(
service.ingestionSchedule.repeatFrequency
)
: '--'}
</span>
</div>
<div className="" data-testid="service-type"> <div className="" data-testid="service-type">
<label className="tw-mb-0">Type:</label> <label className="tw-mb-0">Type:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body"> <span className=" tw-ml-1 tw-font-normal tw-text-grey-body">