mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DataSource: show the uid in edit url, not the local id (#33818)
This commit is contained in:
@@ -546,6 +546,7 @@ export interface DataSourceJsonData {
|
|||||||
*/
|
*/
|
||||||
export interface DataSourceSettings<T extends DataSourceJsonData = DataSourceJsonData, S = {}> {
|
export interface DataSourceSettings<T extends DataSourceJsonData = DataSourceJsonData, S = {}> {
|
||||||
id: number;
|
id: number;
|
||||||
|
uid: string;
|
||||||
orgId: number;
|
orgId: number;
|
||||||
name: string;
|
name: string;
|
||||||
typeLogoUrl: string;
|
typeLogoUrl: string;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
dataSourceConfig: {
|
dataSourceConfig: {
|
||||||
id: 4,
|
id: 4,
|
||||||
|
uid: 'x',
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
name: 'gdev-influxdb',
|
name: 'gdev-influxdb',
|
||||||
type: 'influxdb',
|
type: 'influxdb',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import mdx from './DataSourceHttpSettings.mdx';
|
|||||||
const settingsMock: DataSourceSettings<any, any> = {
|
const settingsMock: DataSourceSettings<any, any> = {
|
||||||
id: 4,
|
id: 4,
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
|
uid: 'x',
|
||||||
name: 'gdev-influxdb',
|
name: 'gdev-influxdb',
|
||||||
type: 'influxdb',
|
type: 'influxdb',
|
||||||
typeName: 'Influxdb',
|
typeName: 'Influxdb',
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export class InputQueryEditor extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { datasource, query } = this.props;
|
const { datasource, query } = this.props;
|
||||||
const { id, name } = datasource;
|
const { uid, name } = datasource;
|
||||||
const { text } = this.state;
|
const { text } = this.state;
|
||||||
|
|
||||||
const selected = query.data ? options[0] : options[1];
|
const selected = query.data ? options[0] : options[1];
|
||||||
@@ -73,7 +73,7 @@ export class InputQueryEditor extends PureComponent<Props, State> {
|
|||||||
{query.data ? (
|
{query.data ? (
|
||||||
<div style={{ alignSelf: 'center' }}>{describeDataFrame(query.data)}</div>
|
<div style={{ alignSelf: 'center' }}>{describeDataFrame(query.data)}</div>
|
||||||
) : (
|
) : (
|
||||||
<LinkButton variant="link" href={`datasources/edit/${id}/`}>
|
<LinkButton variant="link" href={`datasources/edit/${uid}/`}>
|
||||||
{name}: {describeDataFrame(datasource.data)}
|
{name}: {describeDataFrame(datasource.data)}
|
||||||
<Icon name="pen" />
|
<Icon name="pen" />
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
|
|||||||
@@ -96,13 +96,13 @@ export const RuleList: FC = () => {
|
|||||||
)}
|
)}
|
||||||
{promReqeustErrors.map(({ dataSource, error }) => (
|
{promReqeustErrors.map(({ dataSource, error }) => (
|
||||||
<div key={dataSource.name}>
|
<div key={dataSource.name}>
|
||||||
Failed to load rules state from <a href={`datasources/edit/${dataSource.id}`}>{dataSource.name}</a>:{' '}
|
Failed to load rules state from <a href={`datasources/edit/${dataSource.uid}`}>{dataSource.name}</a>:{' '}
|
||||||
{error.message || 'Unknown error.'}
|
{error.message || 'Unknown error.'}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{rulerRequestErrors.map(({ dataSource, error }) => (
|
{rulerRequestErrors.map(({ dataSource, error }) => (
|
||||||
<div key={dataSource.name}>
|
<div key={dataSource.name}>
|
||||||
Failed to load rules config from <a href={'datasources/edit/${dataSource.id}'}>{dataSource.name}</a>:{' '}
|
Failed to load rules config from <a href={'datasources/edit/${dataSource.uid}'}>{dataSource.name}</a>:{' '}
|
||||||
{error.message || 'Unknown error.'}
|
{error.message || 'Unknown error.'}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
navModel: {} as NavModel,
|
navModel: {} as NavModel,
|
||||||
dashboards: [] as PluginDashboard[],
|
dashboards: [] as PluginDashboard[],
|
||||||
dataSource: {} as DataSourceSettings,
|
dataSource: {} as DataSourceSettings,
|
||||||
dataSourceId: 1,
|
dataSourceId: 'x',
|
||||||
importDashboard: jest.fn(),
|
importDashboard: jest.fn(),
|
||||||
loadDataSource: jest.fn(),
|
loadDataSource: jest.fn(),
|
||||||
loadPluginDashboards: jest.fn(),
|
loadPluginDashboards: jest.fn(),
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import { getDataSource } from './state/selectors';
|
|||||||
import { PluginDashboard, StoreState } from 'app/types';
|
import { PluginDashboard, StoreState } from 'app/types';
|
||||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||||
|
|
||||||
export interface OwnProps extends GrafanaRouteComponentProps<{ id: string }> {}
|
export interface OwnProps extends GrafanaRouteComponentProps<{ uid: string }> {}
|
||||||
|
|
||||||
function mapStateToProps(state: StoreState, props: OwnProps) {
|
function mapStateToProps(state: StoreState, props: OwnProps) {
|
||||||
const dataSourceId = parseInt(props.match.params.id, 10);
|
const dataSourceId = props.match.params.uid;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
navModel: getNavModel(state.navIndex, `datasource-dashboards-${dataSourceId}`),
|
navModel: getNavModel(state.navIndex, `datasource-dashboards-${dataSourceId}`),
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const DataSourcesList: FC<Props> = ({ dataSources, layoutMode }) => {
|
|||||||
{dataSources.map((dataSource, index) => {
|
{dataSources.map((dataSource, index) => {
|
||||||
return (
|
return (
|
||||||
<li key={dataSource.id}>
|
<li key={dataSource.id}>
|
||||||
<Card heading={dataSource.name} href={`datasources/edit/${dataSource.id}`}>
|
<Card heading={dataSource.name} href={`datasources/edit/${dataSource.uid}`}>
|
||||||
<Card.Figure>
|
<Card.Figure>
|
||||||
<img src={dataSource.typeLogoUrl} alt={dataSource.name} />
|
<img src={dataSource.typeLogoUrl} alt={dataSource.name} />
|
||||||
</Card.Figure>
|
</Card.Figure>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export const getMockDataSource = (): DataSourceSettings => {
|
|||||||
withCredentials: false,
|
withCredentials: false,
|
||||||
database: '',
|
database: '',
|
||||||
id: 13,
|
id: 13,
|
||||||
|
uid: 'x',
|
||||||
isDefault: false,
|
isDefault: false,
|
||||||
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' },
|
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' },
|
||||||
name: 'gdev-cloudwatch',
|
name: 'gdev-cloudwatch',
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { DataSourceSettings } from '@grafana/data';
|
|||||||
export function createDatasourceSettings<T>(jsonData: T): DataSourceSettings<T> {
|
export function createDatasourceSettings<T>(jsonData: T): DataSourceSettings<T> {
|
||||||
return {
|
return {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
uid: 'x',
|
||||||
orgId: 0,
|
orgId: 0,
|
||||||
name: 'datasource-test',
|
name: 'datasource-test',
|
||||||
typeLogoUrl: '',
|
typeLogoUrl: '',
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const getProps = (): Props => ({
|
|||||||
},
|
},
|
||||||
dataSource: getMockDataSource(),
|
dataSource: getMockDataSource(),
|
||||||
dataSourceMeta: getMockPlugin(),
|
dataSourceMeta: getMockPlugin(),
|
||||||
dataSourceId: 1,
|
dataSourceId: 'x',
|
||||||
deleteDataSource: jest.fn(),
|
deleteDataSource: jest.fn(),
|
||||||
loadDataSource: jest.fn(),
|
loadDataSource: jest.fn(),
|
||||||
setDataSourceName,
|
setDataSourceName,
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ import { connect, ConnectedProps } from 'react-redux';
|
|||||||
import { cleanUpAction } from 'app/core/actions/cleanUp';
|
import { cleanUpAction } from 'app/core/actions/cleanUp';
|
||||||
import { ShowConfirmModalEvent } from '../../../types/events';
|
import { ShowConfirmModalEvent } from '../../../types/events';
|
||||||
|
|
||||||
export interface OwnProps extends GrafanaRouteComponentProps<{ id: string }> {}
|
export interface OwnProps extends GrafanaRouteComponentProps<{ uid: string }> {}
|
||||||
|
|
||||||
function mapStateToProps(state: StoreState, props: OwnProps) {
|
function mapStateToProps(state: StoreState, props: OwnProps) {
|
||||||
const dataSourceId = props.match.params.id;
|
const dataSourceId = props.match.params.uid;
|
||||||
const params = new URLSearchParams(props.location.search);
|
const params = new URLSearchParams(props.location.search);
|
||||||
const dataSource = getDataSource(state.dataSources, dataSourceId);
|
const dataSource = getDataSource(state.dataSources, dataSourceId);
|
||||||
const { plugin, loadError, testingStatus } = state.dataSourceSettings;
|
const { plugin, loadError, testingStatus } = state.dataSourceSettings;
|
||||||
@@ -49,7 +49,7 @@ function mapStateToProps(state: StoreState, props: OwnProps) {
|
|||||||
),
|
),
|
||||||
dataSource: getDataSource(state.dataSources, dataSourceId),
|
dataSource: getDataSource(state.dataSources, dataSourceId),
|
||||||
dataSourceMeta: getDataSourceMeta(state.dataSources, dataSource.type),
|
dataSourceMeta: getDataSourceMeta(state.dataSources, dataSource.type),
|
||||||
dataSourceId: parseInt(dataSourceId, 10),
|
dataSourceId: dataSourceId,
|
||||||
page,
|
page,
|
||||||
plugin,
|
plugin,
|
||||||
loadError,
|
loadError,
|
||||||
|
|||||||
@@ -72,23 +72,21 @@ describe('Find new name', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('initDataSourceSettings', () => {
|
describe('initDataSourceSettings', () => {
|
||||||
describe('when pageId is not a number', () => {
|
describe('when pageId is missing', () => {
|
||||||
it('then initDataSourceSettingsFailed should be dispatched', async () => {
|
it('then initDataSourceSettingsFailed should be dispatched', async () => {
|
||||||
const dispatchedActions = await thunkTester({})
|
const dispatchedActions = await thunkTester({}).givenThunk(initDataSourceSettings).whenThunkIsDispatched('');
|
||||||
.givenThunk(initDataSourceSettings)
|
|
||||||
.whenThunkIsDispatched('some page');
|
|
||||||
|
|
||||||
expect(dispatchedActions).toEqual([initDataSourceSettingsFailed(new Error('Invalid ID'))]);
|
expect(dispatchedActions).toEqual([initDataSourceSettingsFailed(new Error('Invalid ID'))]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when pageId is a number', () => {
|
describe('when pageId is a valid', () => {
|
||||||
it('then initDataSourceSettingsSucceeded should be dispatched', async () => {
|
it('then initDataSourceSettingsSucceeded should be dispatched', async () => {
|
||||||
const thunkMock = (): ThunkResult<void> => (dispatch: ThunkDispatch, getState) => {};
|
const thunkMock = (): ThunkResult<void> => (dispatch: ThunkDispatch, getState) => {};
|
||||||
const dataSource = { type: 'app' };
|
const dataSource = { type: 'app' };
|
||||||
const dataSourceMeta = { id: 'some id' };
|
const dataSourceMeta = { id: 'some id' };
|
||||||
const dependencies: InitDataSourceSettingDependencies = {
|
const dependencies: InitDataSourceSettingDependencies = {
|
||||||
loadDataSource: jest.fn(thunkMock),
|
loadDataSource: jest.fn(thunkMock) as any,
|
||||||
getDataSource: jest.fn().mockReturnValue(dataSource),
|
getDataSource: jest.fn().mockReturnValue(dataSource),
|
||||||
getDataSourceMeta: jest.fn().mockReturnValue(dataSourceMeta),
|
getDataSourceMeta: jest.fn().mockReturnValue(dataSourceMeta),
|
||||||
importDataSourcePlugin: jest.fn().mockReturnValue({} as GenericDataSourcePlugin),
|
importDataSourcePlugin: jest.fn().mockReturnValue({} as GenericDataSourcePlugin),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { getBackendSrv } from 'app/core/services/backend_srv';
|
|||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { updateNavIndex } from 'app/core/actions';
|
import { updateNavIndex } from 'app/core/actions';
|
||||||
import { buildNavModel } from './navModel';
|
import { buildNavModel } from './navModel';
|
||||||
import { DataSourcePluginMeta, DataSourceSettings } from '@grafana/data';
|
import { DataSourcePluginMeta, DataSourceSettings, locationUtil } from '@grafana/data';
|
||||||
import { DataSourcePluginCategory, ThunkResult, ThunkDispatch } from 'app/types';
|
import { DataSourcePluginCategory, ThunkResult, ThunkDispatch } from 'app/types';
|
||||||
import { getPluginSettings } from 'app/features/plugins/PluginSettingsCache';
|
import { getPluginSettings } from 'app/features/plugins/PluginSettingsCache';
|
||||||
import { importDataSourcePlugin } from 'app/features/plugins/plugin_loader';
|
import { importDataSourcePlugin } from 'app/features/plugins/plugin_loader';
|
||||||
@@ -41,7 +41,7 @@ export interface TestDataSourceDependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const initDataSourceSettings = (
|
export const initDataSourceSettings = (
|
||||||
pageId: number,
|
pageId: string,
|
||||||
dependencies: InitDataSourceSettingDependencies = {
|
dependencies: InitDataSourceSettingDependencies = {
|
||||||
loadDataSource,
|
loadDataSource,
|
||||||
getDataSource,
|
getDataSource,
|
||||||
@@ -49,14 +49,16 @@ export const initDataSourceSettings = (
|
|||||||
importDataSourcePlugin,
|
importDataSourcePlugin,
|
||||||
}
|
}
|
||||||
): ThunkResult<void> => {
|
): ThunkResult<void> => {
|
||||||
return async (dispatch: ThunkDispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
if (isNaN(pageId)) {
|
if (!pageId) {
|
||||||
dispatch(initDataSourceSettingsFailed(new Error('Invalid ID')));
|
dispatch(initDataSourceSettingsFailed(new Error('Invalid ID')));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await dispatch(dependencies.loadDataSource(pageId));
|
await dispatch(dependencies.loadDataSource(pageId));
|
||||||
|
|
||||||
|
// have we already loaded the plugin then we can skip the steps below?
|
||||||
if (getState().dataSourceSettings.plugin) {
|
if (getState().dataSourceSettings.plugin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -111,9 +113,9 @@ export function loadDataSources(): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function loadDataSource(id: number): ThunkResult<void> {
|
export function loadDataSource(uid: string): ThunkResult<void> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
const dataSource = (await getBackendSrv().get(`/api/datasources/${id}`)) as DataSourceSettings;
|
const dataSource = await getDataSourceUsingUidOrId(uid);
|
||||||
const pluginInfo = (await getPluginSettings(dataSource.type)) as DataSourcePluginMeta;
|
const pluginInfo = (await getPluginSettings(dataSource.type)) as DataSourcePluginMeta;
|
||||||
const plugin = await importDataSourcePlugin(pluginInfo);
|
const plugin = await importDataSourcePlugin(pluginInfo);
|
||||||
|
|
||||||
@@ -123,6 +125,50 @@ export function loadDataSource(id: number): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get data source by uid or id, if old id detected handles redirect
|
||||||
|
*/
|
||||||
|
async function getDataSourceUsingUidOrId(uid: string): Promise<DataSourceSettings> {
|
||||||
|
// Try first with uid api
|
||||||
|
try {
|
||||||
|
const byUid = await getBackendSrv()
|
||||||
|
.fetch<DataSourceSettings>({
|
||||||
|
method: 'GET',
|
||||||
|
url: `/api/datasources/uid/${uid}`,
|
||||||
|
showErrorAlert: false,
|
||||||
|
})
|
||||||
|
.toPromise();
|
||||||
|
|
||||||
|
if (byUid.ok) {
|
||||||
|
return byUid.data;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log('Failed to lookup data source by uid', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try lookup by old db id
|
||||||
|
const id = parseInt(uid, 10);
|
||||||
|
if (!Number.isNaN(id)) {
|
||||||
|
const response = await getBackendSrv()
|
||||||
|
.fetch<DataSourceSettings>({
|
||||||
|
method: 'GET',
|
||||||
|
url: `/api/datasources/${id}`,
|
||||||
|
showErrorAlert: false,
|
||||||
|
})
|
||||||
|
.toPromise();
|
||||||
|
|
||||||
|
// Not ideal to do a full page reload here but so tricky to handle this otherwise
|
||||||
|
// We can update the location using react router, but need to fully reload the route as the nav model
|
||||||
|
// page index is not matching with the url in that case. And react router has no way to unmount remount a route
|
||||||
|
if (response.ok && response.data.id.toString() === uid) {
|
||||||
|
window.location.href = locationUtil.assureBaseUrl(`/datasources/edit/${response.data.uid}`);
|
||||||
|
return {} as DataSourceSettings; // avoids flashing an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Error('Could not find data source');
|
||||||
|
}
|
||||||
|
|
||||||
export function addDataSource(plugin: DataSourcePluginMeta): ThunkResult<void> {
|
export function addDataSource(plugin: DataSourcePluginMeta): ThunkResult<void> {
|
||||||
return async (dispatch, getStore) => {
|
return async (dispatch, getStore) => {
|
||||||
await dispatch(loadDataSources());
|
await dispatch(loadDataSources());
|
||||||
@@ -141,7 +187,7 @@ export function addDataSource(plugin: DataSourcePluginMeta): ThunkResult<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await getBackendSrv().post('/api/datasources', newInstance);
|
const result = await getBackendSrv().post('/api/datasources', newInstance);
|
||||||
locationService.push(`/datasources/edit/${result.id}`);
|
locationService.push(`/datasources/edit/${result.datasource.uid}`);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,9 +202,9 @@ export function loadDataSourcePlugins(): ThunkResult<void> {
|
|||||||
|
|
||||||
export function updateDataSource(dataSource: DataSourceSettings): ThunkResult<void> {
|
export function updateDataSource(dataSource: DataSourceSettings): ThunkResult<void> {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
await getBackendSrv().put(`/api/datasources/${dataSource.id}`, dataSource);
|
await getBackendSrv().put(`/api/datasources/${dataSource.id}`, dataSource); // by UID not yet supported
|
||||||
await updateFrontendSettings();
|
await updateFrontendSettings();
|
||||||
return dispatch(loadDataSource(dataSource.id));
|
return dispatch(loadDataSource(dataSource.uid));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDat
|
|||||||
|
|
||||||
const navModel: NavModelItem = {
|
const navModel: NavModelItem = {
|
||||||
img: pluginMeta.info.logos.large,
|
img: pluginMeta.info.logos.large,
|
||||||
id: 'datasource-' + dataSource.id,
|
id: 'datasource-' + dataSource.uid,
|
||||||
subTitle: `Type: ${pluginMeta.name}`,
|
subTitle: `Type: ${pluginMeta.name}`,
|
||||||
url: '',
|
url: '',
|
||||||
text: dataSource.name,
|
text: dataSource.name,
|
||||||
@@ -16,9 +16,9 @@ export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDat
|
|||||||
{
|
{
|
||||||
active: false,
|
active: false,
|
||||||
icon: 'sliders-v-alt',
|
icon: 'sliders-v-alt',
|
||||||
id: `datasource-settings-${dataSource.id}`,
|
id: `datasource-settings-${dataSource.uid}`,
|
||||||
text: 'Settings',
|
text: 'Settings',
|
||||||
url: `datasources/edit/${dataSource.id}/`,
|
url: `datasources/edit/${dataSource.uid}/`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -29,7 +29,7 @@ export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDat
|
|||||||
active: false,
|
active: false,
|
||||||
text: page.title,
|
text: page.title,
|
||||||
icon: page.icon,
|
icon: page.icon,
|
||||||
url: `datasources/edit/${dataSource.id}/?page=${page.id}`,
|
url: `datasources/edit/${dataSource.uid}/?page=${page.id}`,
|
||||||
id: `datasource-page-${page.id}`,
|
id: `datasource-page-${page.id}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -39,9 +39,9 @@ export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDat
|
|||||||
navModel.children!.push({
|
navModel.children!.push({
|
||||||
active: false,
|
active: false,
|
||||||
icon: 'apps',
|
icon: 'apps',
|
||||||
id: `datasource-dashboards-${dataSource.id}`,
|
id: `datasource-dashboards-${dataSource.uid}`,
|
||||||
text: 'Dashboards',
|
text: 'Dashboards',
|
||||||
url: `datasources/edit/${dataSource.id}/dashboards`,
|
url: `datasources/edit/${dataSource.uid}/dashboards`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,25 +49,25 @@ export function buildNavModel(dataSource: DataSourceSettings, plugin: GenericDat
|
|||||||
navModel.children!.push({
|
navModel.children!.push({
|
||||||
active: false,
|
active: false,
|
||||||
icon: 'lock',
|
icon: 'lock',
|
||||||
id: `datasource-permissions-${dataSource.id}`,
|
id: `datasource-permissions-${dataSource.uid}`,
|
||||||
text: 'Permissions',
|
text: 'Permissions',
|
||||||
url: `datasources/edit/${dataSource.id}/permissions`,
|
url: `datasources/edit/${dataSource.uid}/permissions`,
|
||||||
});
|
});
|
||||||
|
|
||||||
navModel.children!.push({
|
navModel.children!.push({
|
||||||
active: false,
|
active: false,
|
||||||
icon: 'info-circle',
|
icon: 'info-circle',
|
||||||
id: `datasource-insights-${dataSource.id}`,
|
id: `datasource-insights-${dataSource.uid}`,
|
||||||
text: 'Insights',
|
text: 'Insights',
|
||||||
url: `datasources/edit/${dataSource.id}/insights`,
|
url: `datasources/edit/${dataSource.uid}/insights`,
|
||||||
});
|
});
|
||||||
|
|
||||||
navModel.children!.push({
|
navModel.children!.push({
|
||||||
active: false,
|
active: false,
|
||||||
icon: 'database',
|
icon: 'database',
|
||||||
id: `datasource-cache-${dataSource.id}`,
|
id: `datasource-cache-${dataSource.uid}`,
|
||||||
text: 'Cache',
|
text: 'Cache',
|
||||||
url: `datasources/edit/${dataSource.id}/cache`,
|
url: `datasources/edit/${dataSource.uid}/cache`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +84,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel {
|
|||||||
withCredentials: false,
|
withCredentials: false,
|
||||||
database: '',
|
database: '',
|
||||||
id: 1,
|
id: 1,
|
||||||
|
uid: 'x',
|
||||||
isDefault: false,
|
isDefault: false,
|
||||||
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' },
|
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' },
|
||||||
name: 'Loading',
|
name: 'Loading',
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const getDataSourcePlugins = (state: DataSourcesState) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getDataSource = (state: DataSourcesState, dataSourceId: UrlQueryValue): DataSourceSettings => {
|
export const getDataSource = (state: DataSourcesState, dataSourceId: UrlQueryValue): DataSourceSettings => {
|
||||||
if (state.dataSource.id === parseInt(dataSourceId as string, 10)) {
|
if (state.dataSource.uid === dataSourceId) {
|
||||||
return state.dataSource;
|
return state.dataSource;
|
||||||
}
|
}
|
||||||
return {} as DataSourceSettings;
|
return {} as DataSourceSettings;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
options: {
|
options: {
|
||||||
id: 1,
|
id: 1,
|
||||||
|
uid: 'z',
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
typeLogoUrl: '',
|
typeLogoUrl: '',
|
||||||
name: 'CloudWatch',
|
name: 'CloudWatch',
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ exports[`Render should disable access key id field 1`] = `
|
|||||||
"type": "cloudwatch",
|
"type": "cloudwatch",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Cloudwatch",
|
"typeName": "Cloudwatch",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"withCredentials": false,
|
"withCredentials": false,
|
||||||
@@ -101,6 +102,7 @@ exports[`Render should render component 1`] = `
|
|||||||
"type": "cloudwatch",
|
"type": "cloudwatch",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Cloudwatch",
|
"typeName": "Cloudwatch",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"withCredentials": false,
|
"withCredentials": false,
|
||||||
@@ -165,6 +167,7 @@ exports[`Render should show access key and secret access key fields 1`] = `
|
|||||||
"type": "cloudwatch",
|
"type": "cloudwatch",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Cloudwatch",
|
"typeName": "Cloudwatch",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"withCredentials": false,
|
"withCredentials": false,
|
||||||
@@ -229,6 +232,7 @@ exports[`Render should show arn role field 1`] = `
|
|||||||
"type": "cloudwatch",
|
"type": "cloudwatch",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Cloudwatch",
|
"typeName": "Cloudwatch",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"withCredentials": false,
|
"withCredentials": false,
|
||||||
@@ -293,6 +297,7 @@ exports[`Render should show credentials profile name field 1`] = `
|
|||||||
"type": "cloudwatch",
|
"type": "cloudwatch",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Cloudwatch",
|
"typeName": "Cloudwatch",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"withCredentials": false,
|
"withCredentials": false,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
options: {
|
options: {
|
||||||
id: 21,
|
id: 21,
|
||||||
|
uid: 'x',
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
name: 'Azure Monitor-10-10',
|
name: 'Azure Monitor-10-10',
|
||||||
type: 'grafana-azure-monitor-datasource',
|
type: 'grafana-azure-monitor-datasource',
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const setup = () => {
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
options: {
|
options: {
|
||||||
id: 21,
|
id: 21,
|
||||||
|
uid: 'y',
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
name: 'Azure Monitor-10-10',
|
name: 'Azure Monitor-10-10',
|
||||||
type: 'grafana-azure-monitor-datasource',
|
type: 'grafana-azure-monitor-datasource',
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
options: {
|
options: {
|
||||||
id: 21,
|
id: 21,
|
||||||
|
uid: 'x',
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
name: 'Azure Monitor-10-10',
|
name: 'Azure Monitor-10-10',
|
||||||
type: 'grafana-azure-monitor-datasource',
|
type: 'grafana-azure-monitor-datasource',
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ exports[`Render should render component 1`] = `
|
|||||||
"type": "grafana-azure-monitor-datasource",
|
"type": "grafana-azure-monitor-datasource",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Azure",
|
"typeName": "Azure",
|
||||||
|
"uid": "y",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@@ -69,6 +70,7 @@ exports[`Render should render component 1`] = `
|
|||||||
"type": "grafana-azure-monitor-datasource",
|
"type": "grafana-azure-monitor-datasource",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Azure",
|
"typeName": "Azure",
|
||||||
|
"uid": "y",
|
||||||
"url": "/api/datasources/proxy/21",
|
"url": "/api/datasources/proxy/21",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@@ -109,6 +111,7 @@ exports[`Render should render component 1`] = `
|
|||||||
"type": "grafana-azure-monitor-datasource",
|
"type": "grafana-azure-monitor-datasource",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Azure",
|
"typeName": "Azure",
|
||||||
|
"uid": "y",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@@ -145,6 +148,7 @@ exports[`Render should render component 1`] = `
|
|||||||
"type": "grafana-azure-monitor-datasource",
|
"type": "grafana-azure-monitor-datasource",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Azure",
|
"typeName": "Azure",
|
||||||
|
"uid": "y",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ const setup = (propOverrides?: object) => {
|
|||||||
const props: Props = {
|
const props: Props = {
|
||||||
options: {
|
options: {
|
||||||
id: 21,
|
id: 21,
|
||||||
|
uid: 'z',
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
name: 'InfluxDB-3',
|
name: 'InfluxDB-3',
|
||||||
type: 'influxdb',
|
type: 'influxdb',
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ exports[`Render should disable basic auth password input 1`] = `
|
|||||||
"type": "influxdb",
|
"type": "influxdb",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Influx",
|
"typeName": "Influx",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@@ -389,6 +390,7 @@ exports[`Render should hide basic auth fields when switch off 1`] = `
|
|||||||
"type": "influxdb",
|
"type": "influxdb",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Influx",
|
"typeName": "Influx",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@@ -685,6 +687,7 @@ exports[`Render should hide white listed cookies input when browser access chose
|
|||||||
"type": "influxdb",
|
"type": "influxdb",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Influx",
|
"typeName": "Influx",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
@@ -981,6 +984,7 @@ exports[`Render should render component 1`] = `
|
|||||||
"type": "influxdb",
|
"type": "influxdb",
|
||||||
"typeLogoUrl": "",
|
"typeLogoUrl": "",
|
||||||
"typeName": "Influx",
|
"typeName": "Influx",
|
||||||
|
"uid": "z",
|
||||||
"url": "",
|
"url": "",
|
||||||
"user": "",
|
"user": "",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export function getAppRoutes(): RouteDescriptor[] {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/datasources/edit/:id/',
|
path: '/datasources/edit/:uid/',
|
||||||
component: SafeDynamicImport(
|
component: SafeDynamicImport(
|
||||||
() =>
|
() =>
|
||||||
import(
|
import(
|
||||||
@@ -103,7 +103,7 @@ export function getAppRoutes(): RouteDescriptor[] {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/datasources/edit/:id/dashboards',
|
path: '/datasources/edit/:uid/dashboards',
|
||||||
component: SafeDynamicImport(
|
component: SafeDynamicImport(
|
||||||
() => import(/* webpackChunkName: "DataSourceDashboards"*/ 'app/features/datasources/DataSourceDashboards')
|
() => import(/* webpackChunkName: "DataSourceDashboards"*/ 'app/features/datasources/DataSourceDashboards')
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user