Added UI for Messaging services (#290)

* Added UI tabs for different services

* Integrated apis and added icons for messaging services
This commit is contained in:
darth-coder00 2021-08-27 16:31:20 +05:30 committed by GitHub
parent 5703a69e8c
commit 8d27ca7ef5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 443 additions and 220 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -16,13 +16,16 @@
*/
import classNames from 'classnames';
import React, { FunctionComponent, useRef, useState } from 'react';
import { ServiceTypes } from 'Models';
import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
import { serviceTypes } from '../../../constants/services.const';
import { ServiceCategory } from '../../../enums/service.enum';
import { fromISOString } from '../../../utils/ServiceUtils';
import { Button } from '../../buttons/Button/Button';
import MarkdownWithPreview from '../../common/editor/MarkdownWithPreview';
// import { serviceType } from '../../../constants/services.const';
export type DatabaseObj = {
export type DataObj = {
description: string | undefined;
ingestionSchedule:
| {
@ -30,25 +33,36 @@ export type DatabaseObj = {
startDate: string;
}
| undefined;
jdbc: {
name: string;
serviceType: string;
jdbc?: {
connectionUrl: string;
driverClass: string;
};
name: string;
serviceType: string;
brokers?: Array<string>;
schemaRegistry?: string;
};
type DatabaseService = {
connectionUrl: string;
driverClass: string;
jdbc: { driverClass: string; connectionUrl: string };
};
type MessagingService = {
brokers: Array<string>;
schemaRegistry: string;
};
export type ServiceDataObj = {
connectionUrl: string;
description: string;
driverClass: string;
href: string;
id: string;
jdbc: { driverClass: string; connectionUrl: string };
name: string;
serviceType: string;
ingestionSchedule?: { repeatFrequency: string; startDate: string };
};
} & Partial<DatabaseService> &
Partial<MessagingService>;
export type EditObj = {
edit: boolean;
@ -57,21 +71,22 @@ export type EditObj = {
type Props = {
header: string;
serviceName: string;
serviceName: ServiceTypes;
serviceList: Array<ServiceDataObj>;
data?: ServiceDataObj;
onSave: (obj: DatabaseObj, text: string, editData: EditObj) => void;
onSave: (obj: DataObj, text: string, editData: EditObj) => void;
onCancel: () => void;
};
type ErrorMsg = {
selectService: boolean;
name: boolean;
url: boolean;
url?: boolean;
// port: boolean;
// userName: boolean;
// password: boolean;
driverClass: boolean;
driverClass?: boolean;
broker?: boolean;
};
type EditorContentRef = {
getEditorContent: () => string;
@ -137,15 +152,9 @@ export const AddServiceModal: FunctionComponent<Props> = ({
serviceList,
}: Props) => {
const [editData] = useState({ edit: !!data, id: data?.id });
const [serviceType] = useState([
'BigQuery',
'MySQL',
'Redshift',
'Snowflake',
'Postgres',
'MSSQL',
'Hive',
]);
const [serviceType, setServiceType] = useState(
serviceTypes[serviceName] || []
);
const [parseUrl] = useState(seprateUrl(data?.connectionUrl) || {});
const [existingNames] = useState(generateName(serviceList));
const [ingestion, setIngestion] = useState(!!data?.ingestionSchedule);
@ -158,10 +167,16 @@ export const AddServiceModal: FunctionComponent<Props> = ({
// const [port, setPort] = useState(parseUrl?.port || '');
const [database, setDatabase] = useState(parseUrl?.database || '');
const [driverClass, setDriverClass] = useState(data?.driverClass || 'jdbc');
const [broker, setBroker] = useState(
data?.brokers?.length ? data.brokers[0] : ''
);
const [schemaRegistry, setSchemaRegistry] = useState(
data?.schemaRegistry || ''
);
const [frequency, setFrequency] = useState(
fromISOString(data?.ingestionSchedule?.repeatFrequency)
);
const [showErrorMsg, setShowErrorMsg] = useState({
const [showErrorMsg, setShowErrorMsg] = useState<ErrorMsg>({
selectService: false,
name: false,
url: false,
@ -169,6 +184,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
// userName: false,
// password: false,
driverClass: false,
broker: false,
});
const [sameNameError, setSameNameError] = useState(false);
const markdownRef = useRef<EditorContentRef>();
@ -235,7 +251,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
};
const onSaveHelper = (value: ErrorMsg) => {
const { selectService, name, url, driverClass } = value;
const { selectService, name, url, driverClass, broker } = value;
return (
!sameNameError &&
@ -245,25 +261,47 @@ export const AddServiceModal: FunctionComponent<Props> = ({
// !port &&
// !userName &&
// !password &&
!driverClass
!driverClass &&
!broker
);
};
const handleSave = () => {
const setMsg = {
let setMsg: ErrorMsg = {
selectService: !selectService,
name: !name,
url: !url,
// port: !port,
// userName: !userName,
// password: !password,
driverClass: !driverClass,
};
switch (serviceName) {
case ServiceCategory.DATABASE_SERVICES:
{
setMsg = {
...setMsg,
url: !url,
// port: !port,
// userName: !userName,
// password: !password,
driverClass: !driverClass,
};
}
break;
case ServiceCategory.MESSAGING_SERVICES:
{
setMsg = {
...setMsg,
broker: !broker,
};
}
break;
default:
break;
}
setShowErrorMsg(setMsg);
if (onSaveHelper(setMsg)) {
const { day, hour, minute } = frequency;
const date = new Date();
const databaseObj: DatabaseObj = {
let dataObj: DataObj = {
description: markdownRef.current?.getEditorContent(),
ingestionSchedule: ingestion
? {
@ -271,37 +309,201 @@ export const AddServiceModal: FunctionComponent<Props> = ({
startDate: date.toISOString(),
}
: undefined,
jdbc: {
connectionUrl: `${url}${database && '/' + database}`,
driverClass: driverClass,
},
name: name,
serviceType: selectService,
};
onSave(databaseObj, serviceName, editData);
switch (serviceName) {
case ServiceCategory.DATABASE_SERVICES:
{
dataObj = {
...dataObj,
jdbc: {
connectionUrl: `${url}${database && '/' + database}`,
driverClass: driverClass,
},
};
}
break;
case ServiceCategory.MESSAGING_SERVICES:
{
dataObj = {
...dataObj,
brokers: [broker],
schemaRegistry: schemaRegistry,
};
}
break;
default:
break;
}
onSave(dataObj, serviceName, editData);
}
};
const getDatabaseFields = (): JSX.Element => {
return (
<>
<div className="tw-mt-4 tw-grid tw-grid-cols-3 tw-gap-2 ">
<div className="tw-col-span-3">
<label className="tw-block tw-form-label" htmlFor="url">
{requiredField('Connection Url:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="url"
name="url"
type="text"
value={url}
onChange={handleValidation}
/>
{showErrorMsg.url && errorMsg('Connection url is required')}
</div>
{/* didn't removed below code as it will be need in future relase */}
{/* <div>
<label className="tw-block tw-form-label" htmlFor="port">
{requiredField('Connection Port:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="port"
name="port"
type="number"
value={port}
onChange={handleValidation}
/>
{showErrorMsg.port && errorMsg('Port is required')}
</div> */}
</div>
{/* <div className="tw-mt-4 tw-grid tw-grid-cols-2 tw-gap-2 ">
<div>
<label className="tw-block tw-form-label" htmlFor="userName">
{requiredField('Username:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="userName"
name="userName"
type="text"
value={userName}
onChange={handleValidation}
/>
{showErrorMsg.userName && errorMsg('Username is required')}
</div>
<div>
<label className="tw-block tw-form-label" htmlFor="password">
{requiredField('Password:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="password"
name="password"
type="password"
value={password}
onChange={handleValidation}
/>
{showErrorMsg.password && errorMsg('Password is required')}
</div>
</div> */}
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="database">
Database:
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="database"
name="database"
type="text"
value={database}
onChange={(e) => setDatabase(e.target.value)}
/>
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="driverClass">
{requiredField('Driver Class:')}
</label>
{!editData.edit ? (
<select
className="tw-form-inputs tw-px-3 tw-py-1"
id="driverClass"
name="driverClass"
value={driverClass}
onChange={handleValidation}>
<option value="jdbc">jdbc</option>
</select>
) : (
<input
disabled
className="tw-form-inputs tw-px-3 tw-py-1 tw-cursor-not-allowed"
id="driverClass"
name="driverClass"
value={driverClass}
/>
)}
{showErrorMsg.driverClass && errorMsg('Driver class is required')}
</div>
</>
);
};
const getMessagingFields = (): JSX.Element => {
return (
<>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="broker">
{requiredField('Broker Url:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="broker"
name="broker"
type="text"
value={broker}
onChange={(e) => setBroker(e.target.value)}
/>
{showErrorMsg.broker && errorMsg('Broker url is required')}
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="schema-registry">
Schema Registry:
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="schema-registry"
name="schema-registry"
type="text"
value={schemaRegistry}
onChange={(e) => setSchemaRegistry(e.target.value)}
/>
</div>
</>
);
};
const getOptionalFields = (): JSX.Element => {
switch (serviceName) {
case ServiceCategory.DATABASE_SERVICES:
return getDatabaseFields();
case ServiceCategory.MESSAGING_SERVICES:
return getMessagingFields();
default:
return <></>;
}
};
useEffect(() => {
setServiceType(serviceTypes[serviceName] || []);
}, [serviceName]);
return (
<dialog className="tw-modal">
<div className="tw-modal-backdrop" />
<div className="tw-modal-container tw-max-w-lg">
<div className="tw-modal-header">
<p className="tw-modal-title">{header}</p>
<svg
className="tw-w-6 tw-h-6 tw-cursor-pointer"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
onClick={onCancel}>
<path
d="M6 18L18 6M6 6l12 12"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</div>
<div className="tw-modal-body">
<form className="tw-min-w-full">
@ -360,106 +562,7 @@ export const AddServiceModal: FunctionComponent<Props> = ({
{showErrorMsg.name && errorMsg('Service name is required.')}
{sameNameError && errorMsg('Service name already exist.')}
</div>
<div className="tw-mt-4 tw-grid tw-grid-cols-3 tw-gap-2 ">
<div className="tw-col-span-3">
<label className="tw-block tw-form-label" htmlFor="url">
{requiredField('Connection Url:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="url"
name="url"
type="text"
value={url}
onChange={handleValidation}
/>
{showErrorMsg.url && errorMsg('Connection url is required')}
</div>
{/* didn't removed below code as it will be need in future relase */}
{/* <div>
<label className="tw-block tw-form-label" htmlFor="port">
{requiredField('Connection Port:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="port"
name="port"
type="number"
value={port}
onChange={handleValidation}
/>
{showErrorMsg.port && errorMsg('Port is required')}
</div> */}
</div>
{/* <div className="tw-mt-4 tw-grid tw-grid-cols-2 tw-gap-2 ">
<div>
<label className="tw-block tw-form-label" htmlFor="userName">
{requiredField('Username:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="userName"
name="userName"
type="text"
value={userName}
onChange={handleValidation}
/>
{showErrorMsg.userName && errorMsg('Username is required')}
</div>
<div>
<label className="tw-block tw-form-label" htmlFor="password">
{requiredField('Password:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="password"
name="password"
type="password"
value={password}
onChange={handleValidation}
/>
{showErrorMsg.password && errorMsg('Password is required')}
</div>
</div> */}
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="database">
Database:
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="database"
name="database"
type="text"
value={database}
onChange={(e) => setDatabase(e.target.value)}
/>
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="driverClass">
{requiredField('Driver Class:')}
</label>
{!editData.edit ? (
<select
className="tw-form-inputs tw-px-3 tw-py-1"
id="driverClass"
name="driverClass"
value={driverClass}
onChange={handleValidation}>
<option value="jdbc">jdbc</option>
</select>
) : (
<input
disabled
className="tw-form-inputs tw-px-3 tw-py-1 tw-cursor-not-allowed"
id="driverClass"
name="driverClass"
value={driverClass}
/>
)}
{showErrorMsg.driverClass && errorMsg('Driver class is required')}
</div>
{getOptionalFields()}
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="description">
Description:
@ -469,23 +572,6 @@ export const AddServiceModal: FunctionComponent<Props> = ({
value={data?.description || ''}
/>
</div>
{/* <div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="tags">
Tags:
</label>
<select
className="tw-form-inputs tw-px-3 tw-py-1 "
name="tags"
id="tags"
value={tags}
onChange={(e) => setTags(e.target.value)}>
<option value="">Select Tags</option>
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
</div> */}
<div className="tw-mt-4 tw-flex tw-items-center">
<label className="tw-form-label tw-mb-0">Enable Ingestion</label>
<div

View File

@ -15,12 +15,15 @@
* limitations under the License.
*/
import { ServiceTypes } from 'Models';
import noService from '../assets/img/no-service.png';
import serviceDefault from '../assets/img/service-icon-generic.png';
import hive from '../assets/img/service-icon-hive.png';
import kafka from '../assets/img/service-icon-kafka.png';
import mssql from '../assets/img/service-icon-mssql.png';
import oracle from '../assets/img/service-icon-oracle.png';
import postgres from '../assets/img/service-icon-post.png';
import pulsar from '../assets/img/service-icon-pulsar.png';
import query from '../assets/img/service-icon-query.png';
import redshift from '../assets/img/service-icon-redshift.png';
import snowflakes from '../assets/img/service-icon-snowflakes.png';
@ -35,17 +38,32 @@ export const HIVE = hive;
export const POSTGRES = postgres;
export const ORACLE = oracle;
export const SNOWFLAKE = snowflakes;
export const KAFKA = kafka;
export const PULSAR = pulsar;
export const SERVICE_DEFAULT = serviceDefault;
export const PLUS = plus;
export const NOSERVICE = noService;
export const serviceType = [
'MySQL',
'Postgres',
'Redshift',
'BigQuery',
'Hive',
'Oracle',
'Snowflake',
export const serviceTypes: Record<ServiceTypes, Array<string>> = {
databaseServices: [
'BigQuery',
'MySQL',
'Redshift',
'Snowflake',
'Postgres',
'MSSQL',
'Hive',
],
messagingServices: ['Kafka', 'Pulsar'],
};
export const arrServiceTypes: Array<ServiceTypes> = [
'databaseServices',
'messagingServices',
];
export const servicesDisplayName = {
databaseServices: 'Database Service',
messagingServices: 'Messaging Service',
};

View File

@ -15,7 +15,12 @@
* limitations under the License.
*/
export enum ServiceType {
export enum ServiceCategory {
DATABASE_SERVICES = 'databaseServices',
MESSAGING_SERVICES = 'messagingServices',
}
export enum DatabaseServiceType {
MYSQL = 'MySQL',
REDSHIFT = 'Redshift',
BIGQUERY = 'BigQuery',
@ -25,3 +30,8 @@ export enum ServiceType {
SNOWFLAKE = 'Snowflake',
MSSQL = 'MSSQL',
}
export enum MessagingServiceType {
KAFKA = 'Kafka',
PULSAR = 'Pulsar',
}

View File

@ -313,6 +313,10 @@ declare module 'Models' {
};
};
export type ServiceTypes = 'databaseServices' | 'messagingServices';
export type ServiceRecord = Record<ServiceTypes, Array<ServiceDataObj>>;
export type SampleData = {
columns: Array<string>;
rows: Array<Array<string>>;

View File

@ -17,7 +17,12 @@
import { AxiosResponse } from 'axios';
import { isNull } from 'lodash';
import { ServiceCollection, ServiceData } from 'Models';
import {
ServiceCollection,
ServiceData,
ServiceRecord,
ServiceTypes,
} from 'Models';
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import {
@ -32,12 +37,19 @@ import PageContainer from '../../components/containers/PageContainer';
import Loader from '../../components/Loader/Loader';
import {
AddServiceModal,
DatabaseObj,
DataObj,
EditObj,
ServiceDataObj,
} from '../../components/Modals/AddServiceModal/AddServiceModal';
import { getServiceDetailsPath } from '../../constants/constants';
import { NOSERVICE, PLUS } from '../../constants/services.const';
import {
arrServiceTypes,
NOSERVICE,
PLUS,
servicesDisplayName,
} from '../../constants/services.const';
import { ServiceCategory } from '../../enums/service.enum';
import { getTabClasses } from '../../utils/CommonUtils';
import { getFrequencyTime, serviceTypeLogo } from '../../utils/ServiceUtils';
import SVGIcons from '../../utils/SvgUtils';
@ -53,7 +65,12 @@ export type ApiData = {
const ServicesPage = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [serviceName] = useState('databaseServices');
const [serviceName, setServiceName] =
useState<ServiceTypes>('databaseServices');
const [services, setServices] = useState<ServiceRecord>({
databaseServices: [],
messagingServices: [],
});
const [serviceList, setServiceList] = useState<Array<ServiceDataObj>>([]);
const [editData, setEditData] = useState<ServiceDataObj>();
const [isLoading, setIsLoading] = useState<boolean>(false);
@ -61,7 +78,7 @@ const ServicesPage = () => {
const updateServiceList = (
allServiceCollectionArr: Array<ServiceCollection>
) => {
let listArr = [];
// let listArr = [];
// fetch services of all individual collection
if (allServiceCollectionArr.length) {
let promiseArr = [];
@ -71,16 +88,24 @@ const ServicesPage = () => {
Promise.all(promiseArr).then((result: AxiosResponse[]) => {
if (result.length) {
let serviceArr = [];
const serviceRecord = {} as ServiceRecord;
serviceArr = result.map((service) => service?.data?.data || []);
// converted array of arrays to array
const allServices = serviceArr.reduce(
(acc, el) => acc.concat(el),
[]
);
listArr = allServices.map((s: ApiData) => {
return { ...s, ...s.jdbc };
});
setServiceList(listArr);
for (let i = 0; i < serviceArr.length; i++) {
serviceRecord[allServiceCollectionArr[i].value as ServiceTypes] =
serviceArr[i].map((s: ApiData) => {
return { ...s, ...s.jdbc };
});
}
// // converted array of arrays to array
// const allServices = serviceArr.reduce(
// (acc, el) => acc.concat(el),
// []
// );
// listArr = allServices.map((s: ApiData) => {
// return { ...s, ...s.jdbc };
// });
setServices(serviceRecord);
setServiceList(serviceRecord[serviceName]);
}
});
}
@ -103,36 +128,43 @@ const ServicesPage = () => {
const handleUpdate = (
selectedService: string,
id: string,
dataObj: DatabaseObj
dataObj: DataObj
) => {
updateService(selectedService, id, dataObj).then(
({ data }: { data: AxiosResponse['data'] }) => {
const updatedData = {
...data,
...data.jdbc,
...data.brokers,
...data.schemaRegistry,
};
const updatedServiceList = serviceList.map((s) =>
s.id === updatedData.id ? updatedData : s
);
setServices({ ...services, [serviceName]: updatedServiceList });
setServiceList(updatedServiceList);
}
);
};
const handleAdd = (selectedService: string, dataObj: DatabaseObj) => {
const handleAdd = (selectedService: string, dataObj: DataObj) => {
postService(selectedService, dataObj).then(
({ data }: { data: AxiosResponse['data'] }) => {
const updatedData = {
...data,
...data.jdbc,
...data.brokers,
...data.schemaRegistry,
};
setServiceList([...serviceList, updatedData]);
const updatedServiceList = [...serviceList, updatedData];
setServices({ ...services, [serviceName]: updatedServiceList });
setServiceList(updatedServiceList);
}
);
};
const handleSave = (
dataObj: DatabaseObj,
dataObj: DataObj,
selectedService: string,
isEdit: EditObj
) => {
@ -149,6 +181,7 @@ const ServicesPage = () => {
deleteService(serviceName, id).then((res: AxiosResponse) => {
if (res.statusText === 'OK') {
const updatedServiceList = serviceList.filter((s) => s.id !== id);
setServices({ ...services, [serviceName]: updatedServiceList });
setServiceList(updatedServiceList);
}
});
@ -163,6 +196,54 @@ const ServicesPage = () => {
return null;
};
const getServiceTabs = (): Array<{
name: ServiceTypes;
displayName: string;
}> => {
const tabs = Object.keys(services);
return arrServiceTypes
.filter((item) => tabs.includes(item))
.map((type) => {
return {
name: type,
displayName: servicesDisplayName[type],
};
});
};
const getOptionalFields = (service: ServiceDataObj): JSX.Element => {
switch (serviceName) {
case ServiceCategory.DATABASE_SERVICES: {
return (
<>
<div className="tw-mb-1">
<label className="tw-mb-0">Driver Class:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.driverClass}
</span>
</div>
</>
);
}
case ServiceCategory.MESSAGING_SERVICES: {
return (
<>
<div className="tw-mb-1">
<label className="tw-mb-0">Brokers:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.brokers?.join(', ')}
</span>
</div>
</>
);
}
default: {
return <></>;
}
}
};
useEffect(() => {
// fetch all service collection
setIsLoading(true);
@ -188,6 +269,22 @@ const ServicesPage = () => {
{!isLoading ? (
<PageContainer>
<div className="container-fluid">
<div className="tw-bg-transparent tw-mb-4">
<nav className="tw-flex tw-flex-row tw-gh-tabs-container tw-px-4">
{getServiceTabs().map((tab, index) => (
<button
className={getTabClasses(tab.name, serviceName)}
data-testid="tab"
key={index}
onClick={() => {
setServiceName(tab.name);
setServiceList(services[tab.name]);
}}>
{tab.displayName}
</button>
))}
</nav>
</div>
{serviceList.length ? (
<div className="tw-grid tw-grid-cols-4 tw-gap-4">
{serviceList.map((service, index) => (
@ -213,19 +310,9 @@ const ServicesPage = () => {
</span>
)}
</div>
{/* <div className="tw-my-2">
<label className="tw-font-semibold ">Tags:</label>
<span className="tw-tag tw-ml-3">mysql</span>
<span className="tw-tag tw-ml-2">sales</span>
</div> */}
{getOptionalFields(service)}
<div className="tw-mb-1">
<label className="tw-mb-0">Driver Class:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.driverClass}
</span>
</div>
<div className="tw-mb-1">
<label className="tw-mb-0">Frequency:</label>
<label className="tw-mb-0">Ingestion:</label>
<span className=" tw-ml-1 tw-font-normal tw-text-grey-body">
{service.ingestionSchedule
? getFrequencyTime(
@ -275,8 +362,8 @@ const ServicesPage = () => {
className="tw-cursor-pointer tw-card tw-flex tw-flex-col tw-justify-center tw-items-center tw-py-2"
onClick={() => handleAddService()}>
<img alt="" src={PLUS} />
<p className="tw-text-base tw-font-normal tw-mt-1">
Add new service
<p className="tw-text-base tw-font-normal tw-mt-4">
Add new {servicesDisplayName[serviceName]}
</p>
</div>
</div>
@ -289,11 +376,11 @@ const ServicesPage = () => {
<p className="tw-text-lg">
No services found.{' '}
<button
className="tw-text-blue-700 tw-cursor-pointer tw-underline"
className="link-text tw-underline"
onClick={handleAddService}>
Click here
</button>{' '}
to add new services
to add new {servicesDisplayName[serviceName]}
</p>
</div>
</div>

View File

@ -84,3 +84,10 @@ export const getUserTeams = (): Array<UserTeam> => {
return retVal;
};
export const getTabClasses = (
tab: number | string,
activeTab: number | string
) => {
return 'tw-gh-tabs' + (activeTab === tab ? ' active' : '');
};

View File

@ -5,43 +5,54 @@ import { ServiceDataObj } from '../components/Modals/AddServiceModal/AddServiceM
import {
BIGQUERY,
HIVE,
KAFKA,
MSSQL,
MYSQL,
ORACLE,
POSTGRES,
PULSAR,
REDSHIFT,
SERVICE_DEFAULT,
SNOWFLAKE,
} from '../constants/services.const';
import { ServiceType } from '../enums/service.enum';
import {
DatabaseServiceType,
MessagingServiceType,
} from '../enums/service.enum';
import { ApiData } from '../pages/services';
export const serviceTypeLogo = (type: string) => {
switch (type) {
case ServiceType.MYSQL:
case DatabaseServiceType.MYSQL:
return MYSQL;
case ServiceType.REDSHIFT:
case DatabaseServiceType.REDSHIFT:
return REDSHIFT;
case ServiceType.BIGQUERY:
case DatabaseServiceType.BIGQUERY:
return BIGQUERY;
case ServiceType.HIVE:
case DatabaseServiceType.HIVE:
return HIVE;
case ServiceType.POSTGRES:
case DatabaseServiceType.POSTGRES:
return POSTGRES;
case ServiceType.ORACLE:
case DatabaseServiceType.ORACLE:
return ORACLE;
case ServiceType.SNOWFLAKE:
case DatabaseServiceType.SNOWFLAKE:
return SNOWFLAKE;
case ServiceType.MSSQL:
case DatabaseServiceType.MSSQL:
return MSSQL;
case MessagingServiceType.KAFKA:
return KAFKA;
case MessagingServiceType.PULSAR:
return PULSAR;
default:
return SERVICE_DEFAULT;
}