mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-25 22:49:12 +00:00
Minor: Day one trigger button on service details page (#20613)
* Worked on adding the day 1 trigger button on service details page * Fix the service main tab styling * Enhance DataAssetsHeader and ServiceInsightsTab components to support day one application triggering. Added new props for disabling the run agents button and handling post-trigger actions. Updated localization files with new messages for day one application status. Refactored ServiceDetailsPage to integrate workflow state management and trigger fetching. * Fix the border on application config tab * Change the logic to show the trigger day one button to only display in case of failure Fix the add service page card spacing * Fix the unit test
This commit is contained in:
parent
d747536f48
commit
188f575180
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 7.5 KiB |
@ -19,17 +19,19 @@ import { get, isEmpty } from 'lodash';
|
||||
import QueryString from 'qs';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link, useHistory } from 'react-router-dom';
|
||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||
import { ReactComponent as IconExternalLink } from '../../../assets/svg/external-links.svg';
|
||||
import { ReactComponent as RedAlertIcon } from '../../../assets/svg/ic-alert-red.svg';
|
||||
import { ReactComponent as TaskOpenIcon } from '../../../assets/svg/ic-open-task.svg';
|
||||
import { ReactComponent as VersionIcon } from '../../../assets/svg/ic-version.svg';
|
||||
import { ReactComponent as LinkIcon } from '../../../assets/svg/link-icon-with-bg.svg';
|
||||
import { ReactComponent as TriggerIcon } from '../../../assets/svg/trigger.svg';
|
||||
import { ActivityFeedTabs } from '../../../components/ActivityFeed/ActivityFeedTab/ActivityFeedTab.interface';
|
||||
import { DomainLabel } from '../../../components/common/DomainLabel/DomainLabel.component';
|
||||
import { OwnerLabel } from '../../../components/common/OwnerLabel/OwnerLabel.component';
|
||||
import TierCard from '../../../components/common/TierCard/TierCard';
|
||||
import EntityHeaderTitle from '../../../components/Entity/EntityHeaderTitle/EntityHeaderTitle.component';
|
||||
import { DAY_ONE_EXPERIENCE_APP_NAME } from '../../../constants/Applications.constant';
|
||||
import { DATA_ASSET_ICON_DIMENSION } from '../../../constants/constants';
|
||||
import { SERVICE_TYPES } from '../../../constants/Services.constant';
|
||||
import { TAG_START_WITH } from '../../../constants/Tag.constants';
|
||||
@ -39,12 +41,14 @@ import {
|
||||
EntityType,
|
||||
TabSpecificField,
|
||||
} from '../../../enums/entity.enum';
|
||||
import { ServiceCategory } from '../../../enums/service.enum';
|
||||
import { LineageLayer } from '../../../generated/configuration/lineageSettings';
|
||||
import { Container } from '../../../generated/entity/data/container';
|
||||
import { Table } from '../../../generated/entity/data/table';
|
||||
import { Thread } from '../../../generated/entity/feed/thread';
|
||||
import { useApplicationStore } from '../../../hooks/useApplicationStore';
|
||||
import { SearchSourceAlias } from '../../../interface/search.interface';
|
||||
import { triggerOnDemandApp } from '../../../rest/applicationAPI';
|
||||
import { getActiveAnnouncement } from '../../../rest/feedsAPI';
|
||||
import { getDataQualityLineage } from '../../../rest/lineageAPI';
|
||||
import { getContainerByName } from '../../../rest/storageAPI';
|
||||
@ -62,6 +66,7 @@ import {
|
||||
} from '../../../utils/EntityUtils';
|
||||
import { getEntityDetailsPath } from '../../../utils/RouterUtils';
|
||||
import serviceUtilClassBase from '../../../utils/ServiceUtilClassBase';
|
||||
import { getEntityTypeFromServiceCategory } from '../../../utils/ServiceUtils';
|
||||
import tableClassBase from '../../../utils/TableClassBase';
|
||||
import { getTierTags } from '../../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
@ -193,7 +198,11 @@ export const DataAssetsHeader = ({
|
||||
badge,
|
||||
isDqAlertSupported,
|
||||
isCustomizedView = false,
|
||||
disableRunAgentsButton = true,
|
||||
afterTriggerAction,
|
||||
isDayOneWorkflowStatusLoading = false,
|
||||
}: DataAssetsHeaderProps) => {
|
||||
const { serviceCategory } = useParams<{ serviceCategory: ServiceCategory }>();
|
||||
const { currentUser } = useApplicationStore();
|
||||
const { selectedUserSuggestions } = useSuggestionsContext();
|
||||
const USER_ID = currentUser?.id ?? '';
|
||||
@ -204,6 +213,7 @@ export const DataAssetsHeader = ({
|
||||
const [dqFailureCount, setDqFailureCount] = useState(0);
|
||||
const [isFollowingLoading, setIsFollowingLoading] = useState(false);
|
||||
const history = useHistory();
|
||||
const [isDayOneTriggering, setIsDayOneTriggering] = useState(false);
|
||||
const icon = useMemo(() => {
|
||||
const serviceType = get(dataAsset, 'serviceType', '');
|
||||
|
||||
@ -282,7 +292,7 @@ export const DataAssetsHeader = ({
|
||||
(node) => node?.fullyQualifiedName !== dataAsset?.fullyQualifiedName
|
||||
) ?? [];
|
||||
setDqFailureCount(updatedNodes.length);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
setDqFailureCount(0);
|
||||
}
|
||||
};
|
||||
@ -472,6 +482,56 @@ export const DataAssetsHeader = ({
|
||||
selectedUserSuggestions,
|
||||
]);
|
||||
|
||||
const triggerTheDayOneApplication = useCallback(async () => {
|
||||
try {
|
||||
setIsDayOneTriggering(true);
|
||||
const entityType = getEntityTypeFromServiceCategory(serviceCategory);
|
||||
const entityLink = getEntityFeedLink(
|
||||
entityType,
|
||||
dataAsset.fullyQualifiedName ?? ''
|
||||
);
|
||||
|
||||
await triggerOnDemandApp(DAY_ONE_EXPERIENCE_APP_NAME, {
|
||||
entityLink,
|
||||
});
|
||||
|
||||
afterTriggerAction?.();
|
||||
} catch (err) {
|
||||
showErrorToast(err as AxiosError);
|
||||
} finally {
|
||||
setIsDayOneTriggering(false);
|
||||
}
|
||||
}, [serviceCategory, afterTriggerAction]);
|
||||
|
||||
const triggerDayOneApplicationButton = useMemo(() => {
|
||||
if (!SERVICE_TYPES.includes(entityType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isDisabled = isDayOneWorkflowStatusLoading || disableRunAgentsButton;
|
||||
const isLoading = isDayOneWorkflowStatusLoading || isDayOneTriggering;
|
||||
|
||||
return (
|
||||
<Tooltip title={t('message.trigger-day-one-application')}>
|
||||
<Button
|
||||
className="font-semibold"
|
||||
data-testid="trigger-day-one-application-button"
|
||||
disabled={isDisabled}
|
||||
icon={<Icon className="flex-center" component={TriggerIcon} />}
|
||||
loading={isLoading}
|
||||
type="primary"
|
||||
onClick={triggerTheDayOneApplication}>
|
||||
{t('label.run-agent-plural')}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
}, [
|
||||
disableRunAgentsButton,
|
||||
isDayOneWorkflowStatusLoading,
|
||||
isDayOneTriggering,
|
||||
triggerTheDayOneApplication,
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row
|
||||
@ -509,6 +569,7 @@ export const DataAssetsHeader = ({
|
||||
className="data-asset-button-group spaced"
|
||||
data-testid="asset-header-btn-group"
|
||||
size="small">
|
||||
{triggerDayOneApplicationButton}
|
||||
{onUpdateVote && (
|
||||
<Voting
|
||||
disabled={deleted}
|
||||
|
||||
@ -136,6 +136,9 @@ export type DataAssetsHeaderProps = {
|
||||
extraDropdownContent?: ManageButtonProps['extraDropdownContent'];
|
||||
onMetricUpdate?: (updatedData: Metric, key: keyof Metric) => Promise<void>;
|
||||
isCustomizedView?: boolean;
|
||||
disableRunAgentsButton?: boolean;
|
||||
afterTriggerAction?: VoidFunction;
|
||||
isDayOneWorkflowStatusLoading?: boolean;
|
||||
} & (
|
||||
| DataAssetTable
|
||||
| DataAssetTopic
|
||||
|
||||
@ -10,13 +10,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import { act, fireEvent, render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { EntityType } from '../../../enums/entity.enum';
|
||||
import {
|
||||
APIEndpoint,
|
||||
APIRequestMethod,
|
||||
} from '../../../generated/entity/data/apiEndpoint';
|
||||
import {
|
||||
Container,
|
||||
StorageServiceType,
|
||||
@ -28,8 +24,12 @@ import { DEFAULT_ENTITY_PERMISSION } from '../../../utils/PermissionsUtils';
|
||||
import { DataAssetsHeader, ExtraInfoLink } from './DataAssetsHeader.component';
|
||||
import { DataAssetsHeaderProps } from './DataAssetsHeader.interface';
|
||||
|
||||
import { DAY_ONE_EXPERIENCE_APP_NAME } from '../../../constants/Applications.constant';
|
||||
import { ServiceCategory } from '../../../enums/service.enum';
|
||||
import { DatabaseServiceType } from '../../../generated/entity/services/databaseService';
|
||||
import { LabelType, State, TagSource } from '../../../generated/tests/testCase';
|
||||
import { AssetCertification } from '../../../generated/type/assetCertification';
|
||||
import { triggerOnDemandApp } from '../../../rest/applicationAPI';
|
||||
const mockProps: DataAssetsHeaderProps = {
|
||||
dataAsset: {
|
||||
id: 'assets-id',
|
||||
@ -57,6 +57,42 @@ const mockProps: DataAssetsHeaderProps = {
|
||||
onOwnerUpdate: jest.fn(),
|
||||
};
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useParams: jest.fn().mockImplementation(() => ({
|
||||
serviceCategory: ServiceCategory.DATABASE_SERVICES,
|
||||
})),
|
||||
}));
|
||||
|
||||
jest.mock('../../../rest/applicationAPI', () => ({
|
||||
triggerOnDemandApp: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/ServiceUtils', () => ({
|
||||
getEntityTypeFromServiceCategory: jest
|
||||
.fn()
|
||||
.mockImplementation(() => EntityType.DATABASE_SERVICE),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/EntityUtils', () => ({
|
||||
getEntityName: jest.fn().mockImplementation(() => 'name'),
|
||||
getEntityFeedLink: jest.fn().mockImplementation(() => 'entityFeedLink'),
|
||||
getEntityVoteStatus: jest.fn().mockImplementation(() => 'unVoted'),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils/DataAssetsHeader.utils', () => ({
|
||||
getDataAssetsHeaderInfo: jest.fn().mockImplementation(() => ({
|
||||
breadcrumbs: [],
|
||||
extraInfo: [],
|
||||
})),
|
||||
getEntityExtraInfoLength: jest.fn().mockImplementation(() => 0),
|
||||
isDataAssetsWithServiceField: jest.fn().mockImplementation(() => true),
|
||||
}));
|
||||
|
||||
jest.mock('../../common/CertificationTag/CertificationTag', () => {
|
||||
return jest.fn().mockImplementation(() => <div>CertificationTag</div>);
|
||||
});
|
||||
|
||||
jest.mock(
|
||||
'../../../components/common/TitleBreadcrumb/TitleBreadcrumb.component',
|
||||
() => {
|
||||
@ -196,27 +232,6 @@ describe('DataAssetsHeader component', () => {
|
||||
expect(screen.getByTestId('Tier')).toContainHTML('label.no-entity');
|
||||
});
|
||||
|
||||
it('should render the request method if entityType is apiEndpoint', () => {
|
||||
render(
|
||||
<DataAssetsHeader
|
||||
{...mockProps}
|
||||
dataAsset={
|
||||
{
|
||||
name: 'testAPIEndpoint',
|
||||
id: 'testAPIEndpointId',
|
||||
endpointURL: 'testAPIEndpointURL',
|
||||
requestMethod: APIRequestMethod.Get,
|
||||
} as APIEndpoint
|
||||
}
|
||||
entityType={EntityType.API_ENDPOINT}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByTestId('api-endpoint-request-method')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should call getDataQualityLineage, if isDqAlertSupported and alert supported is true', () => {
|
||||
mockIsAlertSupported = true;
|
||||
act(() => {
|
||||
@ -291,11 +306,35 @@ describe('DataAssetsHeader component', () => {
|
||||
|
||||
expect(screen.getByText('label.certification')).toBeInTheDocument();
|
||||
|
||||
const certificatComponent = screen.getByTestId(
|
||||
`certification-${mockCertification.tagLabel.tagFQN}`
|
||||
);
|
||||
const certificatComponent = screen.getByText(`CertificationTag`);
|
||||
|
||||
expect(certificatComponent).toBeInTheDocument();
|
||||
expect(certificatComponent).toHaveTextContent('Bronze_Medal');
|
||||
});
|
||||
|
||||
it('should trigger the Day One application when the button is clicked', () => {
|
||||
render(
|
||||
<DataAssetsHeader
|
||||
{...mockProps}
|
||||
dataAsset={{
|
||||
...mockProps.dataAsset,
|
||||
serviceType: DatabaseServiceType.BigQuery,
|
||||
}}
|
||||
disableRunAgentsButton={false}
|
||||
entityType={EntityType.DATABASE_SERVICE}
|
||||
/>
|
||||
);
|
||||
|
||||
const button = screen.getByTestId('trigger-day-one-application-button');
|
||||
|
||||
expect(button).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(triggerOnDemandApp).toHaveBeenCalledWith(
|
||||
DAY_ONE_EXPERIENCE_APP_NAME,
|
||||
{
|
||||
entityLink: 'entityFeedLink',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
max-width: 148px;
|
||||
}
|
||||
|
||||
.ant-btn.source-url-button {
|
||||
.ant-btn.ant-btn-default.source-url-button {
|
||||
background-color: @blue-11;
|
||||
|
||||
.ant-typography {
|
||||
|
||||
@ -17,6 +17,8 @@ import { ServicesType } from '../../interface/service.interface';
|
||||
|
||||
export interface ServiceInsightsTabProps {
|
||||
serviceDetails: ServicesType;
|
||||
workflowStatesData?: WorkflowStatesData;
|
||||
isWorkflowStatusLoading: boolean;
|
||||
}
|
||||
export interface WorkflowStatesData {
|
||||
mainInstanceState: WorkflowInstance;
|
||||
|
||||
@ -19,41 +19,32 @@ import { isUndefined, toLower } from 'lodash';
|
||||
import { ServiceTypes } from 'Models';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {
|
||||
PLATFORM_INSIGHTS_CHART,
|
||||
SERVICE_INSIGHTS_WORKFLOW_DEFINITION_NAME,
|
||||
} from '../../constants/ServiceInsightsTab.constants';
|
||||
import { PLATFORM_INSIGHTS_CHART } from '../../constants/ServiceInsightsTab.constants';
|
||||
import { SystemChartType } from '../../enums/DataInsight.enum';
|
||||
import { WorkflowStatus } from '../../generated/governance/workflows/workflowInstance';
|
||||
import { getMultiChartsPreviewByName } from '../../rest/DataInsightAPI';
|
||||
import {
|
||||
getWorkflowInstancesForApplication,
|
||||
getWorkflowInstanceStateById,
|
||||
} from '../../rest/workflowAPI';
|
||||
import {
|
||||
getCurrentDayStartGMTinMillis,
|
||||
getCurrentMillis,
|
||||
getDayAgoStartGMTinMillis,
|
||||
} from '../../utils/date-time/DateTimeUtils';
|
||||
import { getEntityFeedLink } from '../../utils/EntityUtils';
|
||||
import {
|
||||
getPlatformInsightsChartDataFormattingMethod,
|
||||
getStatusIconFromStatusType,
|
||||
} from '../../utils/ServiceInsightsTabUtils';
|
||||
import serviceUtilClassBase from '../../utils/ServiceUtilClassBase';
|
||||
import { getEntityTypeFromServiceCategory } from '../../utils/ServiceUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import {
|
||||
ChartData,
|
||||
ChartSeriesData,
|
||||
} from './PlatformInsightsWidget/PlatformInsightsWidget.interface';
|
||||
import './service-insights-tab.less';
|
||||
import {
|
||||
ServiceInsightsTabProps,
|
||||
WorkflowStatesData,
|
||||
} from './ServiceInsightsTab.interface';
|
||||
import { ServiceInsightsTabProps } from './ServiceInsightsTab.interface';
|
||||
|
||||
const ServiceInsightsTab = ({ serviceDetails }: ServiceInsightsTabProps) => {
|
||||
const ServiceInsightsTab = ({
|
||||
serviceDetails,
|
||||
workflowStatesData,
|
||||
isWorkflowStatusLoading,
|
||||
}: ServiceInsightsTabProps) => {
|
||||
const { serviceCategory } = useParams<{
|
||||
serviceCategory: ServiceTypes;
|
||||
tab: string;
|
||||
@ -64,53 +55,11 @@ const ServiceInsightsTab = ({ serviceDetails }: ServiceInsightsTabProps) => {
|
||||
tierDistributionChart: ChartData[];
|
||||
}>();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [workflowStatesData, setWorkflowStatesData] =
|
||||
useState<WorkflowStatesData>();
|
||||
const [isWorkflowStatusLoading, setIsWorkflowStatusLoading] = useState(false);
|
||||
|
||||
const serviceName = serviceDetails.name;
|
||||
|
||||
const widgets = serviceUtilClassBase.getInsightsTabWidgets(serviceCategory);
|
||||
|
||||
const fetchWorkflowInstanceStates = async () => {
|
||||
try {
|
||||
setIsWorkflowStatusLoading(true);
|
||||
const startTs = getDayAgoStartGMTinMillis(6);
|
||||
const endTs = getCurrentMillis();
|
||||
const entityType = getEntityTypeFromServiceCategory(serviceCategory);
|
||||
const workflowInstances = await getWorkflowInstancesForApplication({
|
||||
startTs,
|
||||
endTs,
|
||||
workflowDefinitionName: SERVICE_INSIGHTS_WORKFLOW_DEFINITION_NAME,
|
||||
entityLink: getEntityFeedLink(
|
||||
entityType,
|
||||
serviceDetails.fullyQualifiedName
|
||||
),
|
||||
});
|
||||
|
||||
const workflowInstanceId = workflowInstances.data[0]?.id;
|
||||
|
||||
if (workflowInstanceId) {
|
||||
const workflowInstanceStates = await getWorkflowInstanceStateById(
|
||||
SERVICE_INSIGHTS_WORKFLOW_DEFINITION_NAME,
|
||||
workflowInstanceId,
|
||||
{
|
||||
startTs,
|
||||
endTs,
|
||||
}
|
||||
);
|
||||
setWorkflowStatesData({
|
||||
mainInstanceState: workflowInstances.data[0],
|
||||
subInstanceStates: workflowInstanceStates.data,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsWorkflowStatusLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchChartsData = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
@ -157,7 +106,6 @@ const ServiceInsightsTab = ({ serviceDetails }: ServiceInsightsTabProps) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchWorkflowInstanceStates();
|
||||
fetchChartsData();
|
||||
}, []);
|
||||
|
||||
|
||||
@ -54,23 +54,21 @@ const ApplicationConfiguration = ({
|
||||
};
|
||||
|
||||
const formPanel = (
|
||||
<div className="m-auto max-width-md w-full p-lg">
|
||||
<FormBuilder
|
||||
useSelectWidget
|
||||
cancelText={t('label.back')}
|
||||
formData={appData?.appConfiguration ?? {}}
|
||||
hideCancelButton={!onCancel}
|
||||
isLoading={isLoading}
|
||||
okText={t('label.submit')}
|
||||
schema={jsonSchema}
|
||||
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||
uiSchema={UiSchema}
|
||||
validator={validator}
|
||||
onCancel={onCancel}
|
||||
onFocus={handleFieldFocus}
|
||||
onSubmit={onConfigSave}
|
||||
/>
|
||||
</div>
|
||||
<FormBuilder
|
||||
useSelectWidget
|
||||
cancelText={t('label.back')}
|
||||
formData={appData?.appConfiguration ?? {}}
|
||||
hideCancelButton={!onCancel}
|
||||
isLoading={isLoading}
|
||||
okText={t('label.submit')}
|
||||
schema={jsonSchema}
|
||||
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||
uiSchema={UiSchema}
|
||||
validator={validator}
|
||||
onCancel={onCancel}
|
||||
onFocus={handleFieldFocus}
|
||||
onSubmit={onConfigSave}
|
||||
/>
|
||||
);
|
||||
|
||||
const docPanel = (
|
||||
@ -83,7 +81,7 @@ const ApplicationConfiguration = ({
|
||||
|
||||
return (
|
||||
<ResizablePanels
|
||||
className="content-height-with-resizable-panel border-default border-radius-sm"
|
||||
className="content-height-with-resizable-panel"
|
||||
firstPanel={{
|
||||
children: formPanel,
|
||||
minWidth: 700,
|
||||
|
||||
@ -120,8 +120,8 @@ const SelectServiceType = ({
|
||||
<Row className="service-list-container" data-testid="select-service">
|
||||
{filteredConnectors.map((type) => (
|
||||
<Button
|
||||
className={classNames('service-box p-xs d-block border', {
|
||||
'border-primary': type === selectServiceType,
|
||||
className={classNames('service-box', {
|
||||
'selected-service': type === selectServiceType,
|
||||
})}
|
||||
data-testid={type}
|
||||
key={type}
|
||||
|
||||
@ -13,15 +13,20 @@
|
||||
@import (reference) url('../../../../../styles/variables.less');
|
||||
|
||||
.service-list-container {
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
margin-top: @margin-md;
|
||||
gap: @margin-md;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.ant-btn.ant-btn-default.selected-service {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
.service-box {
|
||||
position: relative;
|
||||
height: auto;
|
||||
flex: 0 0 114px;
|
||||
padding: 20px 8px;
|
||||
|
||||
p {
|
||||
white-space: pre-wrap;
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Regelname",
|
||||
"rule-plural": "Regeln",
|
||||
"run": "Ausführen",
|
||||
"run-agent-plural": "Agenten ausführen",
|
||||
"run-at": "Ausführen um",
|
||||
"run-now": "Jetzt ausführen",
|
||||
"run-type": "Ausführart",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Suchen Sie nach übereinstimmenden Datenvermögenswerten nach \"Name\", \"Beschreibung\", \"Spaltenname\" usw. aus dem <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": "Mit <0>{{text}}</0> verfolgen Sie den Pfad der Daten über Tabellen, Pipelines und Dashboards.",
|
||||
"tour-step-type-search-term": "Geben Sie im Suchfeld <0>\"{{text}}\"</0> ein. Drücken Sie <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Day One-Anwendung auslösen",
|
||||
"try-adjusting-filter": "Versuchen Sie, Ihre Suche oder Ihren Filter anzupassen, um zu finden, was Sie suchen.",
|
||||
"try-different-time-period-filtering": "Keine Ergebnisse verfügbar. Versuchen Sie, nach einem anderen Zeitraum zu filtern.",
|
||||
"try-extending-time-frame": "Versuchen Sie, den Zeitraum zu verlängern, um die Ergebnisse anzuzeigen.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Rule Name",
|
||||
"rule-plural": "Rules",
|
||||
"run": "Run",
|
||||
"run-agent-plural": "Run Agents",
|
||||
"run-at": "Run at",
|
||||
"run-now": "Run now",
|
||||
"run-type": "Run Type",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Search for matching data assets by \"name\", \"description\", \"column name\", and so on from the <0>{{text}}</0> box.",
|
||||
"tour-step-trace-path-across-tables": " With <0>{{text}}</0>, trace the path of data across tables, pipelines, & dashboards.",
|
||||
"tour-step-type-search-term": "In the search box, type <0>\"{{text}}\"</0>. Hit <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Trigger the Day One application",
|
||||
"try-adjusting-filter": "Try adjusting your search or filter to find what you are looking for.",
|
||||
"try-different-time-period-filtering": "No Results Available. Try filtering by a different time period.",
|
||||
"try-extending-time-frame": "Try extending the time frame to view the results.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Nombre de la Regla",
|
||||
"rule-plural": "Reglas",
|
||||
"run": "Ejecutar",
|
||||
"run-agent-plural": "Ejecutar Agentes",
|
||||
"run-at": "Ejecutar a las",
|
||||
"run-now": "Ejecutar ahora",
|
||||
"run-type": "Tipo de Ejecución",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Busca activos de datos coincidentes por \"nombre\", \"descripción\", \"nombre de la columna\", y así sucesivamente desde el cuadro <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": " Con <0>{{text}}</0>, sigue el camino de los datos a través de tablas, pipelines y paneles de control.",
|
||||
"tour-step-type-search-term": "En el cuadro de búsqueda, escribe <0>\"{{text}}\"</0>. Presiona <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Ejecutar la aplicación de Día Uno",
|
||||
"try-adjusting-filter": "Intenta ajustar tu búsqueda o filtro para encontrar lo que estás buscando.",
|
||||
"try-different-time-period-filtering": "No hay resultados disponibles. Intente filtrar por un período de tiempo diferente.",
|
||||
"try-extending-time-frame": "Intenta extender el marco de tiempo para ver los resultados.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Nom de la Règle",
|
||||
"rule-plural": "Règles",
|
||||
"run": "Exécuter",
|
||||
"run-agent-plural": "Exécuter les Agents",
|
||||
"run-at": "Run at",
|
||||
"run-now": "Exécuter maintenant",
|
||||
"run-type": "Run Type",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Rechercher les actifs de données correspondant par \"nom\", \"description\", \"nom de colonne\", etc. depuis <0>{{text}}</0> box.",
|
||||
"tour-step-trace-path-across-tables": " Avec <0>{{text}}</0>, suivez le chemin des données à travers les tables, les pipelines et les tableaux de bord.",
|
||||
"tour-step-type-search-term": "Dans la zone de recherche, tapez <0>« {{text}} »</0>. Appuyez sur <0>{{enterText}}</0>",
|
||||
"trigger-day-one-application": "Déclencher l'application Day One",
|
||||
"try-adjusting-filter": "Essayez de trouver ce que vous cherchez en ajustant votre recherche ou vos filtres.",
|
||||
"try-different-time-period-filtering": "Aucun résultat disponible. Essayez de filtrer par une période de temps différente.",
|
||||
"try-extending-time-frame": "Essayez d'étendre la période de temps pour voir les résultats.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Nome da regra",
|
||||
"rule-plural": "Regras",
|
||||
"run": "Executar",
|
||||
"run-agent-plural": "Executar Agentes",
|
||||
"run-at": "Executar ás",
|
||||
"run-now": "Executar agora",
|
||||
"run-type": "Tipo de execución",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Busca activos de datos coincidentes por \"nome\", \"descrición\", \"nome da columna\", e moito máis desde o cadro <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": "Con <0>{{text}}</0>, traza o camiño dos datos entre táboas, pipelines e paneis.",
|
||||
"tour-step-type-search-term": "No cadro de busca, escribe <0>\"{{text}}\"</0>. Preme <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Ejecutar la aplicación Day One",
|
||||
"try-adjusting-filter": "Tenta axustar a túa busca ou filtro para atopar o que estás buscando.",
|
||||
"try-different-time-period-filtering": "Non hai resultados dispoñibles. Proba a filtrar por un período de tempo diferente.",
|
||||
"try-extending-time-frame": "Tenta ampliar o intervalo de tempo para ver os resultados.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "שם הכלל",
|
||||
"rule-plural": "כללים",
|
||||
"run": "הרץ",
|
||||
"run-agent-plural": "הפעל סוכנים",
|
||||
"run-at": "הרץ ב",
|
||||
"run-now": "הרץ עכשיו",
|
||||
"run-type": "סוג הרצה",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "חפש נכסי נתונים תואמים לפי \"שם\", \"תיאור\", \"שם עמודה\" וכדומה מתוך <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": "עם <0>{{text}}</0>, תרסה את הנתיב של הנתונים בטבלאות, תהליכי טעינה ולוחות בקרה.",
|
||||
"tour-step-type-search-term": "בתיבת החיפוש, הקלד <0>\"{{text}}\"</0>. לחץ <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "הפעל את האפליקציה Day One",
|
||||
"try-adjusting-filter": "נסה להתאים את החיפוש או הסינון שלך כדי למצוא את מה שאתה מחפש.",
|
||||
"try-different-time-period-filtering": "אין תוצאות זמינות. נסה לסנן לפי תקופת זמן שונה.",
|
||||
"try-extending-time-frame": "Try extending the time frame to view the results.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "ルール名",
|
||||
"rule-plural": "Rules",
|
||||
"run": "実行",
|
||||
"run-agent-plural": "エージェントを実行",
|
||||
"run-at": "Run at",
|
||||
"run-now": "Run now",
|
||||
"run-type": "Run Type",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Search for matching data assets by \"name\", \"description\", \"column name\", and so on from the <0>{{text}}</0> box.",
|
||||
"tour-step-trace-path-across-tables": "<0>{{text}}</0>で、 テーブル、パイプライン、ダッシュボードにまたがるデータのパスを追跡します。",
|
||||
"tour-step-type-search-term": "In the search box, type <0>\"{{text}}\"</0>. Hit <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Day Oneアプリケーションをトリガーする",
|
||||
"try-adjusting-filter": "Try adjusting your search or filter to find what you are looking for.",
|
||||
"try-different-time-period-filtering": "結果がありません。異なる期間でのフィルタリングを試して下さい。",
|
||||
"try-extending-time-frame": "Try extending the time frame to view the results.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "규칙 이름",
|
||||
"rule-plural": "규칙들",
|
||||
"run": "실행",
|
||||
"run-agent-plural": "에이전트 실행",
|
||||
"run-at": "실행 시간",
|
||||
"run-now": "지금 실행",
|
||||
"run-type": "실행 유형",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "검색 상자에 '이름', '설명', '열 이름' 등을 입력하여 일치하는 데이터 자산을 찾으세요: <0>{{text}}</0>",
|
||||
"tour-step-trace-path-across-tables": "<0>{{text}}</0>를 사용하여 테이블, 파이프라인, 대시보드 간의 데이터 경로를 추적하세요.",
|
||||
"tour-step-type-search-term": "검색 상자에 <0>\"{{text}}\"</0>를 입력하고 <0>{{enterText}}</0>를 누르세요.",
|
||||
"trigger-day-one-application": "Day One 애플리케이션 트리거",
|
||||
"try-adjusting-filter": "원하는 항목을 찾기 위해 검색어나 필터를 조정해 보세요.",
|
||||
"try-different-time-period-filtering": "결과가 없습니다. 다른 기간으로 필터링해 보세요.",
|
||||
"try-extending-time-frame": "결과를 확인하려면 시간 범위를 확장해 보세요.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "नियम नाव",
|
||||
"rule-plural": "नियम",
|
||||
"run": "चालवा",
|
||||
"run-agent-plural": "एजेंट्स चलवा",
|
||||
"run-at": "येथे चालवा",
|
||||
"run-now": "आता चालवा",
|
||||
"run-type": "चालवा प्रकार",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "<0>{{text}}</0> बॉक्समधून \"नाव\", \"वर्णन\", \"स्तंभ नाव\" आणि अशा प्रकारे जुळणारे डेटा ॲसेट्स शोधा.",
|
||||
"tour-step-trace-path-across-tables": "<0>{{text}}</0> सह, टेबल्स, पाइपलाइन आणि डॅशबोर्ड्समध्ये डेटाचा मार्ग शोधा.",
|
||||
"tour-step-type-search-term": "शोध बॉक्समध्ये, <0>\"{{text}}\"</0> टाइप करा. <0>{{enterText}}</0> दाबा.",
|
||||
"trigger-day-one-application": "दिवस एक अॅप्लिकेशन ट्रिगर करा",
|
||||
"try-adjusting-filter": "तुम्ही शोधत असलेले शोधण्यासाठी तुमचा शोध किंवा फिल्टर समायोजित करण्याचा प्रयत्न करा.",
|
||||
"try-different-time-period-filtering": "कोणतेही परिणाम उपलब्ध नाहीत. वेगळ्या कालावधीने फिल्टर करण्याचा प्रयत्न करा.",
|
||||
"try-extending-time-frame": "परिणाम पाहण्यासाठी वेळेची चौकट वाढवण्याचा प्रयत्न करा.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Regelnaam",
|
||||
"rule-plural": "Regels",
|
||||
"run": "Uitvoeren",
|
||||
"run-agent-plural": "Agents Uitvoeren",
|
||||
"run-at": "Uitvoeren op",
|
||||
"run-now": "Nu uitvoeren",
|
||||
"run-type": "Uitvoertype",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Zoek naar overeenkomende data-assets op \"naam\", \"beschrijving\", \"kolomnaam\", enzovoort vanuit het <0>{{text}}</0> vak.",
|
||||
"tour-step-trace-path-across-tables": "Met <0>{{text}}</0> kun je het pad van data over tabellen, pipelines en dashboards volgen.",
|
||||
"tour-step-type-search-term": "Typ in het zoekvak <0>\"{{text}}\"</0>. Druk op <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "De Day One-toepassing activeren",
|
||||
"try-adjusting-filter": "Probeer je zoekopdracht of filter aan te passen om te vinden wat je zoekt.",
|
||||
"try-different-time-period-filtering": "Geen resultaten beschikbaar. Probeer te filteren op een ander tijdsinterval.",
|
||||
"try-extending-time-frame": "Try extending the time frame to view the results.",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"label": {
|
||||
"aborted": "Interrumpido",
|
||||
"aborted": "لغو شده",
|
||||
"accept": "پذیرفتن",
|
||||
"accept-all": "پذیرفتن همه",
|
||||
"accept-suggestion": "پذیرفتن پیشنهاد",
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "نام قانون",
|
||||
"rule-plural": "قوانین",
|
||||
"run": "اجرا",
|
||||
"run-agent-plural": "اجرای عاملها",
|
||||
"run-at": "اجرا در",
|
||||
"run-now": "الان اجرا کنید",
|
||||
"run-type": "نوع اجرا",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "برای جستجوی داراییهای داده مشابه بر اساس \"نام\"، \"توضیحات\"، \"نام ستون\" و غیره از جعبه جستجو <0>{{text}}</0> استفاده کنید.",
|
||||
"tour-step-trace-path-across-tables": "با <0>{{text}}</0>، مسیر داده را در سراسر جداول، خطوط لوله و داشبوردها دنبال کنید.",
|
||||
"tour-step-type-search-term": "در جعبه جستجو، <0>\"{{text}}\"</0> را تایپ کنید. سپس <0>{{enterText}}.</0> را فشار دهید.",
|
||||
"trigger-day-one-application": "تریگر یکی از اپلیکیشنهای Day One",
|
||||
"try-adjusting-filter": "سعی کنید جستجو یا فیلتر خود را تنظیم کنید تا آنچه را که به دنبال آن هستید پیدا کنید.",
|
||||
"try-different-time-period-filtering": "نتایج موجود نیست. سعی کنید با یک دوره زمانی متفاوت فیلتر کنید.",
|
||||
"try-extending-time-frame": "سعی کنید بازه زمانی را گسترش دهید تا نتایج را مشاهده کنید.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Nome da Regra",
|
||||
"rule-plural": "Regras",
|
||||
"run": "Executar",
|
||||
"run-agent-plural": "Executar Agentes",
|
||||
"run-at": "Executar em",
|
||||
"run-now": "Executar agora",
|
||||
"run-type": "Tipo de Execução",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Pesquise ativos de dados correspondentes por \"nome\", \"descrição\", \"nome da coluna\", e assim por diante a partir da caixa de <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": "Com <0>{{text}}</0>, trace o caminho dos dados através de tabelas, pipelines e painéis.",
|
||||
"tour-step-type-search-term": "Na caixa de pesquisa, digite <0>\"{{text}}\"</0>. Pressione <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Ativar a aplicação Day One",
|
||||
"try-adjusting-filter": "Tente ajustar sua pesquisa ou filtro para encontrar o que está procurando.",
|
||||
"try-different-time-period-filtering": "Nenhum resultado disponível. Tente filtrar por um período de tempo diferente.",
|
||||
"try-extending-time-frame": "Tente aumentar o período de tempo para visualizar os resultados.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Nome da Regra",
|
||||
"rule-plural": "Regras",
|
||||
"run": "Executar",
|
||||
"run-agent-plural": "Executar Agentes",
|
||||
"run-at": "Executar em",
|
||||
"run-now": "Executar agora",
|
||||
"run-type": "Tipo de Execução",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Pesquise ativos de dados correspondentes por \"nome\", \"descrição\", \"nome da coluna\", e assim por diante a partir da caixa de <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": "Com <0>{{text}}</0>, trace o caminho dos dados através de tabelas, pipelines e painéis.",
|
||||
"tour-step-type-search-term": "Na caixa de pesquisa, digite <0>\"{{text}}\"</0>. Pressione <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Ativar a aplicação Day One",
|
||||
"try-adjusting-filter": "Tente ajustar sua pesquisa ou filtro para encontrar o que está procurando.",
|
||||
"try-different-time-period-filtering": "Nenhum resultado disponível. Tente filtrar por um período de tempo diferente.",
|
||||
"try-extending-time-frame": "Tente aumentar o período de tempo para visualizar os resultados.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "Наименование правила",
|
||||
"rule-plural": "Правила",
|
||||
"run": "Запустить",
|
||||
"run-agent-plural": "Запустить агенты",
|
||||
"run-at": "Run at",
|
||||
"run-now": "Run now",
|
||||
"run-type": "Run Type",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "Найдите соответствующие объекты данных по «имени», «описанию», «названию столбца» и т. д. в поле <0>{{text}}</0>.",
|
||||
"tour-step-trace-path-across-tables": "С помощью <0>{{text}}</0> отслеживайте путь данных между таблицами, пайплайнами и дашбордами.",
|
||||
"tour-step-type-search-term": "В поле поиска введите <0>\"{{текст}}\"</0>. Нажмите <0>{{enterText}}.</0>",
|
||||
"trigger-day-one-application": "Применить приложение Day One",
|
||||
"try-adjusting-filter": "Попробуйте настроить поиск или фильтр, чтобы найти то, что вы ищете.",
|
||||
"try-different-time-period-filtering": "Нет доступных результатов. Попробуйте отфильтровать по другому периоду времени.",
|
||||
"try-extending-time-frame": "Try extending the time frame to view the results.",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "ชื่อกฎ",
|
||||
"rule-plural": "กฎหลายรายการ",
|
||||
"run": "รัน",
|
||||
"run-agent-plural": "รันเอเจนต์",
|
||||
"run-at": "รันที่",
|
||||
"run-now": "รันตอนนี้",
|
||||
"run-type": "ประเภทการรัน",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "ค้นหาสินทรัพย์ข้อมูลที่ตรงกันโดยใช้ \"ชื่อ\", \"คำอธิบาย\", \"ชื่อคอลัมน์\" และอื่น ๆ จากกล่อง <0>{{text}}</0>",
|
||||
"tour-step-trace-path-across-tables": "ด้วย <0>{{text}}</0>, ติดตามเส้นทางของข้อมูลข้ามตาราง, ท่อ, & แดชบอร์ด",
|
||||
"tour-step-type-search-term": "ในกล่องค้นหา, พิมพ์ <0>\"{{text}}\"</0>. กด <0>{{enterText}}</0>",
|
||||
"trigger-day-one-application": "เปิดใช้งานแอพพลิเคชัน Day One",
|
||||
"try-adjusting-filter": "ลองปรับการค้นหาหรือกรองเพื่อหาสิ่งที่คุณกำลังมองหา",
|
||||
"try-different-time-period-filtering": "ไม่มีผลลัพธ์ที่สามารถใช้งานได้ ลองกรองด้วยช่วงเวลาที่แตกต่างกัน",
|
||||
"try-extending-time-frame": "ลองขยายกรอบเวลาเพื่อดูผลลัพธ์",
|
||||
|
||||
@ -1155,6 +1155,7 @@
|
||||
"rule-name": "规则名称",
|
||||
"rule-plural": "规则",
|
||||
"run": "运行",
|
||||
"run-agent-plural": "运行代理",
|
||||
"run-at": "运行于",
|
||||
"run-now": "立即运行",
|
||||
"run-type": "运行类型",
|
||||
@ -2110,6 +2111,7 @@
|
||||
"tour-step-search-for-matching-dataset": "通过在<0>{{text}}</0>框中输入\"名称\"、\"描述\"、\"列名\"等关键字搜索匹配数据资产。",
|
||||
"tour-step-trace-path-across-tables": "使用<0>{{text}}</0>, 跟踪数据在表、工作流和仪表板之间的路径。",
|
||||
"tour-step-type-search-term": "在搜索框中输入<0>\"{{text}}\"</0>, 并在键盘上点击<0>{{enterText}}</0>回车键。",
|
||||
"trigger-day-one-application": "触发 Day One 应用程序",
|
||||
"try-adjusting-filter": "没有找到相关的数据, 请修改搜索或过滤条件。",
|
||||
"try-different-time-period-filtering": "没有可用的结果, 请选择不同的时间段再次过滤",
|
||||
"try-extending-time-frame": "尝试延长时间框架以查看结果",
|
||||
|
||||
@ -268,6 +268,7 @@ const AddServicePage = () => {
|
||||
{activeServiceStep === 3 && (
|
||||
<ConnectionConfigForm
|
||||
cancelText={t('label.back')}
|
||||
data={serviceConfig as ServicesType}
|
||||
okText={t('label.next')}
|
||||
serviceCategory={serviceCategory}
|
||||
serviceType={serviceConfig.serviceType}
|
||||
|
||||
@ -40,6 +40,7 @@ import { DataAssetsHeader } from '../../components/DataAssets/DataAssetsHeader/D
|
||||
import { EntityName } from '../../components/Modals/EntityNameModal/EntityNameModal.interface';
|
||||
import PageLayoutV1 from '../../components/PageLayoutV1/PageLayoutV1';
|
||||
import ServiceInsightsTab from '../../components/ServiceInsights/ServiceInsightsTab';
|
||||
import { WorkflowStatesData } from '../../components/ServiceInsights/ServiceInsightsTab.interface';
|
||||
import Ingestion from '../../components/Settings/Services/Ingestion/Ingestion.component';
|
||||
import ServiceConnectionDetails from '../../components/Settings/Services/ServiceConnectionDetails/ServiceConnectionDetails.component';
|
||||
import {
|
||||
@ -49,6 +50,7 @@ import {
|
||||
ROUTES,
|
||||
} from '../../constants/constants';
|
||||
import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.constants';
|
||||
import { SERVICE_INSIGHTS_WORKFLOW_DEFINITION_NAME } from '../../constants/ServiceInsightsTab.constants';
|
||||
import {
|
||||
OPEN_METADATA,
|
||||
SERVICE_INGESTION_PIPELINE_TYPES,
|
||||
@ -78,6 +80,7 @@ import { StoredProcedure } from '../../generated/entity/data/storedProcedure';
|
||||
import { Topic } from '../../generated/entity/data/topic';
|
||||
import { DashboardConnection } from '../../generated/entity/services/dashboardService';
|
||||
import { IngestionPipeline } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { WorkflowStatus } from '../../generated/governance/workflows/workflowInstance';
|
||||
import { Include } from '../../generated/type/include';
|
||||
import { Paging } from '../../generated/type/paging';
|
||||
import { useAuth } from '../../hooks/authHooks';
|
||||
@ -106,9 +109,17 @@ import {
|
||||
} from '../../rest/serviceAPI';
|
||||
import { getContainers } from '../../rest/storageAPI';
|
||||
import { getTopics } from '../../rest/topicsAPI';
|
||||
import {
|
||||
getWorkflowInstancesForApplication,
|
||||
getWorkflowInstanceStateById,
|
||||
} from '../../rest/workflowAPI';
|
||||
import { getEntityMissingError } from '../../utils/CommonUtils';
|
||||
import {
|
||||
getCurrentMillis,
|
||||
getDayAgoStartGMTinMillis,
|
||||
} from '../../utils/date-time/DateTimeUtils';
|
||||
import entityUtilClassBase from '../../utils/EntityUtilClassBase';
|
||||
import { getEntityName } from '../../utils/EntityUtils';
|
||||
import { getEntityFeedLink, getEntityName } from '../../utils/EntityUtils';
|
||||
import { DEFAULT_ENTITY_PERMISSION } from '../../utils/PermissionsUtils';
|
||||
import {
|
||||
getEditConnectionPath,
|
||||
@ -173,6 +184,9 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
const ingestionPagingInfo = usePaging(PAGE_SIZE_BASE);
|
||||
const collateAgentPagingInfo = usePaging(PAGE_SIZE_BASE);
|
||||
const pagingInfo = usePaging(PAGE_SIZE_BASE);
|
||||
const [workflowStatesData, setWorkflowStatesData] =
|
||||
useState<WorkflowStatesData>();
|
||||
const [isWorkflowStatusLoading, setIsWorkflowStatusLoading] = useState(true);
|
||||
|
||||
const {
|
||||
paging: collateAgentPaging,
|
||||
@ -354,6 +368,45 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
[activeTab, decodedServiceFQN, serviceCategory]
|
||||
);
|
||||
|
||||
const fetchWorkflowInstanceStates = useCallback(async () => {
|
||||
try {
|
||||
setIsWorkflowStatusLoading(true);
|
||||
const startTs = getDayAgoStartGMTinMillis(6);
|
||||
const endTs = getCurrentMillis();
|
||||
const entityType = getEntityTypeFromServiceCategory(serviceCategory);
|
||||
const workflowInstances = await getWorkflowInstancesForApplication({
|
||||
startTs,
|
||||
endTs,
|
||||
workflowDefinitionName: SERVICE_INSIGHTS_WORKFLOW_DEFINITION_NAME,
|
||||
entityLink: getEntityFeedLink(
|
||||
entityType,
|
||||
serviceDetails.fullyQualifiedName
|
||||
),
|
||||
});
|
||||
|
||||
const workflowInstanceId = workflowInstances.data[0]?.id;
|
||||
|
||||
if (workflowInstanceId) {
|
||||
const workflowInstanceStates = await getWorkflowInstanceStateById(
|
||||
SERVICE_INSIGHTS_WORKFLOW_DEFINITION_NAME,
|
||||
workflowInstanceId,
|
||||
{
|
||||
startTs,
|
||||
endTs,
|
||||
}
|
||||
);
|
||||
setWorkflowStatesData({
|
||||
mainInstanceState: workflowInstances.data[0],
|
||||
subInstanceStates: workflowInstanceStates.data,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsWorkflowStatusLoading(false);
|
||||
}
|
||||
}, [serviceDetails.fullyQualifiedName, serviceCategory]);
|
||||
|
||||
const fetchCollateAgentsList = useCallback(
|
||||
async (paging?: Omit<Paging, 'total'>) => {
|
||||
try {
|
||||
@ -661,7 +714,7 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
} catch {
|
||||
setData([]);
|
||||
handlePagingChange(pagingObject);
|
||||
} finally {
|
||||
@ -989,6 +1042,15 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
]
|
||||
);
|
||||
|
||||
const disableRunAgentsButton = useMemo(
|
||||
() =>
|
||||
workflowStatesData?.mainInstanceState.status &&
|
||||
![WorkflowStatus.Exception, WorkflowStatus.Failure].includes(
|
||||
workflowStatesData?.mainInstanceState.status
|
||||
),
|
||||
[workflowStatesData?.mainInstanceState.status]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
handlePageChange(INITIAL_PAGING_VALUE);
|
||||
getOtherDetails({ limit: pageSize });
|
||||
@ -1038,6 +1100,10 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
}
|
||||
}, [collateAgentPageSize]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchWorkflowInstanceStates();
|
||||
}, [serviceDetails.fullyQualifiedName]);
|
||||
|
||||
const agentCounts = useMemo(() => {
|
||||
return {
|
||||
[ServiceAgentSubTabs.COLLATE_AI]: collateAgentPaging.total,
|
||||
@ -1209,7 +1275,13 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
{
|
||||
name: t('label.insight-plural'),
|
||||
key: EntityTabs.INSIGHTS,
|
||||
children: <ServiceInsightsTab serviceDetails={serviceDetails} />,
|
||||
children: (
|
||||
<ServiceInsightsTab
|
||||
isWorkflowStatusLoading={isWorkflowStatusLoading}
|
||||
serviceDetails={serviceDetails}
|
||||
workflowStatesData={workflowStatesData}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: getCountLabel(serviceCategory),
|
||||
@ -1298,6 +1370,8 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
testConnectionTab,
|
||||
activeTab,
|
||||
isMetadataService,
|
||||
workflowStatesData,
|
||||
isWorkflowStatusLoading,
|
||||
]);
|
||||
|
||||
if (isLoading) {
|
||||
@ -1320,14 +1394,17 @@ const ServiceDetailsPage: FunctionComponent = () => {
|
||||
</ErrorPlaceHolder>
|
||||
) : (
|
||||
<Row data-testid="service-page" gutter={[0, 12]}>
|
||||
<Col className="" span={24}>
|
||||
<Col span={24}>
|
||||
<DataAssetsHeader
|
||||
isRecursiveDelete
|
||||
afterDeleteAction={afterDeleteAction}
|
||||
afterDomainUpdateAction={afterDomainUpdateAction}
|
||||
afterTriggerAction={fetchWorkflowInstanceStates}
|
||||
dataAsset={serviceDetails}
|
||||
disableRunAgentsButton={disableRunAgentsButton}
|
||||
entityType={entityType}
|
||||
extraDropdownContent={extraDropdownContent}
|
||||
isDayOneWorkflowStatusLoading={isWorkflowStatusLoading}
|
||||
permissions={servicePermission}
|
||||
showDomain={!isMetadataService}
|
||||
onDisplayNameUpdate={handleUpdateDisplayName}
|
||||
|
||||
@ -242,83 +242,81 @@ function ServiceMainTabContent({
|
||||
firstPanel={{
|
||||
className: 'entity-resizable-panel-container',
|
||||
children: (
|
||||
<div className="p-t-sm m-x-lg">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col data-testid="description-container" span={24}>
|
||||
<DescriptionV1
|
||||
description={serviceDetails.description}
|
||||
entityName={serviceName}
|
||||
entityType={entityType}
|
||||
hasEditAccess={editDescriptionPermission}
|
||||
showActions={!serviceDetails.deleted}
|
||||
showCommentsIcon={false}
|
||||
onDescriptionUpdate={handleDescriptionUpdate}
|
||||
/>
|
||||
</Col>
|
||||
<Col data-testid="table-container" span={24}>
|
||||
<Space
|
||||
className="w-full m-b-md"
|
||||
direction="vertical"
|
||||
size="large">
|
||||
{isServiceLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<Table
|
||||
columns={tableColumn}
|
||||
customPaginationProps={{
|
||||
currentPage,
|
||||
isLoading: isServiceLoading,
|
||||
showPagination:
|
||||
!isUndefined(pagingInfo) &&
|
||||
pagingInfo.showPagination,
|
||||
pageSize: pagingInfo.pageSize,
|
||||
paging,
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col data-testid="description-container" span={24}>
|
||||
<DescriptionV1
|
||||
description={serviceDetails.description}
|
||||
entityName={serviceName}
|
||||
entityType={entityType}
|
||||
hasEditAccess={editDescriptionPermission}
|
||||
showActions={!serviceDetails.deleted}
|
||||
showCommentsIcon={false}
|
||||
onDescriptionUpdate={handleDescriptionUpdate}
|
||||
/>
|
||||
</Col>
|
||||
<Col data-testid="table-container" span={24}>
|
||||
<Space
|
||||
className="w-full m-b-md"
|
||||
direction="vertical"
|
||||
size="large">
|
||||
{isServiceLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<Table
|
||||
columns={tableColumn}
|
||||
customPaginationProps={{
|
||||
currentPage,
|
||||
isLoading: isServiceLoading,
|
||||
showPagination:
|
||||
!isUndefined(pagingInfo) &&
|
||||
pagingInfo.showPagination,
|
||||
pageSize: pagingInfo.pageSize,
|
||||
paging,
|
||||
|
||||
pagingHandler: pagingHandler,
|
||||
onShowSizeChange: pagingInfo.handlePageSizeChange,
|
||||
}}
|
||||
data-testid="service-children-table"
|
||||
dataSource={pageData}
|
||||
defaultVisibleColumns={
|
||||
DEFAULT_SERVICE_TAB_VISIBLE_COLUMNS
|
||||
}
|
||||
entityType={serviceCategory}
|
||||
extraTableFilters={
|
||||
<>
|
||||
<span>
|
||||
<Switch
|
||||
checked={showDeleted}
|
||||
data-testid="show-deleted"
|
||||
onClick={onShowDeletedChange}
|
||||
/>
|
||||
<Typography.Text className="m-l-xs">
|
||||
{t('label.deleted')}
|
||||
</Typography.Text>
|
||||
</span>
|
||||
pagingHandler: pagingHandler,
|
||||
onShowSizeChange: pagingInfo.handlePageSizeChange,
|
||||
}}
|
||||
data-testid="service-children-table"
|
||||
dataSource={pageData}
|
||||
defaultVisibleColumns={
|
||||
DEFAULT_SERVICE_TAB_VISIBLE_COLUMNS
|
||||
}
|
||||
entityType={serviceCategory}
|
||||
extraTableFilters={
|
||||
<>
|
||||
<span>
|
||||
<Switch
|
||||
checked={showDeleted}
|
||||
data-testid="show-deleted"
|
||||
onClick={onShowDeletedChange}
|
||||
/>
|
||||
<Typography.Text className="m-l-xs">
|
||||
{t('label.deleted')}
|
||||
</Typography.Text>
|
||||
</span>
|
||||
|
||||
{entityType === EntityType.DATABASE_SERVICE &&
|
||||
getBulkEditButton(
|
||||
servicePermission.EditAll &&
|
||||
!serviceDetails.deleted,
|
||||
handleEditTable
|
||||
)}
|
||||
</>
|
||||
}
|
||||
locale={{
|
||||
emptyText: <ErrorPlaceHolder className="m-y-md" />,
|
||||
}}
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
size="small"
|
||||
staticVisibleColumns={
|
||||
COMMON_STATIC_TABLE_VISIBLE_COLUMNS
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
{entityType === EntityType.DATABASE_SERVICE &&
|
||||
getBulkEditButton(
|
||||
servicePermission.EditAll &&
|
||||
!serviceDetails.deleted,
|
||||
handleEditTable
|
||||
)}
|
||||
</>
|
||||
}
|
||||
locale={{
|
||||
emptyText: <ErrorPlaceHolder className="m-y-md" />,
|
||||
}}
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
size="small"
|
||||
staticVisibleColumns={
|
||||
COMMON_STATIC_TABLE_VISIBLE_COLUMNS
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
),
|
||||
...COMMON_RESIZABLE_PANEL_CONFIG.LEFT_PANEL,
|
||||
}}
|
||||
|
||||
@ -45,7 +45,6 @@
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.main-tab-content,
|
||||
.connection-tab-content {
|
||||
background-color: @white;
|
||||
border-radius: @border-radius-sm;
|
||||
|
||||
@ -117,9 +117,24 @@ button {
|
||||
height: 40px;
|
||||
min-width: 50px;
|
||||
padding: 10px 16px;
|
||||
background-color: @background-color;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 1px 2px 0px #0a0d120f, 0px 1px 3px 0px #0a0d121a;
|
||||
}
|
||||
|
||||
.ant-btn-primary:first-child:not(:last-child) {
|
||||
border-right-color: transparent;
|
||||
}
|
||||
|
||||
.ant-btn-default:not(.ant-btn-primary):not([disabled]) {
|
||||
border-left-color: @blue-15;
|
||||
|
||||
&:hover {
|
||||
border-left-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-btn-default {
|
||||
background-color: @background-color;
|
||||
|
||||
&:hover {
|
||||
background-color: @blue-11;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user