Skip to content

Commit

Permalink
Merge pull request elastic#18 from joemcelroy/add-view-code-fields-re…
Browse files Browse the repository at this point in the history
…design

changes for fields redesign
  • Loading branch information
joemcelroy committed Feb 23, 2024
2 parents a1a3660 + b1cf5b6 commit 026c1a0
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 47 deletions.
1 change: 1 addition & 0 deletions packages/kbn-ai-playground/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
export * from './chat';
export * from './empty_index';
export * from './view_query/view_query_action';
export * from './view_code/view_code_action';
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React, { useState } from 'react';
import {
EuiFlyout,
EuiFlyoutHeader,
EuiFlyoutBody,
EuiTitle,
EuiCodeBlock,
EuiButton,
EuiText,
EuiSpacer,
EuiSteps,
EuiCode,
} from '@elastic/eui';
import { useFormContext } from 'react-hook-form';
import { ChatForm } from '../../types';

interface ViewCodeActionProps {}

export const ViewCodeAction: React.FC<ViewCodeActionProps> = () => {
const { getValues } = useFormContext<ChatForm>();
const [showFlyout, setShowFlyout] = useState(false);
const selectedIndices: string[] = getValues('indices');

let flyout;

const steps = [
{
title: 'Generate and copy an API key',
children: (
<>
<EuiText>
<p>Run this code snippet to install things.</p>
</EuiText>
<EuiSpacer />
<EuiCodeBlock language="bash">npm install</EuiCodeBlock>
</>
),
},
{
title: 'Create application',
children: (
<EuiText>
<p>
Now that you&apos;ve completed step 2, go find the <EuiCode>thing</EuiCode>.
</p>
<p>
Go to <strong>Overview &gt;&gt; Endpoints</strong> note <strong>Elasticsearch</strong>{' '}
as <EuiCode>&lt;thing&gt;</EuiCode>.
</p>
</EuiText>
),
},
];

if (showFlyout) {
flyout = (
<EuiFlyout ownFocus onClose={() => setShowFlyout(false)}>
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>Download Code</h2>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText color="subdued">
<p>Download the code to use in your application.</p>
</EuiText>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiSteps steps={steps} headingElement="h2" />
</EuiFlyoutBody>
</EuiFlyout>
);
}

return (
<>
{flyout}
<EuiButton
color="primary"
fill
onClick={() => setShowFlyout(true)}
disabled={!selectedIndices || selectedIndices?.length === 0}
>
Download Code
</EuiButton>
</>
);
};
140 changes: 95 additions & 45 deletions packages/kbn-ai-playground/components/view_query/view_query_action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ import {
EuiFlexItem,
EuiFlexGroup,
EuiButtonEmpty,
EuiLink,
EuiButton,
EuiFlyoutFooter,
EuiSpacer,
EuiText,
EuiPanel,
EuiAccordion,
EuiBasicTable,
EuiSwitch,
} from '@elastic/eui';
import { useController, useFormContext } from 'react-hook-form';
import { ChatForm, ChatFormFields } from '../../types';
Expand Down Expand Up @@ -70,76 +76,120 @@ export const ViewQueryAction: React.FC<ViewQueryActionProps> = () => {
setShowFlyout(false);
};

const closeFlyout = () => setShowFlyout(false);

let flyout;

