mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
wip: Reactify the api keys page #13411
This commit is contained in:
parent
31b8bf2d47
commit
353a836128
94
public/app/features/api-keys/ApiKeysPage.tsx
Normal file
94
public/app/features/api-keys/ApiKeysPage.tsx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { hot } from 'react-hot-loader';
|
||||||
|
import { NavModel, ApiKey } from '../../types';
|
||||||
|
import { getNavModel } from 'app/core/selectors/navModel';
|
||||||
|
// import { getSearchQuery, getTeams, getTeamsCount } from './state/selectors';
|
||||||
|
import PageHeader from 'app/core/components/PageHeader/PageHeader';
|
||||||
|
import { loadApiKeys, deleteApiKey } from './state/actions';
|
||||||
|
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
navModel: NavModel;
|
||||||
|
apiKeys: ApiKey[];
|
||||||
|
searchQuery: string;
|
||||||
|
loadApiKeys: typeof loadApiKeys;
|
||||||
|
deleteApiKey: typeof deleteApiKey;
|
||||||
|
// loadTeams: typeof loadTeams;
|
||||||
|
// deleteTeam: typeof deleteTeam;
|
||||||
|
// setSearchQuery: typeof setSearchQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApiKeysPage extends PureComponent<Props, any> {
|
||||||
|
componentDidMount() {
|
||||||
|
this.fetchApiKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchApiKeys() {
|
||||||
|
await this.props.loadApiKeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteApiKey(id: number) {
|
||||||
|
return () => {
|
||||||
|
this.props.deleteApiKey(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { navModel, apiKeys } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PageHeader model={navModel} />
|
||||||
|
<div className="page-container page-body">
|
||||||
|
<h3 className="page-heading">Existing Keys</h3>
|
||||||
|
<table className="filter-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Role</th>
|
||||||
|
<th style={{ width: '34px' }} />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{apiKeys.length > 0 ? (
|
||||||
|
<tbody>
|
||||||
|
{apiKeys.map(key => {
|
||||||
|
// id, name, role
|
||||||
|
return (
|
||||||
|
<tr key={key.id}>
|
||||||
|
<td>{key.name}</td>
|
||||||
|
<td>{key.role}</td>
|
||||||
|
<td>
|
||||||
|
<a onClick={this.deleteApiKey(key.id)} className="btn btn-danger btn-mini">
|
||||||
|
<i className="fa fa-remove" />
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
) : null}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
navModel: getNavModel(state.navIndex, 'apikeys'),
|
||||||
|
apiKeys: state.apiKeys.keys,
|
||||||
|
// searchQuery: getSearchQuery(state.teams),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = {
|
||||||
|
loadApiKeys,
|
||||||
|
deleteApiKey,
|
||||||
|
// loadTeams,
|
||||||
|
// deleteTeam,
|
||||||
|
// setSearchQuery,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(ApiKeysPage));
|
37
public/app/features/api-keys/state/actions.ts
Normal file
37
public/app/features/api-keys/state/actions.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ThunkAction } from 'redux-thunk';
|
||||||
|
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||||
|
import { StoreState, ApiKey } from 'app/types';
|
||||||
|
import { updateNavIndex, UpdateNavIndexAction } from 'app/core/actions';
|
||||||
|
|
||||||
|
export enum ActionTypes {
|
||||||
|
LoadApiKeys = 'LOAD_API_KEYS',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoadApiKeysAction {
|
||||||
|
type: ActionTypes.LoadApiKeys;
|
||||||
|
payload: ApiKey[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Action = LoadApiKeysAction;
|
||||||
|
|
||||||
|
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action | UpdateNavIndexAction>;
|
||||||
|
|
||||||
|
const apiKeysLoaded = (apiKeys: ApiKey[]): LoadApiKeysAction => ({
|
||||||
|
type: ActionTypes.LoadApiKeys,
|
||||||
|
payload: apiKeys,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function loadApiKeys(): ThunkResult<void> {
|
||||||
|
return async dispatch => {
|
||||||
|
const response = await getBackendSrv().get('/api/auth/keys');
|
||||||
|
dispatch(apiKeysLoaded(response));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteApiKey(id: number): ThunkResult<void> {
|
||||||
|
return async dispatch => {
|
||||||
|
getBackendSrv()
|
||||||
|
.delete('/api/auth/keys/' + id)
|
||||||
|
.then(dispatch(loadApiKeys()));
|
||||||
|
};
|
||||||
|
}
|
16
public/app/features/api-keys/state/reducers.ts
Normal file
16
public/app/features/api-keys/state/reducers.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ApiKeysState } from 'app/types';
|
||||||
|
import { Action, ActionTypes } from './actions';
|
||||||
|
|
||||||
|
export const initialApiKeysState: ApiKeysState = { keys: [] };
|
||||||
|
|
||||||
|
export const apiKeysReducer = (state = initialApiKeysState, action: Action): ApiKeysState => {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionTypes.LoadApiKeys:
|
||||||
|
return { ...state, keys: action.payload };
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
apiKeys: apiKeysReducer,
|
||||||
|
};
|
@ -5,6 +5,7 @@ import ServerStats from 'app/features/admin/ServerStats';
|
|||||||
import AlertRuleList from 'app/features/alerting/AlertRuleList';
|
import AlertRuleList from 'app/features/alerting/AlertRuleList';
|
||||||
import TeamPages from 'app/features/teams/TeamPages';
|
import TeamPages from 'app/features/teams/TeamPages';
|
||||||
import TeamList from 'app/features/teams/TeamList';
|
import TeamList from 'app/features/teams/TeamList';
|
||||||
|
import ApiKeys from 'app/features/api-keys/ApiKeysPage';
|
||||||
import FolderSettingsPage from 'app/features/folders/FolderSettingsPage';
|
import FolderSettingsPage from 'app/features/folders/FolderSettingsPage';
|
||||||
import FolderPermissions from 'app/features/folders/FolderPermissions';
|
import FolderPermissions from 'app/features/folders/FolderPermissions';
|
||||||
|
|
||||||
@ -141,6 +142,13 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
templateUrl: 'public/app/features/org/partials/orgApiKeys.html',
|
templateUrl: 'public/app/features/org/partials/orgApiKeys.html',
|
||||||
controller: 'OrgApiKeysCtrl',
|
controller: 'OrgApiKeysCtrl',
|
||||||
})
|
})
|
||||||
|
.when('/org/apikeys2', {
|
||||||
|
template: '<react-container />',
|
||||||
|
resolve: {
|
||||||
|
roles: () => ['Editor', 'Admin'],
|
||||||
|
component: () => ApiKeys,
|
||||||
|
},
|
||||||
|
})
|
||||||
.when('/org/teams', {
|
.when('/org/teams', {
|
||||||
template: '<react-container />',
|
template: '<react-container />',
|
||||||
resolve: {
|
resolve: {
|
||||||
|
@ -4,6 +4,7 @@ import { createLogger } from 'redux-logger';
|
|||||||
import sharedReducers from 'app/core/reducers';
|
import sharedReducers from 'app/core/reducers';
|
||||||
import alertingReducers from 'app/features/alerting/state/reducers';
|
import alertingReducers from 'app/features/alerting/state/reducers';
|
||||||
import teamsReducers from 'app/features/teams/state/reducers';
|
import teamsReducers from 'app/features/teams/state/reducers';
|
||||||
|
import apiKeysReducers from 'app/features/api-keys/state/reducers';
|
||||||
import foldersReducers from 'app/features/folders/state/reducers';
|
import foldersReducers from 'app/features/folders/state/reducers';
|
||||||
import dashboardReducers from 'app/features/dashboard/state/reducers';
|
import dashboardReducers from 'app/features/dashboard/state/reducers';
|
||||||
|
|
||||||
@ -11,6 +12,7 @@ const rootReducer = combineReducers({
|
|||||||
...sharedReducers,
|
...sharedReducers,
|
||||||
...alertingReducers,
|
...alertingReducers,
|
||||||
...teamsReducers,
|
...teamsReducers,
|
||||||
|
...apiKeysReducers,
|
||||||
...foldersReducers,
|
...foldersReducers,
|
||||||
...dashboardReducers,
|
...dashboardReducers,
|
||||||
});
|
});
|
||||||
|
11
public/app/types/apiKeys.ts
Normal file
11
public/app/types/apiKeys.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { OrgRole } from './acl';
|
||||||
|
|
||||||
|
export interface ApiKey {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
role: OrgRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ApiKeysState {
|
||||||
|
keys: ApiKey[];
|
||||||
|
}
|
@ -7,6 +7,7 @@ import { DashboardState } from './dashboard';
|
|||||||
import { DashboardAcl, OrgRole, PermissionLevel } from './acl';
|
import { DashboardAcl, OrgRole, PermissionLevel } from './acl';
|
||||||
import { DataSource } from './datasources';
|
import { DataSource } from './datasources';
|
||||||
import { PluginMeta } from './plugins';
|
import { PluginMeta } from './plugins';
|
||||||
|
import { ApiKey, ApiKeysState } from './apiKeys';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Team,
|
Team,
|
||||||
@ -33,6 +34,8 @@ export {
|
|||||||
PermissionLevel,
|
PermissionLevel,
|
||||||
DataSource,
|
DataSource,
|
||||||
PluginMeta,
|
PluginMeta,
|
||||||
|
ApiKey,
|
||||||
|
ApiKeysState,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface StoreState {
|
export interface StoreState {
|
||||||
|
Loading…
Reference in New Issue
Block a user