Added UI for tableau fields (#506)

This commit is contained in:
darth-coder00 2021-09-16 15:08:54 +05:30 committed by GitHub
parent 4af4a66bee
commit abbef2df8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 409 additions and 93 deletions

View File

@ -20,6 +20,7 @@ import { ServiceTypes } from 'Models';
import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
import { serviceTypes } from '../../../constants/services.const'; import { serviceTypes } from '../../../constants/services.const';
import { import {
DashboardServiceType,
MessagingServiceType, MessagingServiceType,
ServiceCategory, ServiceCategory,
} from '../../../enums/service.enum'; } from '../../../enums/service.enum';
@ -47,6 +48,12 @@ export type DataObj = {
dashboardUrl?: string; dashboardUrl?: string;
username?: string; username?: string;
password?: string; password?: string;
url?: string;
api_key?: string;
site_name?: string;
api_version?: string;
server?: string;
env?: string;
}; };
type DatabaseService = { type DatabaseService = {
@ -61,9 +68,15 @@ type MessagingService = {
}; };
type DashboardService = { type DashboardService = {
dashboardUrl: string; dashboardUrl?: string;
username: string; username?: string;
password: string; password?: string;
url?: string;
api_key?: string;
site_name?: string;
api_version?: string;
server?: string;
env?: string;
}; };
export type ServiceDataObj = { export type ServiceDataObj = {
@ -101,6 +114,11 @@ type ErrorMsg = {
dashboardUrl?: boolean; dashboardUrl?: boolean;
username?: boolean; username?: boolean;
password?: boolean; password?: boolean;
redashUrl?: boolean;
apiKey?: boolean;
siteName?: boolean;
apiVersion?: boolean;
server?: boolean;
}; };
type EditorContentRef = { type EditorContentRef = {
getEditorContent: () => string; getEditorContent: () => string;
@ -190,6 +208,12 @@ export const AddServiceModal: FunctionComponent<Props> = ({
const [dashboardUrl, setDashboardUrl] = useState(data?.dashboardUrl || ''); const [dashboardUrl, setDashboardUrl] = useState(data?.dashboardUrl || '');
const [username, setUsername] = useState(data?.username || ''); const [username, setUsername] = useState(data?.username || '');
const [password, setPassword] = useState(data?.password || ''); const [password, setPassword] = useState(data?.password || '');
const [redashUrl, setRedashUrl] = useState(data?.url || '');
const [apiKey, setApiKey] = useState(data?.api_key || '');
const [siteName, setSiteName] = useState(data?.site_name || '');
const [apiVersion, setApiVersion] = useState(data?.api_version || '');
const [server, setServer] = useState(data?.server || '');
const [env, setEnv] = useState(data?.env || '');
const [frequency, setFrequency] = useState( const [frequency, setFrequency] = useState(
fromISOString(data?.ingestionSchedule?.repeatFrequency) fromISOString(data?.ingestionSchedule?.repeatFrequency)
); );
@ -198,10 +222,16 @@ export const AddServiceModal: FunctionComponent<Props> = ({
name: false, name: false,
url: false, url: false,
// port: false, // port: false,
// userName: false,
// password: false,
driverClass: false, driverClass: false,
broker: false, broker: false,
dashboardUrl: false,
username: false,
password: false,
redashUrl: false,
apiKey: false,
siteName: false,
apiVersion: false,
server: false,
}); });
const [sameNameError, setSameNameError] = useState(false); const [sameNameError, setSameNameError] = useState(false);
const markdownRef = useRef<EditorContentRef>(); const markdownRef = useRef<EditorContentRef>();
@ -284,6 +314,11 @@ export const AddServiceModal: FunctionComponent<Props> = ({
dashboardUrl, dashboardUrl,
username, username,
password, password,
redashUrl,
apiKey,
siteName,
apiVersion,
server,
} = value; } = value;
return ( return (
@ -295,7 +330,12 @@ export const AddServiceModal: FunctionComponent<Props> = ({
!broker && !broker &&
!dashboardUrl && !dashboardUrl &&
!username && !username &&
!password !password &&
!redashUrl &&
!apiKey &&
!siteName &&
!apiVersion &&
!server
); );
}; };
@ -325,6 +365,33 @@ export const AddServiceModal: FunctionComponent<Props> = ({
break; break;
case ServiceCategory.DASHBOARD_SERVICES: case ServiceCategory.DASHBOARD_SERVICES:
{
switch (selectService) {
case DashboardServiceType.REDASH:
{
setMsg = {
...setMsg,
redashUrl: !redashUrl,
apiKey: !apiKey,
};
}
break;
case DashboardServiceType.TABLEAU:
{
setMsg = {
...setMsg,
dashboardUrl: !dashboardUrl,
siteName: !siteName,
username: !username,
password: !password,
apiVersion: !apiVersion,
server: !server,
};
}
break;
default:
{ {
setMsg = { setMsg = {
...setMsg, ...setMsg,
@ -334,6 +401,10 @@ export const AddServiceModal: FunctionComponent<Props> = ({
}; };
} }
break;
}
}
break; break;
default: default:
break; break;
@ -380,6 +451,36 @@ export const AddServiceModal: FunctionComponent<Props> = ({
break; break;
case ServiceCategory.DASHBOARD_SERVICES: case ServiceCategory.DASHBOARD_SERVICES:
{
switch (selectService) {
case DashboardServiceType.REDASH:
{
dataObj = {
...dataObj,
url: redashUrl,
// eslint-disable-next-line @typescript-eslint/camelcase
api_key: apiKey,
};
}
break;
case DashboardServiceType.TABLEAU:
{
dataObj = {
...dataObj,
dashboardUrl: dashboardUrl,
// eslint-disable-next-line @typescript-eslint/camelcase
site_name: siteName,
username: username,
password: password,
// eslint-disable-next-line @typescript-eslint/camelcase
api_version: apiVersion,
server: server,
};
}
break;
default:
{ {
dataObj = { dataObj = {
...dataObj, ...dataObj,
@ -389,6 +490,10 @@ export const AddServiceModal: FunctionComponent<Props> = ({
}; };
} }
break;
}
}
break; break;
default: default:
break; break;
@ -496,7 +601,160 @@ export const AddServiceModal: FunctionComponent<Props> = ({
}; };
const getDashboardFields = (): JSX.Element => { const getDashboardFields = (): JSX.Element => {
return ( let elemFields: JSX.Element;
switch (selectService) {
case DashboardServiceType.REDASH: {
elemFields = (
<>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="url">
{requiredField('Url:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="url"
name="url"
placeholder="http(s)://hostname:port"
type="text"
value={redashUrl}
onChange={(e) => setRedashUrl(e.target.value)}
/>
{showErrorMsg.redashUrl && errorMsg('Url is required')}
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="api-key">
{requiredField('Api key:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="api-key"
name="api-key"
placeholder="api key"
type="password"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
/>
{showErrorMsg.apiKey && errorMsg('Api key is required')}
</div>
</>
);
break;
}
case DashboardServiceType.TABLEAU: {
elemFields = (
<>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="site-name">
{requiredField('Site Name:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="site-name"
name="site-name"
placeholder="site name"
type="text"
value={siteName}
onChange={(e) => setSiteName(e.target.value)}
/>
{showErrorMsg.siteName && errorMsg('Site name is required')}
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="dashboard-url">
{requiredField('Site Url:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="dashboard-url"
name="dashboard-url"
placeholder="http(s)://hostname:port"
type="text"
value={dashboardUrl}
onChange={(e) => setDashboardUrl(e.target.value)}
/>
{showErrorMsg.dashboardUrl && errorMsg('Site url is required')}
</div>
<div className="tw-mt-4">
<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"
placeholder="username"
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
{showErrorMsg.username && errorMsg('Username is required')}
</div>
<div className="tw-mt-4">
<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"
placeholder="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
{showErrorMsg.password && errorMsg('Password is required')}
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="server">
{requiredField('Server:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="server"
name="server"
placeholder="http(s)://hostname:port"
type="text"
value={server}
onChange={(e) => setServer(e.target.value)}
/>
{showErrorMsg.server && errorMsg('Server is required')}
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="api-version">
{requiredField('Api Version:')}
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="api-version"
name="api-version"
placeholder="api version"
type="text"
value={apiVersion}
onChange={(e) => setApiVersion(e.target.value)}
/>
{showErrorMsg.apiVersion && errorMsg('Api version is required')}
</div>
<div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="env">
Environment:
</label>
<input
className="tw-form-inputs tw-px-3 tw-py-1"
id="env"
name="env"
placeholder="environment"
type="text"
value={env}
onChange={(e) => setEnv(e.target.value)}
/>
</div>
</>
);
break;
}
default: {
elemFields = (
<> <>
<div className="tw-mt-4"> <div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="dashboard-url"> <label className="tw-block tw-form-label" htmlFor="dashboard-url">
@ -511,7 +769,8 @@ export const AddServiceModal: FunctionComponent<Props> = ({
value={dashboardUrl} value={dashboardUrl}
onChange={(e) => setDashboardUrl(e.target.value)} onChange={(e) => setDashboardUrl(e.target.value)}
/> />
{showErrorMsg.dashboardUrl && errorMsg('Dashboard url is required')} {showErrorMsg.dashboardUrl &&
errorMsg('Dashboard url is required')}
</div> </div>
<div className="tw-mt-4"> <div className="tw-mt-4">
<label className="tw-block tw-form-label" htmlFor="username"> <label className="tw-block tw-form-label" htmlFor="username">
@ -545,6 +804,12 @@ export const AddServiceModal: FunctionComponent<Props> = ({
</div> </div>
</> </>
); );
break;
}
}
return elemFields;
}; };
const getOptionalFields = (): JSX.Element => { const getOptionalFields = (): JSX.Element => {

View File

@ -71,8 +71,8 @@ export const serviceTypes: Record<ServiceTypes, Array<string>> = {
'Athena', 'Athena',
'Presto', 'Presto',
], ],
messagingServices: ['Kafka', 'Pulsar'], messagingServices: ['Kafka'],
dashboardServices: ['Superset', 'Looker', 'Tableau', 'Redash'], dashboardServices: ['Superset', 'Looker', 'Tableau'],
}; };
export const arrServiceTypes: Array<ServiceTypes> = [ export const arrServiceTypes: Array<ServiceTypes> = [

View File

@ -36,7 +36,10 @@ import { ModalWithMarkdownEditor } from '../../components/Modals/ModalWithMarkdo
import Tags from '../../components/tags/tags'; import Tags from '../../components/tags/tags';
import { pagingObject } from '../../constants/constants'; import { pagingObject } from '../../constants/constants';
import { SearchIndex } from '../../enums/search.enum'; import { SearchIndex } from '../../enums/search.enum';
import { ServiceCategory } from '../../enums/service.enum'; import {
DashboardServiceType,
ServiceCategory,
} from '../../enums/service.enum';
import { Dashboard } from '../../generated/entity/data/dashboard'; import { Dashboard } from '../../generated/entity/data/dashboard';
import { Topic } from '../../generated/entity/data/topic'; import { Topic } from '../../generated/entity/data/topic';
import useToastContext from '../../hooks/useToastContext'; import useToastContext from '../../hooks/useToastContext';
@ -244,7 +247,44 @@ const ServicePage: FunctionComponent = () => {
); );
} }
case ServiceCategory.DASHBOARD_SERVICES: { case ServiceCategory.DASHBOARD_SERVICES: {
return ( let elemFields: JSX.Element;
switch (serviceType) {
// case DashboardServiceType.REDASH:
// {
// // TODO: add Redash fields if required
// }
// break;
case DashboardServiceType.TABLEAU:
{
elemFields = (
<>
<span>
<span className="tw-text-grey-muted tw-font-normal">
Site Url :
</span>{' '}
<span className="tw-pl-1tw-font-normal ">
{serviceDetails?.dashboardUrl ? (
<a
className="link-text"
href={serviceDetails.dashboardUrl}
rel="noopener noreferrer"
target="_blank">
{serviceDetails.dashboardUrl}
</a>
) : (
'--'
)}
</span>
<span className="tw-mx-3 tw-text-grey-muted"></span>
</span>
</>
);
}
break;
default: {
elemFields = (
<span> <span>
<span className="tw-text-grey-muted tw-font-normal"> <span className="tw-text-grey-muted tw-font-normal">
Dashboard Url : Dashboard Url :
@ -266,6 +306,10 @@ const ServicePage: FunctionComponent = () => {
</span> </span>
); );
} }
}
return elemFields;
}
default: { default: {
return <></>; return <></>;
} }

View File

@ -48,7 +48,10 @@ import {
PLUS, PLUS,
servicesDisplayName, servicesDisplayName,
} from '../../constants/services.const'; } from '../../constants/services.const';
import { ServiceCategory } from '../../enums/service.enum'; import {
DashboardServiceType,
ServiceCategory,
} from '../../enums/service.enum';
import { getCountBadge, getTabClasses } from '../../utils/CommonUtils'; import { getCountBadge, getTabClasses } from '../../utils/CommonUtils';
import { getFrequencyTime, serviceTypeLogo } from '../../utils/ServiceUtils'; import { getFrequencyTime, serviceTypeLogo } from '../../utils/ServiceUtils';
import SVGIcons from '../../utils/SvgUtils'; import SVGIcons from '../../utils/SvgUtils';
@ -239,7 +242,11 @@ const ServicesPage = () => {
return ( return (
<> <>
<div className="tw-mb-1"> <div className="tw-mb-1">
<label className="tw-mb-0">Dashboard URL:</label> <label className="tw-mb-0">
{service.serviceType === DashboardServiceType.TABLEAU
? 'Site URL:'
: 'Dashboard URL:'}
</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">
{service.dashboardUrl} {service.dashboardUrl}
</span> </span>