mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Fixed nav model
This commit is contained in:
parent
ed349075a0
commit
4ecd33c79c
90
public/app/features/datasources/EditDataSourcePage.tsx
Normal file
90
public/app/features/datasources/EditDataSourcePage.tsx
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { hot } from 'react-hot-loader';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import PageHeader from '../../core/components/PageHeader/PageHeader';
|
||||||
|
import { DataSource, NavModel } from 'app/types';
|
||||||
|
import { loadDataSource } from './state/actions';
|
||||||
|
import { getNavModel } from '../../core/selectors/navModel';
|
||||||
|
import { getRouteParamsId, getRouteParamsPage } from '../../core/selectors/location';
|
||||||
|
import { getDataSourceLoadingNav } from './state/navModel';
|
||||||
|
import { getDataSource } from './state/selectors';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
navModel: NavModel;
|
||||||
|
dataSource: DataSource;
|
||||||
|
dataSourceId: number;
|
||||||
|
pageName: string;
|
||||||
|
loadDataSource: typeof loadDataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PageTypes {
|
||||||
|
Settings = 'settings',
|
||||||
|
Permissions = 'permissions',
|
||||||
|
Dashboards = 'dashboards',
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EditDataSourcePage extends PureComponent<Props> {
|
||||||
|
componentDidMount() {
|
||||||
|
this.fetchDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchDataSource() {
|
||||||
|
await this.props.loadDataSource(this.props.dataSourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
isValidPage(currentPage) {
|
||||||
|
return (Object as any).values(PageTypes).includes(currentPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentPage() {
|
||||||
|
const currentPage = this.props.pageName;
|
||||||
|
|
||||||
|
return this.isValidPage(currentPage) ? currentPage : PageTypes.Settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPage() {
|
||||||
|
switch (this.getCurrentPage()) {
|
||||||
|
case PageTypes.Settings:
|
||||||
|
return <div>Settings</div>;
|
||||||
|
|
||||||
|
case PageTypes.Permissions:
|
||||||
|
return <div>Permissions</div>;
|
||||||
|
|
||||||
|
case PageTypes.Dashboards:
|
||||||
|
return <div>Dashboards</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { navModel } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PageHeader model={navModel} />
|
||||||
|
<div className="page-container page-body" />
|
||||||
|
{this.renderPage()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
const pageName = getRouteParamsPage(state.location) || 'settings';
|
||||||
|
const dataSourceId = getRouteParamsId(state.location);
|
||||||
|
const dataSourceLoadingNav = getDataSourceLoadingNav(pageName);
|
||||||
|
|
||||||
|
return {
|
||||||
|
navModel: getNavModel(state.navIndex, `datasource-${pageName}-${dataSourceId}`, dataSourceLoadingNav),
|
||||||
|
dataSourceId: dataSourceId,
|
||||||
|
dataSource: getDataSource(state.dataSources, dataSourceId),
|
||||||
|
pageName: pageName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
loadDataSource,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(EditDataSourcePage));
|
@ -2,12 +2,14 @@ import { ThunkAction } from 'redux-thunk';
|
|||||||
import { DataSource, Plugin, StoreState } from 'app/types';
|
import { DataSource, Plugin, StoreState } from 'app/types';
|
||||||
import { getBackendSrv } from '../../../core/services/backend_srv';
|
import { getBackendSrv } from '../../../core/services/backend_srv';
|
||||||
import { LayoutMode } from '../../../core/components/LayoutSelector/LayoutSelector';
|
import { LayoutMode } from '../../../core/components/LayoutSelector/LayoutSelector';
|
||||||
import { updateLocation } from '../../../core/actions';
|
import { updateLocation, updateNavIndex, UpdateNavIndexAction } from '../../../core/actions';
|
||||||
import { UpdateLocationAction } from '../../../core/actions/location';
|
import { UpdateLocationAction } from '../../../core/actions/location';
|
||||||
|
import { buildNavModel } from './navModel';
|
||||||
|
|
||||||
export enum ActionTypes {
|
export enum ActionTypes {
|
||||||
LoadDataSources = 'LOAD_DATA_SOURCES',
|
LoadDataSources = 'LOAD_DATA_SOURCES',
|
||||||
LoadDataSourceTypes = 'LOAD_DATA_SOURCE_TYPES',
|
LoadDataSourceTypes = 'LOAD_DATA_SOURCE_TYPES',
|
||||||
|
LoadDataSource = 'LOAD_DATA_SOURCE',
|
||||||
SetDataSourcesSearchQuery = 'SET_DATA_SOURCES_SEARCH_QUERY',
|
SetDataSourcesSearchQuery = 'SET_DATA_SOURCES_SEARCH_QUERY',
|
||||||
SetDataSourcesLayoutMode = 'SET_DATA_SOURCES_LAYOUT_MODE',
|
SetDataSourcesLayoutMode = 'SET_DATA_SOURCES_LAYOUT_MODE',
|
||||||
SetDataSourceTypeSearchQuery = 'SET_DATA_SOURCE_TYPE_SEARCH_QUERY',
|
SetDataSourceTypeSearchQuery = 'SET_DATA_SOURCE_TYPE_SEARCH_QUERY',
|
||||||
@ -38,11 +40,21 @@ export interface SetDataSourceTypeSearchQueryAction {
|
|||||||
payload: string;
|
payload: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LoadDataSourceAction {
|
||||||
|
type: ActionTypes.LoadDataSource;
|
||||||
|
payload: DataSource;
|
||||||
|
}
|
||||||
|
|
||||||
const dataSourcesLoaded = (dataSources: DataSource[]): LoadDataSourcesAction => ({
|
const dataSourcesLoaded = (dataSources: DataSource[]): LoadDataSourcesAction => ({
|
||||||
type: ActionTypes.LoadDataSources,
|
type: ActionTypes.LoadDataSources,
|
||||||
payload: dataSources,
|
payload: dataSources,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dataSourceLoaded = (dataSource: DataSource): LoadDataSourceAction => ({
|
||||||
|
type: ActionTypes.LoadDataSource,
|
||||||
|
payload: dataSource,
|
||||||
|
});
|
||||||
|
|
||||||
const dataSourceTypesLoaded = (dataSourceTypes: Plugin[]): LoadDataSourceTypesAction => ({
|
const dataSourceTypesLoaded = (dataSourceTypes: Plugin[]): LoadDataSourceTypesAction => ({
|
||||||
type: ActionTypes.LoadDataSourceTypes,
|
type: ActionTypes.LoadDataSourceTypes,
|
||||||
payload: dataSourceTypes,
|
payload: dataSourceTypes,
|
||||||
@ -69,7 +81,9 @@ export type Action =
|
|||||||
| SetDataSourcesLayoutModeAction
|
| SetDataSourcesLayoutModeAction
|
||||||
| UpdateLocationAction
|
| UpdateLocationAction
|
||||||
| LoadDataSourceTypesAction
|
| LoadDataSourceTypesAction
|
||||||
| SetDataSourceTypeSearchQueryAction;
|
| SetDataSourceTypeSearchQueryAction
|
||||||
|
| LoadDataSourceAction
|
||||||
|
| UpdateNavIndexAction;
|
||||||
|
|
||||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
|
||||||
|
|
||||||
@ -80,6 +94,15 @@ export function loadDataSources(): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function loadDataSource(id: number): ThunkResult<void> {
|
||||||
|
return async dispatch => {
|
||||||
|
const dataSource = await getBackendSrv().get(`/api/datasources/${id}`);
|
||||||
|
const pluginInfo = await getBackendSrv().get(`/api/plugins/${dataSource.type}/settings`);
|
||||||
|
dispatch(dataSourceLoaded(dataSource));
|
||||||
|
dispatch(updateNavIndex(buildNavModel(dataSource, pluginInfo)));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function addDataSource(plugin: Plugin): ThunkResult<void> {
|
export function addDataSource(plugin: Plugin): ThunkResult<void> {
|
||||||
return async (dispatch, getStore) => {
|
return async (dispatch, getStore) => {
|
||||||
await dispatch(loadDataSources());
|
await dispatch(loadDataSources());
|
||||||
|
97
public/app/features/datasources/state/navModel.ts
Normal file
97
public/app/features/datasources/state/navModel.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { DataSource, NavModel, NavModelItem, PluginMeta } from 'app/types';
|
||||||
|
|
||||||
|
export function buildNavModel(dataSource: DataSource, pluginMeta: PluginMeta): NavModelItem {
|
||||||
|
const navModel = {
|
||||||
|
img: pluginMeta.info.logos.large,
|
||||||
|
id: 'datasource-' + dataSource.id,
|
||||||
|
subTitle: `Type: ${pluginMeta.name}`,
|
||||||
|
url: '',
|
||||||
|
text: dataSource.name,
|
||||||
|
breadcrumbs: [{ title: 'Data Sources', url: 'datasources' }],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
active: false,
|
||||||
|
icon: 'fa fa-fw fa-sliders',
|
||||||
|
id: `datasource-settings-${dataSource.id}`,
|
||||||
|
text: 'Settings',
|
||||||
|
url: `datasources/edit/${dataSource.id}/settings`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
active: false,
|
||||||
|
icon: 'fa fa-fw fa-sliders',
|
||||||
|
id: `datasource-permissions-${dataSource.id}`,
|
||||||
|
text: 'Permissions',
|
||||||
|
url: `datasources/edit/${dataSource.id}/permissions`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pluginMeta.includes && pluginMeta.includes.length > 0) {
|
||||||
|
navModel.children.push({
|
||||||
|
active: false,
|
||||||
|
icon: 'gicon gicon-dashboard',
|
||||||
|
id: `datasource-dashboards-${dataSource.id}`,
|
||||||
|
text: 'Dashboards',
|
||||||
|
url: `datasources/edit/${dataSource.id}/dashboards`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return navModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDataSourceLoadingNav(pageName: string): NavModel {
|
||||||
|
const main = buildNavModel(
|
||||||
|
{
|
||||||
|
access: '',
|
||||||
|
basicAuth: false,
|
||||||
|
database: '',
|
||||||
|
id: 1,
|
||||||
|
isDefault: false,
|
||||||
|
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' },
|
||||||
|
name: 'Loading',
|
||||||
|
orgId: 1,
|
||||||
|
password: '',
|
||||||
|
readOnly: false,
|
||||||
|
type: 'Loading',
|
||||||
|
typeLogoUrl: 'public/img/icn-datasource.svg',
|
||||||
|
url: '',
|
||||||
|
user: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '',
|
||||||
|
info: {
|
||||||
|
author: {
|
||||||
|
name: '',
|
||||||
|
url: '',
|
||||||
|
},
|
||||||
|
description: '',
|
||||||
|
links: [''],
|
||||||
|
logos: {
|
||||||
|
large: '',
|
||||||
|
small: '',
|
||||||
|
},
|
||||||
|
screenshots: '',
|
||||||
|
updated: '',
|
||||||
|
version: '',
|
||||||
|
},
|
||||||
|
includes: [{ type: '', name: '', path: '' }],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let node: NavModelItem;
|
||||||
|
|
||||||
|
// find active page
|
||||||
|
for (const child of main.children) {
|
||||||
|
if (child.id.indexOf(pageName) > 0) {
|
||||||
|
child.active = true;
|
||||||
|
node = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
main: main,
|
||||||
|
node: node,
|
||||||
|
};
|
||||||
|
}
|
@ -4,6 +4,7 @@ import { LayoutModes } from '../../../core/components/LayoutSelector/LayoutSelec
|
|||||||
|
|
||||||
const initialState: DataSourcesState = {
|
const initialState: DataSourcesState = {
|
||||||
dataSources: [] as DataSource[],
|
dataSources: [] as DataSource[],
|
||||||
|
dataSource: {} as DataSource,
|
||||||
layoutMode: LayoutModes.Grid,
|
layoutMode: LayoutModes.Grid,
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
dataSourcesCount: 0,
|
dataSourcesCount: 0,
|
||||||
@ -16,6 +17,9 @@ export const dataSourcesReducer = (state = initialState, action: Action): DataSo
|
|||||||
case ActionTypes.LoadDataSources:
|
case ActionTypes.LoadDataSources:
|
||||||
return { ...state, dataSources: action.payload, dataSourcesCount: action.payload.length };
|
return { ...state, dataSources: action.payload, dataSourcesCount: action.payload.length };
|
||||||
|
|
||||||
|
case ActionTypes.LoadDataSource:
|
||||||
|
return { ...state, dataSource: action.payload };
|
||||||
|
|
||||||
case ActionTypes.SetDataSourcesSearchQuery:
|
case ActionTypes.SetDataSourcesSearchQuery:
|
||||||
return { ...state, searchQuery: action.payload };
|
return { ...state, searchQuery: action.payload };
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { DataSource } from '../../../types';
|
||||||
|
|
||||||
export const getDataSources = state => {
|
export const getDataSources = state => {
|
||||||
const regex = new RegExp(state.searchQuery, 'i');
|
const regex = new RegExp(state.searchQuery, 'i');
|
||||||
|
|
||||||
@ -14,6 +16,13 @@ export const getDataSourceTypes = state => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDataSource = (state, dataSourceId): DataSource | null => {
|
||||||
|
if (state.dataSource.id === parseInt(dataSourceId, 10)) {
|
||||||
|
return state.dataSource;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
export const getDataSourcesSearchQuery = state => state.searchQuery;
|
export const getDataSourcesSearchQuery = state => state.searchQuery;
|
||||||
export const getDataSourcesLayoutMode = state => state.layoutMode;
|
export const getDataSourcesLayoutMode = state => state.layoutMode;
|
||||||
export const getDataSourcesCount = state => state.dataSourcesCount;
|
export const getDataSourcesCount = state => state.dataSourcesCount;
|
||||||
|
@ -12,6 +12,7 @@ import FolderPermissions from 'app/features/folders/FolderPermissions';
|
|||||||
import DataSourcesListPage from 'app/features/datasources/DataSourcesListPage';
|
import DataSourcesListPage from 'app/features/datasources/DataSourcesListPage';
|
||||||
import NewDataSourcePage from '../features/datasources/NewDataSourcePage';
|
import NewDataSourcePage from '../features/datasources/NewDataSourcePage';
|
||||||
import UsersListPage from 'app/features/users/UsersListPage';
|
import UsersListPage from 'app/features/users/UsersListPage';
|
||||||
|
import EditDataSourcePage from 'app/features/datasources/EditDataSourcePage';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
export function setupAngularRoutes($routeProvider, $locationProvider) {
|
export function setupAngularRoutes($routeProvider, $locationProvider) {
|
||||||
@ -71,15 +72,11 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
component: () => DataSourcesListPage,
|
component: () => DataSourcesListPage,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.when('/datasources/edit/:id', {
|
.when('/datasources/edit/:id/:page?', {
|
||||||
templateUrl: 'public/app/features/plugins/partials/ds_edit.html',
|
template: '<react-container />',
|
||||||
controller: 'DataSourceEditCtrl',
|
resolve: {
|
||||||
controllerAs: 'ctrl',
|
component: () => EditDataSourcePage,
|
||||||
})
|
},
|
||||||
.when('/datasources/edit/:id/dashboards', {
|
|
||||||
templateUrl: 'public/app/features/plugins/partials/ds_dashboards.html',
|
|
||||||
controller: 'DataSourceDashboardsCtrl',
|
|
||||||
controllerAs: 'ctrl',
|
|
||||||
})
|
})
|
||||||
.when('/datasources/new', {
|
.when('/datasources/new', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
|
@ -25,4 +25,5 @@ export interface DataSourcesState {
|
|||||||
layoutMode: LayoutMode;
|
layoutMode: LayoutMode;
|
||||||
dataSourcesCount: number;
|
dataSourcesCount: number;
|
||||||
dataSourceTypes: Plugin[];
|
dataSourceTypes: Plugin[];
|
||||||
|
dataSource: DataSource;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user