[8.10] Assorted Tweaks + Telemetry (#165604) (#165620)

# Backport

This will backport the following commits from `main` to `8.10`:
- [Assorted Tweaks + Telemetry
(#165604)](https://github.com/elastic/kibana/pull/165604)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Coen
Warmer","email":"coen.warmer@gmail.com"},"sourceCommit":{"committedDate":"2023-09-04T16:15:36Z","message":"Assorted
Tweaks + Telemetry
(#165604)","sha":"63b7227250a362053d5df1ff980921820a0d6d7a","branchLabelMapping":{"^v8.11.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:prev-minor","v8.10.0","v8.11.0"],"number":165604,"url":"https://github.com/elastic/kibana/pull/165604","mergeCommit":{"message":"Assorted
Tweaks + Telemetry
(#165604)","sha":"63b7227250a362053d5df1ff980921820a0d6d7a"}},"sourceBranch":"main","suggestedTargetBranches":["8.10"],"targetPullRequestStates":[{"branch":"8.10","label":"v8.10.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.11.0","labelRegex":"^v8.11.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/165604","number":165604,"mergeCommit":{"message":"Assorted
Tweaks + Telemetry
(#165604)","sha":"63b7227250a362053d5df1ff980921820a0d6d7a"}}]}]
BACKPORT-->
This commit is contained in:
Coen Warmer 2023-09-04 20:13:00 +02:00 committed by GitHub
parent 8ddf099d12
commit 310c5f1a5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 142 additions and 25 deletions

View file

@ -49,6 +49,7 @@ export function ObservabilityAIAssistantActionMenuItem() {
<>
<EuiHeaderLink
color="primary"
data-test-subj="observabilityAiAssistantNewChatHeaderLink"
onClick={() => {
setIsOpen(() => true);
}}

View file

@ -56,14 +56,26 @@ export function AskAssistantButton({
switch (variant) {
case 'basic':
return (
<EuiButton fill={fill} size={size} iconType="sparkles" onClick={onClick}>
<EuiButton
data-test-subj="observabilityAiAssistantAskAssistantButton"
fill={fill}
size={size}
iconType="sparkles"
onClick={onClick}
>
{buttonLabel}
</EuiButton>
);
case 'empty':
return (
<EuiButtonEmpty size={size} flush={flush} iconType="sparkles" onClick={onClick}>
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantAskAssistantButton"
size={size}
flush={flush}
iconType="sparkles"
onClick={onClick}
>
{buttonLabel}
</EuiButtonEmpty>
);
@ -89,8 +101,9 @@ export function AskAssistantButton({
defaultMessage: 'Elastic Assistant',
}
)}
iconType="sparkles"
data-test-subj="observabilityAiAssistantAskAssistantButtonButtonIcon"
display={fill ? 'fill' : 'base'}
iconType="sparkles"
size={size}
style={{ minWidth: 'auto' }}
onClick={onClick}

View file

@ -14,7 +14,12 @@ export type HideExpandConversationListButtonProps = React.ComponentProps<typeof
export function HideExpandConversationListButton(props: HideExpandConversationListButtonProps) {
return (
<EuiButtonEmpty iconType={props.isExpanded ? 'menuLeft' : 'menuRight'} size="xs" {...props}>
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantHideExpandConversationListButton"
iconType={props.isExpanded ? 'menuLeft' : 'menuRight'}
size="xs"
{...props}
>
{props.isExpanded
? i18n.translate('xpack.observabilityAiAssistant.hideExpandConversationButton.hide', {
defaultMessage: 'Hide chats',

View file

@ -10,7 +10,12 @@ import { i18n } from '@kbn/i18n';
export function NewChatButton(props: React.ComponentProps<typeof EuiButton>) {
return (
<EuiButton {...props} fill iconType="discuss">
<EuiButton
data-test-subj="observabilityAiAssistantNewChatButton"
fill
iconType="discuss"
{...props}
>
{i18n.translate('xpack.observabilityAiAssistant.newChatButton', {
defaultMessage: 'New chat',
})}

View file

@ -11,7 +11,12 @@ import { i18n } from '@kbn/i18n';
export function RegenerateResponseButton(props: Partial<EuiButtonEmptyProps>) {
return (
<EuiButtonEmpty size="s" {...props} iconType="sparkles">
<EuiButtonEmpty
size="s"
data-test-subj="observabilityAiAssistantRegenerateResponseButton"
iconType="sparkles"
{...props}
>
{i18n.translate('xpack.observabilityAiAssistant.regenerateResponseButtonLabel', {
defaultMessage: 'Regenerate',
})}

View file

@ -10,7 +10,13 @@ import { i18n } from '@kbn/i18n';
export function StartChatButton(props: React.ComponentProps<typeof EuiButton>) {
return (
<EuiButton {...props} fill iconType="discuss" size="s">
<EuiButton
data-test-subj="observabilityAiAssistantStartChatButton"
fill
iconType="discuss"
size="s"
{...props}
>
{i18n.translate('xpack.observabilityAiAssistant.insight.response.startChat', {
defaultMessage: 'Start chat',
})}

View file

@ -11,7 +11,13 @@ import { i18n } from '@kbn/i18n';
export function StopGeneratingButton(props: Partial<EuiButtonEmptyProps>) {
return (
<EuiButtonEmpty size="s" {...props} iconType="stop" color="text">
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantStopGeneratingButton"
color="text"
iconType="stop"
size="s"
{...props}
>
{i18n.translate('xpack.observabilityAiAssistant.stopGeneratingButtonLabel', {
defaultMessage: 'Stop generating',
})}

View file

@ -31,6 +31,7 @@ export function ChatActionsMenu({
connectors,
connectorsManagementHref,
conversationId,
disabled,
knowledgeBase,
modelsManagementHref,
startedFrom,
@ -39,6 +40,7 @@ export function ChatActionsMenu({
connectors: UseGenAIConnectorsResult;
connectorsManagementHref: string;
conversationId?: string;
disabled: boolean;
knowledgeBase: UseKnowledgeBaseResult;
modelsManagementHref: string;
startedFrom?: StartedFrom;
@ -54,7 +56,13 @@ export function ChatActionsMenu({
<EuiPopover
isOpen={isOpen}
button={
<EuiButtonIcon iconType="boxesVertical" onClick={toggleActionsMenu} aria-label="Menu" />
<EuiButtonIcon
aria-label="Menu"
data-test-subj="observabilityAiAssistantChatActionsMenuButtonIcon"
disabled={disabled}
iconType="boxesVertical"
onClick={toggleActionsMenu}
/>
}
panelPaddingSize="none"
closePopover={toggleActionsMenu}
@ -134,6 +142,7 @@ export function ChatActionsMenu({
<ConnectorSelectorBase {...connectors} />
<EuiSpacer size="m" />
<EuiButton
data-test-subj="observabilityAiAssistantChatActionsMenuManageConnectorsButton"
href={connectorsManagementHref}
iconSide="right"
iconType="arrowRight"
@ -170,6 +179,7 @@ export function ChatActionsMenu({
}
)}{' '}
<EuiLink
data-test-subj="observabilityAiAssistantChatActionsMenuLearnMoreLink"
external
target="_blank"
href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-elser.html"
@ -218,7 +228,12 @@ export function ChatActionsMenu({
<EuiSpacer size="m" />
<EuiButton href={modelsManagementHref} fullWidth size="s">
<EuiButton
data-test-subj="observabilityAiAssistantChatActionsMenuGoToMachineLearningButton"
fullWidth
href={modelsManagementHref}
size="s"
>
{i18n.translate(
'xpack.observabilityAiAssistant.chatHeader.actions.connectorManagement',
{

View file

@ -78,6 +78,7 @@ export function ChatFlyout({
>
{conversationId ? (
<EuiLink
data-test-subj="observabilityAiAssistantChatFlyoutOpenConversationLink"
href={router.link('/conversations/{conversationId}', {
path: { conversationId },
})}
@ -87,7 +88,10 @@ export function ChatFlyout({
})}
</EuiLink>
) : (
<EuiLink href={router.link('/conversations/new')}>
<EuiLink
data-test-subj="observabilityAiAssistantChatFlyoutGoToConversationsLink"
href={router.link('/conversations/new')}
>
{i18n.translate('xpack.observabilityAiAssistant.conversationListDeepLinkLabel', {
defaultMessage: 'Go to conversations',
})}

View file

@ -99,9 +99,10 @@ export function ChatHeader({
<ChatActionsMenu
connectors={connectors}
connectorsManagementHref={connectorsManagementHref}
modelsManagementHref={modelsManagementHref}
disabled={licenseInvalid}
conversationId={conversationId}
knowledgeBase={knowledgeBase}
modelsManagementHref={modelsManagementHref}
startedFrom={startedFrom}
onCopyConversationClick={onCopyConversation}
/>

View file

@ -53,6 +53,7 @@ export function ChatItemActions({
}
)}
color="text"
data-test-subj="observabilityAiAssistantChatItemActionsEditPromptButton"
display={editing ? 'fill' : 'empty'}
iconType="documentEdit"
onClick={onToggleEdit}
@ -68,6 +69,7 @@ export function ChatItemActions({
}
)}
color="text"
data-test-subj="observabilityAiAssistantChatItemActionsInspectPromptButton"
display={expanded ? 'fill' : 'empty'}
iconType={expanded ? 'eyeClosed' : 'eye'}
onClick={onToggleExpand}
@ -85,6 +87,7 @@ export function ChatItemActions({
}
)}
color="text"
data-test-subj="observabilityAiAssistantChatItemActionsCopyMessageButton"
iconType="copyClipboard"
display={isPopoverOpen === 'copy' ? 'fill' : 'empty'}
onClick={() => {

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import React, { useCallback, useEffect, useRef, useState } from 'react';
import {
EuiButtonEmpty,
EuiButtonIcon,
@ -18,7 +19,6 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { CodeEditor } from '@kbn/kibana-react-plugin/public';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { MessageRole, type Message } from '../../../common';
import { useJsonEditorModel } from '../../hooks/use_json_editor_model';
import { FunctionListPopover } from './function_list_popover';
@ -51,6 +51,7 @@ export function ChatPromptEditor({
const [functionPayload, setFunctionPayload] = useState<string | undefined>(
initialFunctionPayload
);
const [functionEditorLineCount, setFunctionEditorLineCount] = useState<number>(0);
const { model, initialJsonString } = useJsonEditorModel({
functionName: selectedFunctionName,
@ -59,9 +60,12 @@ export function ChatPromptEditor({
const textAreaRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
setFunctionPayload(initialJsonString);
}, [initialJsonString, selectedFunctionName]);
const recalculateFunctionEditorLineCount = useCallback(() => {
const newLineCount = model?.getLineCount() || 0;
if (newLineCount !== functionEditorLineCount) {
setFunctionEditorLineCount(newLineCount);
}
}, [functionEditorLineCount, model]);
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
setPrompt(event.currentTarget.value);
@ -69,6 +73,7 @@ export function ChatPromptEditor({
const handleChangeFunctionPayload = (params: string) => {
setFunctionPayload(params);
recalculateFunctionEditorLineCount();
};
const handleClearSelection = () => {
@ -91,7 +96,7 @@ export function ChatPromptEditor({
};
const handleSubmit = useCallback(async () => {
if (loading) {
if (loading || !prompt?.trim()) {
return;
}
const currentPrompt = prompt;
@ -129,6 +134,14 @@ export function ChatPromptEditor({
}
}, [functionPayload, loading, onSubmit, prompt, selectedFunctionName]);
useEffect(() => {
setFunctionPayload(initialJsonString);
}, [initialJsonString, selectedFunctionName]);
useEffect(() => {
recalculateFunctionEditorLineCount();
}, [model, recalculateFunctionEditorLineCount]);
useEffect(() => {
const keyboardListener = (event: KeyboardEvent) => {
if (!event.shiftKey && event.key === keys.ENTER && (prompt || selectedFunctionName)) {
@ -174,6 +187,7 @@ export function ChatPromptEditor({
<EuiFlexItem grow={false}>
{selectedFunctionName ? (
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantChatPromptEditorEmptySelectionButton"
iconType="cross"
iconSide="right"
size="xs"
@ -193,8 +207,9 @@ export function ChatPromptEditor({
<EuiPanel borderRadius="none" color="subdued" hasShadow={false} paddingSize="xs">
<CodeEditor
aria-label="payloadEditor"
data-test-subj="observabilityAiAssistantChatPromptEditorCodeEditor"
fullWidth
height="120px"
height={functionEditorLineCount > 8 ? '200px' : '120px'}
languageId="json"
isCopyable
languageConfiguration={{
@ -238,6 +253,8 @@ export function ChatPromptEditor({
</EuiPanel>
) : (
<EuiTextArea
data-test-subj="observabilityAiAssistantChatPromptEditorTextArea"
css={{ maxHeight: 200 }}
disabled={disabled}
fullWidth
inputRef={textAreaRef}
@ -256,8 +273,9 @@ export function ChatPromptEditor({
<EuiFlexItem grow={false}>
<EuiSpacer size="xl" />
<EuiButtonIcon
data-test-subj="observabilityAiAssistantChatPromptEditorButtonIcon"
aria-label="Submit"
disabled={selectedFunctionName ? false : !prompt || loading || disabled}
disabled={selectedFunctionName ? false : !prompt?.trim() || loading || disabled}
display={
selectedFunctionName ? (functionPayload ? 'fill' : 'base') : prompt ? 'fill' : 'base'
}

View file

@ -39,6 +39,7 @@ const Template: ComponentStory<typeof Component> = (props: ChatTimelineProps) =>
<EuiSpacer />
<EuiButton
data-test-subj="observabilityAiAssistantTemplateAddMessageButton"
onClick={() => setCount(count >= 0 && count < props.items.length - 1 ? count + 1 : 0)}
>
Add message

View file

@ -51,6 +51,7 @@ export function ChatWelcomePanel({ knowledgeBase }: { knowledgeBase: UseKnowledg
{!knowledgeBase.status.value?.ready ? (
<EuiButton
data-test-subj="observabilityAiAssistantChatWelcomePanelSetUpKnowledgeBaseButton"
color="primary"
fill
iconType={knowledgeBase.status.value?.ready ? 'checkInCircleFilled' : 'dotInCircle'}

View file

@ -42,7 +42,12 @@ export function ExperimentalFeatureBanner() {
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton color="warning" href="https://ela.st/obs-ai-assistant" target="_blank">
<EuiButton
data-test-subj="observabilityAiAssistantExperimentalFeatureBannerGiveFeedbackButton"
color="warning"
href="https://ela.st/obs-ai-assistant"
target="_blank"
>
{i18n.translate(
'xpack.observabilityAiAssistant.experimentalFunctionBanner.feedbackButton',
{ defaultMessage: 'Give feedback' }

View file

@ -109,6 +109,7 @@ export function FunctionListPopover({
anchorPosition="downLeft"
button={
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantFunctionListPopoverButton"
iconType="arrowRight"
iconSide="right"
size="xs"

View file

@ -53,7 +53,12 @@ export function IncorrectLicensePanel() {
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexItem>
<EuiButton fill href="https://www.elastic.co/subscriptions" target="_blank">
<EuiButton
data-test-subj="observabilityAiAssistantIncorrectLicensePanelSubscriptionPlansButton"
fill
href="https://www.elastic.co/subscriptions"
target="_blank"
>
{i18n.translate(
'xpack.observabilityAiAssistant.incorrectLicense.subscriptionPlansButton',
{
@ -63,7 +68,10 @@ export function IncorrectLicensePanel() {
</EuiButton>
</EuiFlexItem>
<EuiFlexItem>
<EuiButtonEmpty onClick={handleNavigateToLicenseManagement}>
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantIncorrectLicensePanelManageLicenseButton"
onClick={handleNavigateToLicenseManagement}
>
{i18n.translate('xpack.observabilityAiAssistant.incorrectLicense.manageLicense', {
defaultMessage: 'Manage license',
})}

View file

@ -101,6 +101,7 @@ export function InitialSetupPanel({
/>
) : (
<EuiButton
data-test-subj="observabilityAiAssistantInitialSetupPanelButton"
color={knowledgeBase.status.value?.ready ? 'success' : 'primary'}
fill
isLoading={knowledgeBase.isInstalling || knowledgeBase.status.loading}
@ -187,7 +188,12 @@ export function InitialSetupPanel({
}
footer={
!connectors.connectors?.length ? (
<EuiButton fill color="primary" href={connectorsManagementHref}>
<EuiButton
data-test-subj="observabilityAiAssistantInitialSetupPanelSetUpGenerativeAiConnectorButton"
fill
color="primary"
href={connectorsManagementHref}
>
{i18n.translate(
'xpack.observabilityAiAssistant.initialSetupPanel.setupConnector.buttonLabel',
{

View file

@ -89,6 +89,7 @@ export function KnowledgeBaseCallout({ knowledgeBase }: { knowledgeBase: UseKnow
} else if (!knowledgeBase.status.value?.ready && !knowledgeBase.status.error) {
content = (
<EuiLink
data-test-subj="observabilityAiAssistantKnowledgeBaseCalloutLink"
onClick={() => {
knowledgeBase.install();
}}

View file

@ -32,6 +32,7 @@ export function FeedbackButtons({ onClickFeedback }: FeedbackButtonsProps) {
<EuiFlexGroup responsive={false} direction="row" alignItems="center" gutterSize="xs">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantFeedbackButtonsPositiveButton"
color="success"
iconType="faceHappy"
size="s"
@ -45,6 +46,7 @@ export function FeedbackButtons({ onClickFeedback }: FeedbackButtonsProps) {
<EuiFlexItem grow={false}>
<EuiButtonEmpty
data-test-subj="observabilityAiAssistantFeedbackButtonsNegativeButton"
color="danger"
iconType="faceSad"
size="s"

View file

@ -95,6 +95,7 @@ export function InsightBase({
)}
color="text"
css={{ alignSelf: 'flex-start' }}
data-test-subj="observabilityAiAssistantInsightBaseButtonIcon"
disabled={actions?.length === 0}
display="empty"
iconType="boxesHorizontal"

View file

@ -24,7 +24,11 @@ export function InsightError() {
<EuiSpacer size="m" />
<EuiButton fill color="danger">
<EuiButton
data-test-subj="observabilityAiAssistantInsightErrorRegenerateButton"
fill
color="danger"
>
{i18n.translate('xpack.observabilityAiAssistant.insight.error.buttonLabel', {
defaultMessage: 'Regenerate',
})}

View file

@ -29,7 +29,12 @@ export function MissingCredentialsCallout(props: Props) {
<EuiSpacer size="m" />
<EuiButton fill color="primary" href={props.connectorsManagementHref}>
<EuiButton
data-test-subj="observabilityAiAssistantMissingCredentialsCalloutConnectAssistantButton"
fill
color="primary"
href={props.connectorsManagementHref}
>
{i18n.translate('xpack.observabilityAiAssistant.missingCredentialsCallout.buttonLabel', {
defaultMessage: 'Connect Assistant',
})}