if (showFlyout) {
flyout = (
<EuiFlyout ownFocus onClose={() => setShowFlyout(false)}>
<EuiFlyout ownFocus onClose={() => setShowFlyout(false)} size="l">
<EuiFlyoutHeader hasBorder>
<EuiTitle size="m">
<h2>View Query</h2>
<h2>Customise your Elasticsearch Query</h2>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText color="subdued">
<p>
The query that will be used to search your data. You can customise it by choosing
which fields to search on.
</p>
</EuiText>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiFlexGroup>
<EuiFlexItem grow={3}>
<EuiCodeBlock language="json" fontSize="m" paddingSize="m">
<EuiFlexItem grow={6}>
<EuiCodeBlock language="json" fontSize="m" paddingSize="m" lineNumbers>
{JSON.stringify(createQuery(queryFields, fields), null, 2)}
</EuiCodeBlock>
</EuiFlexItem>
<EuiFlexItem grow={1}>
{Object.keys(fields).map((index: string) => {
const group = fields[index];
return (
<>
<h2>{index}</h2>
<br />
{[...group.elser_query_fields, ...group.dense_vector_query_fields].map(
(field) => {
return (
<EuiLink
onClick={() => toggleQueryField(index, field.field)}
color={isQueryFieldSelected(index, field.field) ? 'primary' : 'text'}
>
{field.field} ({field.model_id})
</EuiLink>
);
}
)}
{group.bm25_query_fields.map((field) => {
return (
<EuiLink
onClick={() => toggleQueryField(index, field)}
color={isQueryFieldSelected(index, field) ? 'primary' : 'text'}
<EuiFlexItem grow={3}>
<EuiFlexGroup direction="column">
<EuiText>
<h5>Selected Fields</h5>
</EuiText>
{Object.keys(fields).map((index: string) => {
const group = fields[index];
return (
<EuiFlexItem grow={false}>
<EuiPanel grow={false} hasShadow={false} hasBorder>
<EuiAccordion
id={index}
buttonContent={
<EuiText>
<h5>{index}</h5>
</EuiText>
}
>
{field}
</EuiLink>
);
})}
</>
);
})}
<EuiSpacer size="s" />
<EuiBasicTable
items={[
...group.elser_query_fields,
...group.dense_vector_query_fields,
...group.bm25_query_fields,
].map((field) => ({
field: typeof field === 'string' ? field : field.field,
}))}
columns={[
{
field: 'field',
name: 'Field',
truncateText: false,
render: (field) => field,
},
{
actions: [
{
name: 'toggle',
description: 'Toggle field',
isPrimary: true,
render: ({ field }: { field: string }) => (
<EuiSwitch
showLabel={false}
label="toggle"
checked={isQueryFieldSelected(index, field)}
onChange={(e) => toggleQueryField(index, field)}
compressed
/>
),
},
],
},
]}
hasActions
/>
</EuiAccordion>
</EuiPanel>
</EuiFlexItem>
);
})}
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem>
<EuiButtonEmpty onClick={() => setShowFlyout(false)}>Close</EuiButtonEmpty>
</EuiFlyoutBody>
<EuiFlyoutFooter>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButtonEmpty iconType="cross" onClick={closeFlyout} flush="left">
Close
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem>
<EuiButton onClick={saveQuery}>Save</EuiButton>
<EuiFlexItem grow={false}>
<EuiButton onClick={saveQuery} fill>
Save changes
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlyoutBody>
</EuiFlyoutFooter>
</EuiFlyout>
);
}

return (
<>
{flyout}
{selectedIndices?.length > 0 && (
<EuiButtonEmpty onClick={() => setShowFlyout(true)}>View Query</EuiButtonEmpty>
)}
<EuiButtonEmpty onClick={() => setShowFlyout(true)} disabled={selectedIndices?.length === 0}>
View Query
</EuiButtonEmpty>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import React, { useCallback, useEffect } from 'react';
import { useValues, useActions } from 'kea';

import { EuiPageTemplate } from '@elastic/eui';
import { Chat, EmptyIndex, AIPlaygroundProvider, ViewQueryAction } from '@kbn/ai-playground';
import {
Chat,
EmptyIndex,
AIPlaygroundProvider,
ViewQueryAction,
ViewCodeAction,
} from '@kbn/ai-playground';
import { i18n } from '@kbn/i18n';

import { KibanaLogic } from '../../../shared/kibana';
Expand Down Expand Up @@ -46,7 +52,10 @@ export const AIPlayground: React.FC = () => {
pageTitle: i18n.translate('xpack.enterpriseSearch.content.aiPlayground.headerTitle', {
defaultMessage: 'AI Playground',
}),
rightSideItems: [<ViewQueryAction key="viewQueryAction" />],
rightSideItems: [
<ViewCodeAction key="viewCodeAction" />,
<ViewQueryAction key="viewQueryAction" />,
],
}}
pageViewTelemetry="AI Playground"
restrictWidth={false}
Expand Down

0 comments on commit 026c1a0

Please sign in to comment.