From 0e03616a7450df345a60b6120ec18c59884988b4 Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Mon, 15 Nov 2021 11:20:32 +0100 Subject: [PATCH] Add ConfigEditor util components (#4) --- src/index.ts | 1 + src/sql/ConfigEditor/ConfigSelect.test.tsx | 55 ++++++++++++++++++ src/sql/ConfigEditor/ConfigSelect.tsx | 61 ++++++++++++++++++++ src/sql/ConfigEditor/InlineInput.test.tsx | 46 +++++++++++++++ src/sql/ConfigEditor/InlineInput.tsx | 45 +++++++++++++++ src/sql/ConfigEditor/__mocks__/datasource.ts | 33 +++++++++++ src/sql/ConfigEditor/index.ts | 2 + src/sql/ResourceSelector.tsx | 3 +- src/types.ts | 4 +- yarn.lock | 13 ++--- 10 files changed, 252 insertions(+), 11 deletions(-) create mode 100644 src/sql/ConfigEditor/ConfigSelect.test.tsx create mode 100644 src/sql/ConfigEditor/ConfigSelect.tsx create mode 100644 src/sql/ConfigEditor/InlineInput.test.tsx create mode 100644 src/sql/ConfigEditor/InlineInput.tsx create mode 100644 src/sql/ConfigEditor/__mocks__/datasource.ts create mode 100644 src/sql/ConfigEditor/index.ts diff --git a/src/index.ts b/src/index.ts index 6b6f2a1..00b19ae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ export { ConnectionConfig, ConnectionConfigProps } from './ConnectionConfig'; +export { ConfigSelect, InlineInput } from './sql/ConfigEditor'; export { ResourceSelector, ResourceSelectorProps } from './sql/ResourceSelector'; export * from './types'; export * from './regions'; diff --git a/src/sql/ConfigEditor/ConfigSelect.test.tsx b/src/sql/ConfigEditor/ConfigSelect.test.tsx new file mode 100644 index 0000000..697590c --- /dev/null +++ b/src/sql/ConfigEditor/ConfigSelect.test.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { ConfigSelect, ConfigSelectProps } from './ConfigSelect'; +import { mockDatasourceOptions } from './__mocks__/datasource'; +import { select } from 'react-select-event'; + +const props: ConfigSelectProps = { + ...mockDatasourceOptions, + jsonDataPath: 'foo', + fetch: jest.fn(), + saveOptions: jest.fn(), +}; + +describe('SQLTextInput', () => { + it('should update jsonData', async () => { + const fetch = jest.fn().mockResolvedValue(['bar']); + const onOptionsChange = jest.fn(); + const label = 'foo-id'; + render(); + + const selectEl = screen.getByLabelText(label); + expect(selectEl).toBeInTheDocument(); + await select(selectEl, 'bar', { container: document.body }); + expect(fetch).toHaveBeenCalled(); + expect(onOptionsChange).toHaveBeenCalledWith({ + ...props.options, + jsonData: { + ...props.options.jsonData, + foo: 'bar', + }, + }); + }); + + it('should call deep nested jsonData value', async () => { + const onOptionsChange = jest.fn(); + const fetch = jest.fn().mockResolvedValue(['foobar']); + const label = 'foo-id'; + render( + + ); + const selectEl = screen.getByLabelText(label); + expect(selectEl).toBeInTheDocument(); + await select(selectEl, 'foobar', { container: document.body }); + expect(fetch).toHaveBeenCalled(); + expect(onOptionsChange).toHaveBeenCalledWith({ + ...props.options, + jsonData: { + ...props.options.jsonData, + foo: { + bar: 'foobar', + }, + }, + }); + }); +}); diff --git a/src/sql/ConfigEditor/ConfigSelect.tsx b/src/sql/ConfigEditor/ConfigSelect.tsx new file mode 100644 index 0000000..061699e --- /dev/null +++ b/src/sql/ConfigEditor/ConfigSelect.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { DataSourcePluginOptionsEditorProps, SelectableValue } from '@grafana/data'; +import { AwsAuthDataSourceJsonData, AwsAuthDataSourceSecureJsonData } from '../../types'; +import { ResourceSelector } from '../ResourceSelector'; +import { set, get } from 'lodash'; + +export interface ConfigSelectProps + extends DataSourcePluginOptionsEditorProps { + jsonDataPath: string; + fetch: () => Promise>>; + dependencies?: string[]; + label?: string; + 'data-testid'?: string; + hidden?: boolean; + disabled?: boolean; + jsonDataPathLabel?: string; + saveOptions: () => Promise; +} + +export function ConfigSelect(props: ConfigSelectProps) { + const { jsonData } = props.options; + const commonProps = { + title: jsonData.defaultRegion ? '' : 'select a default region', + disabled: !jsonData.defaultRegion, + labelWidth: 28, + className: 'width-30', + }; + const onChange = (e: SelectableValue | null) => { + const newOptions = { + ...props.options, + }; + set(newOptions.jsonData, props.jsonDataPath, e ? e.value || '' : e); + if (props.jsonDataPathLabel) { + set(newOptions.jsonData, props.jsonDataPathLabel, e ? e.label || '' : e); + } + props.onOptionsChange(newOptions); + }; + // Any change in the AWS connection details will affect selectors + const dependencies: string[] = [ + props.options.jsonData.assumeRoleArn, + props.options.jsonData.authType, + props.options.jsonData.defaultRegion, + props.options.jsonData.endpoint, + props.options.jsonData.externalId, + props.options.jsonData.profile, + ].concat(props.dependencies); + return ( +