mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Enterprise Search] Name and description flyout for connectors (#143827)
This commit is contained in:
parent
879b101669
commit
8974e826bf
9 changed files with 219 additions and 84 deletions
|
@ -191,7 +191,7 @@ export const indices: ElasticsearchIndexWithIngestion[] = [
|
|||
count: 1,
|
||||
crawler: {
|
||||
id: '5',
|
||||
index_name: 'crawler',
|
||||
index_name: 'connector-crawler',
|
||||
},
|
||||
hidden: false,
|
||||
name: 'crawler',
|
||||
|
|
|
@ -205,7 +205,7 @@ export const crawlerIndex: CrawlerViewIndex = {
|
|||
count: 1,
|
||||
crawler: {
|
||||
id: '5',
|
||||
index_name: 'crawler',
|
||||
index_name: 'connector-crawler',
|
||||
},
|
||||
hidden: false,
|
||||
ingestionMethod: IngestionMethod.CRAWLER,
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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 { useValues, useActions } from 'kea';
|
||||
|
||||
import {
|
||||
EuiFlyout,
|
||||
EuiFlyoutHeader,
|
||||
EuiFlyoutBody,
|
||||
EuiFormRow,
|
||||
EuiText,
|
||||
EuiSpacer,
|
||||
EuiFlyoutFooter,
|
||||
EuiButtonEmpty,
|
||||
EuiButton,
|
||||
EuiTitle,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { Status } from '../../../../../../../common/types/api';
|
||||
import { CANCEL_BUTTON_LABEL } from '../../../../../shared/constants';
|
||||
|
||||
import { ConnectorNameAndDescriptionApiLogic } from '../../../../api/connector/update_connector_name_and_description_api_logic';
|
||||
|
||||
import { ConnectorNameAndDescriptionFormContent } from './connector_name_and_description_form_content';
|
||||
import { ConnectorNameAndDescriptionLogic } from './connector_name_and_description_logic';
|
||||
|
||||
export const ConnectorNameAndDescriptionFlyout: React.FC = () => {
|
||||
const { status } = useValues(ConnectorNameAndDescriptionApiLogic);
|
||||
const { isEditing } = useValues(ConnectorNameAndDescriptionLogic);
|
||||
const { saveNameAndDescription, setIsEditing } = useActions(ConnectorNameAndDescriptionLogic);
|
||||
|
||||
if (!isEditing) return null;
|
||||
|
||||
return (
|
||||
<EuiFlyout onClose={() => setIsEditing(false)} size="s">
|
||||
<EuiFlyoutHeader>
|
||||
<EuiTitle size="m">
|
||||
<h3>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescriptionFlyout.title',
|
||||
{
|
||||
defaultMessage: 'Describe this crawler',
|
||||
}
|
||||
)}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
|
||||
<EuiFlyoutBody>
|
||||
<EuiFormRow>
|
||||
<EuiText size="s">
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescriptionFlyout.description',
|
||||
{
|
||||
defaultMessage:
|
||||
'By naming and describing this connector your colleagues and wider team will know what this connector is meant for.',
|
||||
}
|
||||
)}
|
||||
</EuiText>
|
||||
</EuiFormRow>
|
||||
<EuiSpacer />
|
||||
<ConnectorNameAndDescriptionFormContent />
|
||||
</EuiFlyoutBody>
|
||||
|
||||
<EuiFlyoutFooter>
|
||||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
onClick={() => setIsEditing(false)}
|
||||
isLoading={status === Status.LOADING}
|
||||
>
|
||||
{CANCEL_BUTTON_LABEL}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton isLoading={status === Status.LOADING} fill onClick={saveNameAndDescription}>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.content.indices.configurationConnector.nameAndDescriptionFlyout.saveButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Save name and description',
|
||||
}
|
||||
)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlyoutFooter>
|
||||
</EuiFlyout>
|
||||
);
|
||||
};
|
|
@ -12,40 +12,23 @@ import { useActions, useValues } from 'kea';
|
|||
import {
|
||||
EuiButton,
|
||||
EuiButtonEmpty,
|
||||
EuiFieldText,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiForm,
|
||||
EuiFormRow,
|
||||
EuiTextArea,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { Status } from '../../../../../../../common/types/api';
|
||||
import {
|
||||
NAME_LABEL,
|
||||
DESCRIPTION_LABEL,
|
||||
SAVE_BUTTON_LABEL,
|
||||
CANCEL_BUTTON_LABEL,
|
||||
} from '../../../../../shared/constants';
|
||||
import { SAVE_BUTTON_LABEL, CANCEL_BUTTON_LABEL } from '../../../../../shared/constants';
|
||||
import { ConnectorNameAndDescriptionApiLogic } from '../../../../api/connector/update_connector_name_and_description_api_logic';
|
||||
import { isConnectorIndex } from '../../../../utils/indices';
|
||||
import { IndexViewLogic } from '../../index_view_logic';
|
||||
|
||||
import { ConnectorNameAndDescriptionFormContent } from './connector_name_and_description_form_content';
|
||||
import { ConnectorNameAndDescriptionLogic } from './connector_name_and_description_logic';
|
||||
|
||||
export const ConnectorNameAndDescriptionForm: React.FC = () => {
|
||||
const { index } = useValues(IndexViewLogic);
|
||||
const { status } = useValues(ConnectorNameAndDescriptionApiLogic);
|
||||
const {
|
||||
localNameAndDescription: { name, description },
|
||||
} = useValues(ConnectorNameAndDescriptionLogic);
|
||||
const { saveNameAndDescription, setIsEditing, updateLocalNameAndDescription } = useActions(
|
||||
ConnectorNameAndDescriptionLogic
|
||||
);
|
||||
|
||||
if (!isConnectorIndex(index)) {
|
||||
return <></>;
|
||||
}
|
||||
const { saveNameAndDescription, setIsEditing } = useActions(ConnectorNameAndDescriptionLogic);
|
||||
|
||||
return (
|
||||
<EuiForm
|
||||
|
@ -55,24 +38,7 @@ export const ConnectorNameAndDescriptionForm: React.FC = () => {
|
|||
}}
|
||||
component="form"
|
||||
>
|
||||
<EuiFormRow label={NAME_LABEL}>
|
||||
<EuiFieldText
|
||||
required
|
||||
value={name ?? ''}
|
||||
onChange={(event) => {
|
||||
updateLocalNameAndDescription({ name: event.target.value });
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow label={DESCRIPTION_LABEL}>
|
||||
<EuiTextArea
|
||||
placeholder={'Optional'}
|
||||
value={description || ''}
|
||||
onChange={(event) => {
|
||||
updateLocalNameAndDescription({ description: event.target.value });
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<ConnectorNameAndDescriptionFormContent />
|
||||
<EuiFormRow>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 { useActions, useValues } from 'kea';
|
||||
|
||||
import { EuiFieldText, EuiFormRow, EuiTextArea } from '@elastic/eui';
|
||||
|
||||
import { NAME_LABEL, DESCRIPTION_LABEL, OPTIONAL_LABEL } from '../../../../../shared/constants';
|
||||
|
||||
import { ConnectorNameAndDescriptionLogic } from './connector_name_and_description_logic';
|
||||
|
||||
export const ConnectorNameAndDescriptionFormContent: React.FC = () => {
|
||||
const {
|
||||
localNameAndDescription: { name, description },
|
||||
} = useValues(ConnectorNameAndDescriptionLogic);
|
||||
const { updateLocalNameAndDescription } = useActions(ConnectorNameAndDescriptionLogic);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiFormRow label={NAME_LABEL}>
|
||||
<EuiFieldText
|
||||
required
|
||||
value={name ?? ''}
|
||||
onChange={(event) => {
|
||||
updateLocalNameAndDescription({ name: event.target.value });
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow label={DESCRIPTION_LABEL}>
|
||||
<EuiTextArea
|
||||
placeholder={OPTIONAL_LABEL}
|
||||
value={description || ''}
|
||||
onChange={(event) => {
|
||||
updateLocalNameAndDescription({ description: event.target.value });
|
||||
}}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -26,7 +26,7 @@ import {
|
|||
CachedFetchIndexApiLogicActions,
|
||||
} from '../../../../api/index/cached_fetch_index_api_logic';
|
||||
import { FetchIndexApiResponse } from '../../../../api/index/fetch_index_api_logic';
|
||||
import { isConnectorIndex } from '../../../../utils/indices';
|
||||
import { isConnectorIndex, isCrawlerIndex } from '../../../../utils/indices';
|
||||
|
||||
type NameAndDescription = Partial<Pick<Connector, 'name' | 'description'>>;
|
||||
|
||||
|
@ -72,7 +72,9 @@ export const ConnectorNameAndDescriptionLogic = kea<
|
|||
},
|
||||
events: ({ actions, values }) => ({
|
||||
afterMount: () =>
|
||||
actions.setNameAndDescription(isConnectorIndex(values.index) ? values.index.connector : {}),
|
||||
actions.setNameAndDescription(
|
||||
isConnectorIndex(values.index) || isCrawlerIndex(values.index) ? values.index.connector : {}
|
||||
),
|
||||
}),
|
||||
listeners: ({ actions, values }) => ({
|
||||
apiError: (error) => flashAPIErrors(error),
|
||||
|
@ -92,7 +94,7 @@ export const ConnectorNameAndDescriptionLogic = kea<
|
|||
},
|
||||
makeRequest: () => clearFlashMessages(),
|
||||
saveNameAndDescription: () => {
|
||||
if (isConnectorIndex(values.index)) {
|
||||
if (isConnectorIndex(values.index) || isCrawlerIndex(values.index)) {
|
||||
actions.makeRequest({
|
||||
connectorId: values.index.connector.id,
|
||||
indexName: values.index.connector.index_name,
|
||||
|
|
|
@ -9,10 +9,18 @@ import React from 'react';
|
|||
|
||||
import { useValues } from 'kea';
|
||||
|
||||
import { EuiStatProps, EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat } from '@elastic/eui';
|
||||
import {
|
||||
EuiStatProps,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPanel,
|
||||
EuiStat,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { CrawlerLogic } from './crawler/crawler_logic';
|
||||
import { NameAndDescriptionStats } from './name_and_description_stats';
|
||||
import { OverviewLogic } from './overview.logic';
|
||||
|
||||
export const CrawlerTotalStats: React.FC = () => {
|
||||
|
@ -60,14 +68,18 @@ export const CrawlerTotalStats: React.FC = () => {
|
|||
];
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="row">
|
||||
{stats.map((item, index) => (
|
||||
<EuiFlexItem key={index}>
|
||||
<EuiPanel color={index === 0 ? 'primary' : 'subdued'} hasShadow={false} paddingSize="l">
|
||||
<EuiStat {...item} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
<>
|
||||
<NameAndDescriptionStats />
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup direction="row">
|
||||
{stats.map((item, index) => (
|
||||
<EuiFlexItem key={index}>
|
||||
<EuiPanel color={index === 0 ? 'primary' : 'subdued'} hasShadow={false} paddingSize="l">
|
||||
<EuiStat {...item} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,55 +5,58 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { MouseEventHandler } from 'react';
|
||||
|
||||
import { useValues } from 'kea';
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiStat, EuiStatProps, EuiText } from '@elastic/eui';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPanel,
|
||||
EuiStat,
|
||||
EuiStatProps,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { DESCRIPTION_LABEL, NAME_LABEL } from '../../../shared/constants';
|
||||
import { generateEncodedPath } from '../../../shared/encode_path_params';
|
||||
import { EuiLinkTo } from '../../../shared/react_router_helpers';
|
||||
import { SEARCH_INDEX_TAB_PATH } from '../../routes';
|
||||
import { isConnectorIndex } from '../../utils/indices';
|
||||
import { isConnectorIndex, isCrawlerIndex } from '../../utils/indices';
|
||||
|
||||
import { IndexNameLogic } from './index_name_logic';
|
||||
import { ConnectorNameAndDescriptionFlyout } from './connector/connector_name_and_description/connector_name_and_description_flyout';
|
||||
import { ConnectorNameAndDescriptionLogic } from './connector/connector_name_and_description/connector_name_and_description_logic';
|
||||
import { OverviewLogic } from './overview.logic';
|
||||
import { SearchIndexTabId } from './search_index';
|
||||
|
||||
const EditDescription: React.FC<{ label: string; indexName: string }> = ({ label, indexName }) => (
|
||||
const EditDescription: React.FC<{
|
||||
label: string;
|
||||
onClick: MouseEventHandler<HTMLButtonElement>;
|
||||
}> = ({ label, onClick }) => (
|
||||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={false}>{label}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLinkTo
|
||||
to={generateEncodedPath(SEARCH_INDEX_TAB_PATH, {
|
||||
indexName,
|
||||
tabId: SearchIndexTabId.CONFIGURATION,
|
||||
})}
|
||||
>
|
||||
Edit
|
||||
</EuiLinkTo>
|
||||
<EuiButtonEmpty onClick={onClick}>Edit</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
||||
export const NameAndDescriptionStats: React.FC = () => {
|
||||
const { indexName } = useValues(IndexNameLogic);
|
||||
const { indexData, isError, isLoading } = useValues(OverviewLogic);
|
||||
const hideStats = isLoading || isError;
|
||||
const { setIsEditing: setIsFlyoutVisible } = useActions(ConnectorNameAndDescriptionLogic);
|
||||
|
||||
if (!isConnectorIndex(indexData)) {
|
||||
if (!(isConnectorIndex(indexData) || isCrawlerIndex(indexData))) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const stats: EuiStatProps[] = [
|
||||
{
|
||||
description: <EditDescription label={NAME_LABEL} indexName={indexName} />,
|
||||
description: <EditDescription label={NAME_LABEL} onClick={() => setIsFlyoutVisible(true)} />,
|
||||
isLoading: hideStats,
|
||||
title: indexData.connector.name,
|
||||
},
|
||||
{
|
||||
description: <EditDescription label={DESCRIPTION_LABEL} indexName={indexName} />,
|
||||
description: (
|
||||
<EditDescription label={DESCRIPTION_LABEL} onClick={() => setIsFlyoutVisible(true)} />
|
||||
),
|
||||
isLoading: hideStats,
|
||||
title: <EuiText size="s">{indexData.connector.description || ''}</EuiText>,
|
||||
titleElement: 'p',
|
||||
|
@ -61,14 +64,17 @@ export const NameAndDescriptionStats: React.FC = () => {
|
|||
];
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="row">
|
||||
{stats.map((item, index) => (
|
||||
<EuiFlexItem key={index}>
|
||||
<EuiPanel color={'subdued'} hasShadow={false} paddingSize="l">
|
||||
<EuiStat {...item} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
<>
|
||||
<EuiFlexGroup direction="row">
|
||||
{stats.map((item, index) => (
|
||||
<EuiFlexItem key={index}>
|
||||
<EuiPanel color={'subdued'} hasShadow={false} paddingSize="l">
|
||||
<EuiStat {...item} />
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
<ConnectorNameAndDescriptionFlyout />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -37,3 +37,7 @@ export const NAME_LABEL = i18n.translate('xpack.enterpriseSearch.nameLabel', {
|
|||
export const DESCRIPTION_LABEL = i18n.translate('xpack.enterpriseSearch.descriptionLabel', {
|
||||
defaultMessage: 'Description',
|
||||
});
|
||||
|
||||
export const OPTIONAL_LABEL = i18n.translate('xpack.enterpriseSearch.optionalLabel', {
|
||||
defaultMessage: 'Optional',
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue