restore basicSettings component and apply feature toggle

This commit is contained in:
Taewoo Kim
2023-05-11 11:38:07 -04:00
parent 806f8a9e2e
commit 6562581ede
8 changed files with 216 additions and 3 deletions
+3
View File
@@ -2593,6 +2593,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "10"],
[0, 0, 0, "Unexpected any. Specify a different type.", "11"]
],
"public/app/features/datasources/components/BasicSettings.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
"public/app/features/datasources/components/DataSourceReadOnlyMessage.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
],
@@ -0,0 +1,34 @@
import { useLocation, useParams } from 'react-router-dom';
import {
useDataSource,
useDataSourceSettingsNav as useDataSourceSettingsNavOriginal,
} from 'app/features/datasources/state/hooks';
import { useGetSingle } from 'app/features/plugins/admin/state/hooks';
// We are extending the original useDataSourceSettingsNav in the following ways:
// - changing the URL of the nav items to point to Connections
// - setting the parent nav item
export function useDataSourceSettingsNav(pageId?: string) {
const { uid } = useParams<{ uid: string }>();
const location = useLocation();
const datasource = useDataSource(uid);
const datasourcePlugin = useGetSingle(datasource.type);
const params = new URLSearchParams(location.search);
const nav = useDataSourceSettingsNavOriginal(uid, pageId || params.get('page'));
const pageNav = {
...nav.main,
text: datasource.name,
subTitle: `Type: ${datasourcePlugin?.name}`,
active: true,
children: (nav.main.children || []).map((navModelItem) => ({
...navModelItem,
url: navModelItem.url?.replace('datasources/edit/', '/connections/datasources/edit/'),
})),
};
return {
navId: 'connections-datasources',
pageNav,
};
}
@@ -1,13 +1,31 @@
import * as React from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { config } from '@grafana/runtime';
import { Page } from 'app/core/components/Page/Page';
import DataSourceTabPage from 'app/features/datasources/components/DataSourceTabPage';
import { EditDataSource } from 'app/features/datasources/components/EditDataSource';
import { EditDataSourceActions } from 'app/features/datasources/components/EditDataSourceActions';
import { useDataSourceSettingsNav } from '../hooks/useDataSourceSettingsNav';
export function EditDataSourcePage() {
const { uid } = useParams<{ uid: string }>();
const location = useLocation();
const params = new URLSearchParams(location.search);
const pageId = params.get('page');
const dataSourcePageHeader = config.featureToggles.dataSourcePageHeader;
const { navId, pageNav } = useDataSourceSettingsNav();
return <DataSourceTabPage uid={uid} pageId={pageId} navId="connections-datasources" />;
if (dataSourcePageHeader) {
return <DataSourceTabPage uid={uid} pageId={pageId} navId="connections-datasources" />;
}
return (
<Page navId={navId} pageNav={pageNav} actions={<EditDataSourceActions uid={uid} />}>
<Page.Contents>
<EditDataSource uid={uid} pageId={pageId} />
</Page.Contents>
</Page>
);
}
@@ -0,0 +1,27 @@
import { render, screen } from '@testing-library/react';
import React from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { BasicSettings, Props } from './BasicSettings';
const setup = () => {
const props: Props = {
dataSourceName: 'Graphite',
isDefault: false,
onDefaultChange: jest.fn(),
onNameChange: jest.fn(),
alertingSupported: false,
};
return render(<BasicSettings {...props} />);
};
describe('<BasicSettings>', () => {
it('should render component', () => {
setup();
expect(screen.getByRole('textbox', { name: selectors.pages.DataSource.name })).toBeInTheDocument();
expect(screen.getByRole('checkbox', { name: /Default/ })).toBeInTheDocument();
});
});
@@ -0,0 +1,85 @@
import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { InlineField, InlineSwitch, Input, Badge, useStyles2 } from '@grafana/ui';
export interface Props {
dataSourceName: string;
isDefault: boolean;
onNameChange: (name: string) => void;
onDefaultChange: (value: boolean) => void;
alertingSupported: boolean;
disabled?: boolean;
}
export function BasicSettings({
dataSourceName,
isDefault,
onDefaultChange,
onNameChange,
alertingSupported,
disabled,
}: Props) {
return (
<>
<AlertingEnabled enabled={alertingSupported} />
<div className="gf-form-group" aria-label="Datasource settings page basic settings">
<div className="gf-form-inline">
{/* Name */}
<div className="gf-form max-width-30">
<InlineField
label="Name"
tooltip="The name is used when you select the data source in panels. The default data source is
'preselected in new panels."
grow
disabled={disabled}
>
<Input
id="basic-settings-name"
type="text"
value={dataSourceName}
placeholder="Name"
onChange={(event) => onNameChange(event.currentTarget.value)}
required
aria-label={selectors.pages.DataSource.name}
/>
</InlineField>
</div>
{/* Is Default */}
<InlineField label="Default" labelWidth={8} disabled={disabled}>
<InlineSwitch
id="basic-settings-default"
value={isDefault}
onChange={(event: React.FormEvent<HTMLInputElement>) => {
onDefaultChange(event.currentTarget.checked);
}}
/>
</InlineField>
</div>
</div>
</>
);
}
export function AlertingEnabled({ enabled }: { enabled: boolean }) {
const styles = useStyles2(getStyles);
return (
<div className={styles.badge}>
{enabled ? (
<Badge color="green" icon="check-circle" text="Alerting supported" />
) : (
<Badge color="orange" icon="exclamation-triangle" text="Alerting not supported" />
)}
</div>
);
}
const getStyles = (theme: GrafanaTheme2) => ({
badge: css`
margin-bottom: ${theme.spacing(2)};
`,
});
@@ -37,6 +37,8 @@ const setup = (props?: Partial<ViewProps>) => {
dataSourceRights={{ readOnly: false, hasWriteRights: true, hasDeleteRights: true }}
exploreUrl={'/explore'}
onDelete={jest.fn()}
onDefaultChange={jest.fn()}
onNameChange={jest.fn()}
onOptionsChange={jest.fn()}
onTest={jest.fn()}
onUpdate={jest.fn()}
@@ -6,12 +6,14 @@ import {
DataSourcePluginMeta,
DataSourceSettings as DataSourceSettingsType,
} from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { getDataSourceSrv, config } from '@grafana/runtime';
import PageLoader from 'app/core/components/PageLoader/PageLoader';
import { DataSourceSettingsState, useDispatch } from 'app/types';
import {
dataSourceLoaded,
setDataSourceName,
setIsDefault,
useDataSource,
useDataSourceExploreUrl,
useDataSourceMeta,
@@ -24,6 +26,7 @@ import {
} from '../state';
import { DataSourceRights } from '../types';
import { BasicSettings } from './BasicSettings';
import { ButtonRow } from './ButtonRow';
import { CloudInfoBox } from './CloudInfoBox';
import { DataSourceLoadError } from './DataSourceLoadError';
@@ -53,6 +56,8 @@ export function EditDataSource({ uid, pageId }: Props) {
const onDelete = useDeleteLoadedDataSource();
const onTest = useTestDataSource(uid);
const onUpdate = useUpdateDatasource();
const onDefaultChange = (value: boolean) => dispatch(setIsDefault(value));
const onNameChange = (name: string) => dispatch(setDataSourceName(name));
const onOptionsChange = (ds: DataSourceSettingsType) => dispatch(dataSourceLoaded(ds));
return (
@@ -64,6 +69,8 @@ export function EditDataSource({ uid, pageId }: Props) {
dataSourceRights={dataSourceRights}
exploreUrl={exploreUrl}
onDelete={onDelete}
onDefaultChange={onDefaultChange}
onNameChange={onNameChange}
onOptionsChange={onOptionsChange}
onTest={onTest}
onUpdate={onUpdate}
@@ -79,6 +86,8 @@ export type ViewProps = {
dataSourceRights: DataSourceRights;
exploreUrl: string;
onDelete: () => void;
onDefaultChange: (isDefault: boolean) => AnyAction;
onNameChange: (name: string) => AnyAction;
onOptionsChange: (dataSource: DataSourceSettingsType) => AnyAction;
onTest: () => void;
onUpdate: (dataSource: DataSourceSettingsType) => Promise<DataSourceSettingsType>;
@@ -92,6 +101,8 @@ export function EditDataSourceView({
dataSourceRights,
exploreUrl,
onDelete,
onDefaultChange,
onNameChange,
onOptionsChange,
onTest,
onUpdate,
@@ -102,6 +113,11 @@ export function EditDataSourceView({
const dsi = getDataSourceSrv()?.getInstanceSettings(dataSource.uid);
const hasAlertingEnabled = Boolean(dsi?.meta?.alerting ?? false);
const isAlertManagerDatasource = dsi?.type === 'alertmanager';
const alertingSupported = hasAlertingEnabled || isAlertManagerDatasource;
const dataSourcePageHeader = config.featureToggles.dataSourcePageHeader;
const onSubmit = async (e: React.MouseEvent<HTMLButtonElement> | React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
@@ -142,6 +158,17 @@ export function EditDataSourceView({
<CloudInfoBox dataSource={dataSource} />
{!dataSourcePageHeader && (
<BasicSettings
dataSourceName={dataSource.name}
isDefault={dataSource.isDefault}
onDefaultChange={onDefaultChange}
onNameChange={onNameChange}
alertingSupported={alertingSupported}
disabled={readOnly || !hasWriteRights}
/>
)}
{plugin && (
<DataSourcePluginContextProvider instanceSettings={dsi}>
<DataSourcePluginSettings
@@ -1,8 +1,13 @@
import React from 'react';
import { config } from '@grafana/runtime';
import { Page } from 'app/core/components/Page/Page';
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
import DataSourceTabPage from '../components/DataSourceTabPage';
import { EditDataSource } from '../components/EditDataSource';
import { EditDataSourceActions } from '../components/EditDataSourceActions';
import { useDataSourceSettingsNav } from '../state';
export interface Props extends GrafanaRouteComponentProps<{ uid: string }> {}
@@ -10,8 +15,20 @@ export function EditDataSourcePage(props: Props) {
const uid = props.match.params.uid;
const params = new URLSearchParams(props.location.search);
const pageId = params.get('page');
const dataSourcePageHeader = config.featureToggles.dataSourcePageHeader;
const nav = useDataSourceSettingsNav(uid, pageId);
return <DataSourceTabPage uid={uid} pageId={pageId} navId="datasources" />;
if (dataSourcePageHeader) {
return <DataSourceTabPage uid={uid} pageId={pageId} navId="datasources" />;
}
return (
<Page navId="datasources" pageNav={nav.main} actions={<EditDataSourceActions uid={uid} />}>
<Page.Contents>
<EditDataSource uid={uid} pageId={pageId} />
</Page.Contents>
</Page>
);
}
export default EditDataSourcePage;