Skip to content

Commit

Permalink
Merge pull request elastic#34 from CoenWarmer/storybook
Browse files Browse the repository at this point in the history
  • Loading branch information
CoenWarmer committed Aug 9, 2023
2 parents a5348a4 + 24bf9cc commit 6e54fab
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';
import {
EuiFlexGroup,
EuiFlexItem,
Expand All @@ -12,15 +14,9 @@ import {
EuiPanel,
EuiText,
} from '@elastic/eui';
import { css } from '@emotion/css';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { UseKnowledgeBaseResult } from '../../hooks/use_knowledge_base';

const panelClassName = css`
border-radius: 0;
`;

export function KnowledgeBaseCallout({ knowledgeBase }: { knowledgeBase: UseKnowledgeBaseResult }) {
let content: React.ReactNode;

Expand Down Expand Up @@ -104,13 +100,7 @@ export function KnowledgeBaseCallout({ knowledgeBase }: { knowledgeBase: UseKnow
}

return (
<EuiPanel
hasBorder={false}
hasShadow={false}
className={panelClassName}
color={color}
paddingSize="s"
>
<EuiPanel hasBorder={false} hasShadow={false} borderRadius="none" color={color} paddingSize="s">
{content}
</EuiPanel>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { useMemo } from 'react';
import { monaco } from '@kbn/monaco';
import { useObservabilityAIAssistant } from './use_observability_ai_assistant';
import { createInitializedObject } from '../utils/create_initialized_object';

const { editor, languages, Uri } = monaco;

Expand Down Expand Up @@ -35,13 +36,7 @@ export const useJsonEditorModel = ({
const initialJsonString = initialJson
? initialJson
: functionDefinition.options.parameters.properties
? Object.keys(functionDefinition.options.parameters.properties).reduce(
(acc, curr, index, arr) => {
const val = `${acc} "${curr}": "",\n`;
return index === arr.length - 1 ? `${val}}` : val;
},
'{\n'
)
? JSON.stringify(createInitializedObject(functionDefinition.options.parameters), null, 4)
: '';

languages.json.jsonDefaults.setDiagnosticsOptions({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
* 2.0.
*/

import { i18n } from '@kbn/i18n';
import { useMemo, useState } from 'react';
import { AbortableAsyncState, useAbortableAsync } from './use_abortable_async';
import { useKibana } from './use_kibana';
import { useObservabilityAIAssistant } from './use_observability_ai_assistant';

export interface UseKnowledgeBaseResult {
Expand All @@ -22,6 +24,9 @@ export interface UseKnowledgeBaseResult {
}

export function useKnowledgeBase(): UseKnowledgeBaseResult {
const {
notifications: { toasts },
} = useKibana().services;
const service = useObservabilityAIAssistant();

const status = useAbortableAsync(({ signal }) => {
Expand Down Expand Up @@ -50,12 +55,17 @@ export function useKnowledgeBase(): UseKnowledgeBaseResult {
})
.catch((error) => {
setInstallError(error);
toasts.addError(error, {
title: i18n.translate('xpack.observabilityAiAssistant.errorSettingUpKnowledgeBase', {
defaultMessage: 'Could not set up Knowledge Base',
}),
});
})
.finally(() => {
setIsInstalling(true);
setIsInstalling(false);
});
},
}),
[status, service, isInstalling, installError]
[status, isInstalling, installError, service, toasts]
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type ChatItemBuildProps = Partial<ChatTimelineItem> & Pick<ChatTimelineItem, 'ro
export function buildChatItem(params: ChatItemBuildProps): ChatTimelineItem {
return {
id: uniqueId(),
'@timestamp': new Date().toISOString(),
title: '',
canEdit: false,
canGiveFeedback: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* 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 { createInitializedObject } from './create_initialized_object';

describe('createInitializedObject', () => {
it('should return an object with properties of type "string" set to a default value of ""', () => {
expect(
createInitializedObject({
type: 'object',
properties: {
foo: {
type: 'string',
},
},
required: ['foo'],
})
).toStrictEqual({ foo: '' });
});

it('should return an object with properties of type "number" set to a default value of 1', () => {
expect(
createInitializedObject({
type: 'object',
properties: {
foo: {
type: 'number',
},
},
required: ['foo'],
})
).toStrictEqual({ foo: 1 });
});

it('should return an object with properties of type "array" set to a default value of []', () => {
expect(
createInitializedObject({
type: 'object',
properties: {
foo: {
type: 'array',
},
},
required: ['foo'],
})
).toStrictEqual({ foo: [] });
});

it('should return an object with default values for properties that are required', () => {
expect(
createInitializedObject({
type: 'object',
properties: {
requiredProperty: {
type: 'string',
},
notRequiredProperty: {
type: 'string',
},
},
required: ['requiredProperty'],
})
).toStrictEqual({ requiredProperty: '' });
});

it('should return an object with nested fields if they are present in the schema', () => {
expect(
createInitializedObject({
type: 'object',
properties: {
foo: {
type: 'object',
properties: {
bar: {
type: 'object',
properties: {
baz: {
type: 'string',
},
},
required: ['baz'],
},
},
required: ['bar'],
},
},
})
).toStrictEqual({ foo: { bar: { baz: '' } } });

expect(
createInitializedObject({
type: 'object',
properties: {
foo: {
type: 'object',
properties: {
bar: {
type: 'string',
},
},
},
},
})
).toStrictEqual({ foo: {} });
});

it('should handle a real life example', () => {
expect(
createInitializedObject({
type: 'object',
properties: {
method: {
type: 'string',
description: 'The HTTP method of the Elasticsearch endpoint',
enum: ['GET', 'PUT', 'POST', 'DELETE', 'PATCH'] as const,
},
path: {
type: 'string',
description: 'The path of the Elasticsearch endpoint, including query parameters',
},
notRequired: {
type: 'string',
description: 'This property is not required.',
},
},
required: ['method', 'path'] as const,
})
).toStrictEqual({ method: '', path: '' });
});
});
Original file line number Diff line number Diff line change
@@ -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 { FunctionDefinition } from '../../common/types';

type Params = FunctionDefinition['options']['parameters'];

export function createInitializedObject(parameters: Params) {
const emptyObject: Record<string, string | any> = {};

function traverseProperties({ properties, required }: Params) {
for (const propName in properties) {
if (properties.hasOwnProperty(propName)) {
const prop = properties[propName] as Params;

if (prop.type === 'object') {
emptyObject[propName] = createInitializedObject(prop);
} else if (required?.includes(propName)) {
if (prop.type === 'array') {
emptyObject[propName] = [];
}

if (prop.type === 'number') {
emptyObject[propName] = 1;
}

if (prop.type === 'string') {
emptyObject[propName] = '';
}
}
}
}
}

traverseProperties(parameters);

return emptyObject;
}

0 comments on commit 6e54fab

Please sign in to comment.