Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to new form styling in config and query editors #332

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"devDependencies": {
"@babel/core": "^7.21.4",
"@emotion/css": "^11.1.3",
"@grafana/aws-sdk": "0.3.2",
"@grafana/aws-sdk": "0.4.0",
"@grafana/data": "10.2.0",
"@grafana/e2e": "10.2.0",
"@grafana/e2e-selectors": "10.2.0",
Expand Down
5 changes: 1 addition & 4 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ export default defineConfig<PluginOptions>({
reporter: 'html',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
featureToggles: {
awsDatasourcesNewFormStyling: true,
}
trace: 'on-first-retry'
},

projects: [
Expand Down
13 changes: 1 addition & 12 deletions src/components/ConfigEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { DataSourcePluginOptionsEditorProps } from '@grafana/data';
import { ConfigEditor } from './ConfigEditor';
import { render, screen } from '@testing-library/react';
import { SitewiseOptions, SitewiseSecureJsonData } from 'types';
import { config } from '@grafana/runtime';
const datasourceOptions = {
id: 1,
uid: 'sitewise',
Expand All @@ -28,15 +27,6 @@ const defaultProps: DataSourcePluginOptionsEditorProps<SitewiseOptions, Sitewise
options: datasourceOptions,
onOptionsChange: jest.fn(),
};
const originalToggleValue = config.featureToggles.awsDatasourcesNewFormStyling

describe('ConfigEditor', () => {
beforeEach(() => {
config.featureToggles.awsDatasourcesNewFormStyling = true;
})
afterEach(() => {
config.featureToggles.awsDatasourcesNewFormStyling = originalToggleValue;
})
describe('edge configuration', () => {
it('should show correct fields if Standard authentication', () => {
render(
Expand Down Expand Up @@ -75,5 +65,4 @@ describe('ConfigEditor', () => {
expect(screen.queryByText('Edge settings')).not.toBeInTheDocument();
expect(screen.getByText('Authentication Provider')).toBeInTheDocument();
});
});
});
});
153 changes: 9 additions & 144 deletions src/components/ConfigEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import {
} from '@grafana/data';
import { SitewiseOptions, SitewiseSecureJsonData } from '../types';
import { ConnectionConfig, ConnectionConfigProps, Divider } from '@grafana/aws-sdk';
import { Alert, Button, Field, FieldSet, InlineField, InlineFieldRow, Input, Select } from '@grafana/ui';
import { Alert, Button, Field, Input, Select } from '@grafana/ui';
import { standardRegions } from '../regions';
import { config } from '@grafana/runtime';
import { ConfigSection } from '@grafana/experimental';

export type Props = ConnectionConfigProps<SitewiseOptions, SitewiseSecureJsonData>;
Expand All @@ -23,29 +22,23 @@ const edgeAuthMethods: Array<SelectableValue<string>> = [
];

export function ConfigEditor(props: Props) {
const newFormStylingEnabled = config.featureToggles.awsDatasourcesNewFormStyling;

if (props.options.jsonData.defaultRegion === 'Edge') {
return <EdgeConfig newFormStylingEnabled={newFormStylingEnabled} {...props}/>
return <EdgeConfig {...props}/>
}
return newFormStylingEnabled ? (
<div className="width-30">
<ConnectionConfig {...props} standardRegions={standardRegions} newFormStylingEnabled={true} />{' '}
return <div className="width-30">
<ConnectionConfig {...props} standardRegions={standardRegions} />{' '}
</div>
) : (
<ConnectionConfig {...props} standardRegions={standardRegions} newFormStylingEnabled={false} />
);

}


function EdgeConfig(props: {newFormStylingEnabled?: boolean} & Props) {
function EdgeConfig(props: Props) {
const { options } = props;
const { jsonData } = options;
const { endpoint } = jsonData;

const edgeAuthMode = edgeAuthMethods.find((f) => f.value === jsonData.edgeAuthMode) ?? edgeAuthMethods[0];
const hasEdgeAuth = edgeAuthMode !== edgeAuthMethods[0];
const labelWidth = 28;
const regions = standardRegions.map((value) => ({ value, label: value }));

const onUserChange = (event: ChangeEvent<HTMLInputElement>) => {
Expand Down Expand Up @@ -77,9 +70,7 @@ function EdgeConfig(props: {newFormStylingEnabled?: boolean} & Props) {
});
}

if (props.newFormStylingEnabled) {
return (
<div className="width-30">
return <div className="width-30">
{hasEdgeAuth && (
<ConfigSection title="Connection Details" data-testid="connection-config">
<Field
Expand Down Expand Up @@ -107,7 +98,7 @@ function EdgeConfig(props: {newFormStylingEnabled?: boolean} & Props) {
</ConfigSection>
)}
{!hasEdgeAuth && (
<ConnectionConfig {...props} standardRegions={standardRegions} newFormStylingEnabled={true} />
<ConnectionConfig {...props} standardRegions={standardRegions} />
)}

<Divider />
Expand Down Expand Up @@ -193,131 +184,5 @@ function EdgeConfig(props: {newFormStylingEnabled?: boolean} & Props) {
</Field>
</ConfigSection>
</div>
);
} else {
return (
<>
{hasEdgeAuth && (
<FieldSet label={'Connection Details'} data-testid="connection-config">
<InlineField
label="Endpoint"
labelWidth={28}
tooltip="Optionally, specify a custom endpoint for the service"
>
<Input
className="width-30"
placeholder={endpoint ?? 'https://{service}.{region}.amazonaws.com'}
value={endpoint || ''}
onChange={onUpdateDatasourceJsonDataOption(props, 'endpoint')}
/>
</InlineField>
<InlineField
label="Default Region"
labelWidth={28}
tooltip="Specify the region, such as for US West (Oregon) use ` us-west-2 ` as the region."
>
<Select
className="width-30"
value={regions.find((region) => region.value === options.jsonData.defaultRegion)}
options={regions}
defaultValue={options.jsonData.defaultRegion}
allowCustomValue={true}
onChange={onUpdateDatasourceJsonDataOptionSelect(props, 'defaultRegion')}
formatCreateLabel={(r) => `Use region: ${r}`}
/>
</InlineField>
</FieldSet>
)}
{!hasEdgeAuth && <ConnectionConfig {...props} standardRegions={standardRegions} />}

<FieldSet label={'Edge settings'} data-testid="edge-connection">
{!endpoint && (
<Alert title="Edge region requires an explicit endpoint configured above" severity="warning" />
)}
<InlineFieldRow>
<InlineField
label="Authentication Mode"
labelWidth={labelWidth}
tooltip="Specify which authentication method to use."
>
<Select
className="width-30"
options={edgeAuthMethods}
value={edgeAuthMode}
onChange={(v) => {
updateDatasourcePluginJsonDataOption(props, 'edgeAuthMode', v.value);
}}
/>
</InlineField>
</InlineFieldRow>
{hasEdgeAuth && (
<>
<InlineFieldRow>
<InlineField
label="Username"
labelWidth={labelWidth}
tooltip="The username set to local authentication proxy"
>
<Input
name="username"
value={jsonData.edgeAuthUser}
autoComplete="off"
className="width-30"
onChange={onUserChange}
required
/>
</InlineField>
</InlineFieldRow>
<InlineFieldRow>
<InlineField
label="Password"
labelWidth={labelWidth}
tooltip="The password sent to local authentication proxy"
>
<Input
type="password"
name="password"
autoComplete="off"
placeholder={options.secureJsonFields?.edgeAuthPass ? 'configured' : ''}
value={options.secureJsonData?.edgeAuthPass ?? ''}
onChange={onPasswordChange}
onReset={onResetPassword}
className="width-30"
required
/>
</InlineField>
</InlineFieldRow>
</>
)}
<InlineFieldRow>
<InlineField
label="SSL Certificate"
labelWidth={labelWidth}
tooltip="Certificate for SSL enabled authentication."
>
{options.secureJsonFields?.cert ? (
<Button
variant="secondary"
type="reset"
onClick={onUpdateDatasourceResetOption(props as any, 'cert')}
>
Reset
</Button>
) : (
<textarea
rows={7}
className="gf-form-input gf-form-textarea width-30"
onChange={(event) => {
updateDatasourcePluginSecureJsonDataOption(props as any, 'cert', event.target.value);
}}
placeholder="Begins with -----BEGIN CERTIFICATE------"
required
/>
)}
</InlineField>
</InlineFieldRow>
</FieldSet>
</>
);
}

}
37 changes: 11 additions & 26 deletions src/components/query/ClientCacheRow.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,24 @@
import React from 'react';
import { InlineField, InlineSwitch, Switch } from '@grafana/ui';
import { Switch } from '@grafana/ui';
import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/experimental';

interface Props {
clientCache?: boolean;
newFormStylingEnabled?: boolean;
onClientCacheChange: (evt: React.SyntheticEvent<HTMLInputElement>) => void;
}

export const ClientCacheRow = ({clientCache, newFormStylingEnabled, onClientCacheChange}: Props) => {
if (newFormStylingEnabled) {
return (
<EditorRow>
<EditorFieldGroup>
<EditorField
label="Client cache"
htmlFor="clientCache"
tooltip="Enable to cache results in the browser that are older than 15 minutes. This will improve performance for repeated queries with relative time range."
>
<Switch id="clientCache" value={clientCache} onChange={onClientCacheChange} />
</EditorField>
</EditorFieldGroup>
</EditorRow>
);
}

export const ClientCacheRow = ({ clientCache, onClientCacheChange }: Props) => {
return (
<div className="gf-form">
<InlineField
<EditorRow>
<EditorFieldGroup>
<EditorField
label="Client cache"
htmlFor="clientCache"
tooltip="Enable to cache results from the query. This will improve performance for repeated queries with relative time range."
>
<InlineSwitch value={clientCache} onChange={onClientCacheChange} />
</InlineField>
</div>
tooltip="Enable to cache results in the browser that are older than 15 minutes. This will improve performance for repeated queries with relative time range."
>
<Switch id="clientCache" value={clientCache} onChange={onClientCacheChange} />
</EditorField>
</EditorFieldGroup>
</EditorRow>
);
};
43 changes: 3 additions & 40 deletions src/components/query/ListAssetsQueryEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import React, { PureComponent } from 'react';
import { DataFrameView, SelectableValue } from '@grafana/data';
import { ListAssetsQuery } from 'types';
import { InlineField, Select } from '@grafana/ui';
import { Select } from '@grafana/ui';
import { SitewiseQueryEditorProps } from './types';
import { AssetModelSummary } from 'queryResponseTypes';
import { firstLabelWith } from './QueryEditor';
import { EditorField, EditorFieldGroup, EditorRow } from '@grafana/experimental';

interface Props extends SitewiseQueryEditorProps<ListAssetsQuery> {
newFormStylingEnabled?: boolean;
}

interface State {
models?: DataFrameView<AssetModelSummary>;
}
Expand All @@ -24,7 +19,7 @@ const filters = [
{ label: 'All', value: 'ALL', description: 'The list includes all assets for a given asset model ID' },
];

export class ListAssetsQueryEditor extends PureComponent<Props, State> {
export class ListAssetsQueryEditor extends PureComponent<SitewiseQueryEditorProps<ListAssetsQuery>, State> {
state: State = {};

async componentDidMount() {
Expand Down Expand Up @@ -63,7 +58,7 @@ export class ListAssetsQueryEditor extends PureComponent<Props, State> {
};
}

return this.props.newFormStylingEnabled ? (
return (
<EditorRow>
<EditorFieldGroup>
<EditorField label="Model ID" htmlFor="model" width={30}>
Expand Down Expand Up @@ -95,38 +90,6 @@ export class ListAssetsQueryEditor extends PureComponent<Props, State> {
</EditorField>
</EditorFieldGroup>
</EditorRow>
) : (
<>
<div className="gf-form">
<InlineField htmlFor="model" label="Model ID" labelWidth={firstLabelWith} grow={true}>
<Select
inputId="model"
isLoading={!models}
options={modelIds}
value={currentModel}
onChange={this.onAssetModelIdChange}
placeholder="Select an asset model id"
allowCustomValue={true}
isClearable={true}
isSearchable={true}
formatCreateLabel={(txt) => `Model ID: ${txt}`}
menuPlacement="bottom"
/>
</InlineField>
</div>
<div className="gf-form">
<InlineField htmlFor="filter" label="Filter" labelWidth={firstLabelWith} grow={true}>
<Select
inputId="filter"
options={filters}
value={filters.find((v) => v.value === query.filter) || filters[0]}
onChange={this.onFilterChange}
placeholder="Select a property"
menuPlacement="bottom"
/>
</InlineField>
</div>
</>
);
}
}
Loading
Loading