From dfa732e2384679f107724b95edab1c1a483ecc2f Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 24 Oct 2023 11:49:29 -0600 Subject: [PATCH] OpenAI Preconfigured Connector Dashboard Link (#169148) (cherry picked from commit 75e9d46b4b3a6ff5be4ffc324ba282cea0faea0c) --- .../connector_types/openai/connector.tsx | 35 ++++---------- .../connector_types/openai/dashboard_link.tsx | 48 +++++++++++++++++++ .../public/connector_types/openai/openai.tsx | 1 + .../edit_connector_flyout/index.tsx | 35 ++++---------- .../edit_connector_flyout/read_only.test.tsx | 46 ++++++++++++++++++ .../edit_connector_flyout/read_only.tsx | 42 ++++++++++++++++ .../triggers_actions_ui/public/types.ts | 7 +++ 7 files changed, 161 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/read_only.test.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/read_only.tsx diff --git a/x-pack/plugins/stack_connectors/public/connector_types/openai/connector.tsx b/x-pack/plugins/stack_connectors/public/connector_types/openai/connector.tsx index 516ff9c3e9264..c940ad76e3643 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/openai/connector.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/openai/connector.tsx @@ -5,22 +5,21 @@ * 2.0. */ -import React, { useCallback, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { ActionConnectorFieldsProps, SimpleConnectorForm, } from '@kbn/triggers-actions-ui-plugin/public'; import { SelectField } from '@kbn/es-ui-shared-plugin/static/forms/components'; -import { EuiLink, EuiSpacer } from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; import { UseField, useFormContext, useFormData, } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; -import { useKibana } from '@kbn/triggers-actions-ui-plugin/public'; import { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; +import DashboardLink from './dashboard_link'; import { OpenAiProviderType } from '../../../common/openai/constants'; -import { useGetDashboard } from './use_get_dashboard'; import * as i18n from './translations'; import { azureAiConfig, @@ -37,24 +36,6 @@ const ConnectorFields: React.FC = ({ readOnly, isEdi watch: ['config.apiProvider'], }); - const { - services: { - application: { navigateToUrl }, - }, - } = useKibana(); - - const { dashboardUrl } = useGetDashboard({ connectorId: id }); - - const onClick = useCallback( - (e) => { - e.preventDefault(); - if (dashboardUrl) { - navigateToUrl(dashboardUrl); - } - }, - [dashboardUrl, navigateToUrl] - ); - const selectedProviderDefaultValue = useMemo( () => getFieldDefaultValue('config.apiProvider') ?? OpenAiProviderType.OpenAi, @@ -104,10 +85,12 @@ const ConnectorFields: React.FC = ({ readOnly, isEdi secretsFormSchema={azureAiSecrets} /> )} - {isEdit && dashboardUrl != null && ( - - {i18n.USAGE_DASHBOARD_LINK(selectedProviderDefaultValue, name)} - + {isEdit && ( + )} ); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx b/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx new file mode 100644 index 0000000000000..b7d6ef972372d --- /dev/null +++ b/x-pack/plugins/stack_connectors/public/connector_types/openai/dashboard_link.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { EuiLink } from '@elastic/eui'; +import { useKibana } from '@kbn/triggers-actions-ui-plugin/public'; +import * as i18n from './translations'; +import { useGetDashboard } from './use_get_dashboard'; + +interface Props { + connectorId: string; + connectorName: string; + selectedProvider?: string; +} +// tested from ./connector.test.tsx +export const DashboardLink: React.FC = ({ + connectorId, + connectorName, + selectedProvider = '', +}) => { + const { dashboardUrl } = useGetDashboard({ connectorId }); + const { + services: { + application: { navigateToUrl }, + }, + } = useKibana(); + const onClick = useCallback( + (e) => { + e.preventDefault(); + if (dashboardUrl) { + navigateToUrl(dashboardUrl); + } + }, + [dashboardUrl, navigateToUrl] + ); + return dashboardUrl != null ? ( + + {i18n.USAGE_DASHBOARD_LINK(selectedProvider, connectorName)} + + ) : null; +}; + +// eslint-disable-next-line import/no-default-export +export { DashboardLink as default }; diff --git a/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.tsx b/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.tsx index 35312cdda3b27..3fe382e9b7030 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.tsx @@ -57,5 +57,6 @@ export function getConnectorType(): OpenAIConnector { }, actionConnectorFields: lazy(() => import('./connector')), actionParamsFields: lazy(() => import('./params')), + actionReadOnlyExtraComponent: lazy(() => import('./dashboard_link')), }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx index 343e0b01c4782..2be497ebdd920 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/index.tsx @@ -6,18 +6,12 @@ */ import React, { memo, ReactNode, useCallback, useEffect, useRef, useState } from 'react'; -import { - EuiFlyout, - EuiText, - EuiFlyoutBody, - EuiLink, - EuiButton, - EuiConfirmModal, -} from '@elastic/eui'; +import { EuiFlyout, EuiFlyoutBody, EuiButton, EuiConfirmModal } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { ActionTypeExecutorResult, isActionTypeExecutorResult } from '@kbn/actions-plugin/common'; import { Option, none, some } from 'fp-ts/lib/Option'; +import { ReadOnlyConnectorMessage } from './read_only'; import { ActionConnector, ActionTypeModel, @@ -51,24 +45,6 @@ const getConnectorWithoutSecrets = ( secrets: {}, }); -const ReadOnlyConnectorMessage: React.FC<{ href: string }> = ({ href }) => { - return ( - <> - - {i18n.translate('xpack.triggersActionsUI.sections.editConnectorForm.descriptionText', { - defaultMessage: 'This connector is readonly.', - })} - - - - - - ); -}; - const EditConnectorFlyoutComponent: React.FC = ({ actionTypeRegistry, connector, @@ -299,7 +275,12 @@ const EditConnectorFlyoutComponent: React.FC = ({ )} ) : ( - + ) ) : ( ( +
Extra Component
+)) as unknown as ActionTypeModel['actionReadOnlyExtraComponent']; +describe('ReadOnlyConnectorMessage', () => { + it('should render a readonly message with a link to the provided href', () => { + const { getByTestId, getByText, queryByText } = render( + , + { wrapper: I18nProvider } + ); + + expect(getByText('This connector is readonly.')).toBeInTheDocument(); + expect(getByTestId('read-only-link')).toHaveProperty('href', 'https://example.com/'); + expect(queryByText('Extra Component')).toBeNull(); + }); + + it('should render an extra component if provided', () => { + const { getByText } = render( + , + { wrapper: I18nProvider } + ); + + expect(getByText('Extra Component')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/read_only.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/read_only.tsx new file mode 100644 index 0000000000000..f32bc2a34bd6b --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/edit_connector_flyout/read_only.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { ActionTypeModel } from '../../../..'; + +export const ReadOnlyConnectorMessage: React.FC<{ + connectorId: string; + connectorName: string; + extraComponent?: ActionTypeModel['actionReadOnlyExtraComponent']; + href: string; +}> = ({ connectorId, connectorName, extraComponent, href }) => { + const ExtraComponent = extraComponent; + return ( + <> + + {i18n.translate('xpack.triggersActionsUI.sections.editConnectorForm.descriptionText', { + defaultMessage: 'This connector is readonly.', + })} + + + + + {ExtraComponent && ( + <> + + + + )} + + ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index b62bffec63d2c..5909176c143df 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -170,6 +170,10 @@ export interface ActionConnectorFieldsProps { isEdit: boolean; registerPreSubmitValidator: (validator: ConnectorValidationFunc) => void; } +export interface ActionReadOnlyElementProps { + connectorId: string; + connectorName: string; +} export enum RuleFlyoutCloseReason { SAVED, @@ -254,6 +258,9 @@ export interface ActionTypeModel > | null; actionParamsFields: React.LazyExoticComponent>>; + actionReadOnlyExtraComponent?: React.LazyExoticComponent< + ComponentType + >; defaultActionParams?: RecursivePartial; defaultRecoveredActionParams?: RecursivePartial; customConnectorSelectItem?: CustomConnectorSelectionItem;