import React, { PureComponent } from 'react'; import ReactDOMServer from 'react-dom/server'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; import { NavModel, ApiKey, NewApiKey, OrgRole } from 'app/types'; import { getNavModel } from 'app/core/selectors/navModel'; import { getApiKeys, getApiKeysCount } from './state/selectors'; import { loadApiKeys, deleteApiKey, setSearchQuery, addApiKey } from './state/actions'; import PageHeader from 'app/core/components/PageHeader/PageHeader'; import PageLoader from 'app/core/components/PageLoader/PageLoader'; import SlideDown from 'app/core/components/Animations/SlideDown'; import ApiKeysAddedModal from './ApiKeysAddedModal'; import config from 'app/core/config'; import appEvents from 'app/core/app_events'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import { DeleteButton } from '@grafana/ui'; export interface Props { navModel: NavModel; apiKeys: ApiKey[]; searchQuery: string; hasFetched: boolean; loadApiKeys: typeof loadApiKeys; deleteApiKey: typeof deleteApiKey; setSearchQuery: typeof setSearchQuery; addApiKey: typeof addApiKey; apiKeysCount: number; } export interface State { isAdding: boolean; newApiKey: NewApiKey; } enum ApiKeyStateProps { Name = 'name', Role = 'role', } const initialApiKeyState = { name: '', role: OrgRole.Viewer, }; export class ApiKeysPage extends PureComponent { constructor(props) { super(props); this.state = { isAdding: false, newApiKey: initialApiKeyState }; } componentDidMount() { this.fetchApiKeys(); } async fetchApiKeys() { await this.props.loadApiKeys(); } onDeleteApiKey(key: ApiKey) { this.props.deleteApiKey(key.id); } onSearchQueryChange = evt => { this.props.setSearchQuery(evt.target.value); }; onToggleAdding = () => { this.setState({ isAdding: !this.state.isAdding }); }; onAddApiKey = async evt => { evt.preventDefault(); const openModal = (apiKey: string) => { const rootPath = window.location.origin + config.appSubUrl; const modalTemplate = ReactDOMServer.renderToString(); appEvents.emit('show-modal', { templateHtml: modalTemplate, }); }; this.props.addApiKey(this.state.newApiKey, openModal); this.setState((prevState: State) => { return { ...prevState, newApiKey: initialApiKeyState, isAdding: false, }; }); }; onApiKeyStateUpdate = (evt, prop: string) => { const value = evt.currentTarget.value; this.setState((prevState: State) => { const newApiKey = { ...prevState.newApiKey, }; newApiKey[prop] = value; return { ...prevState, newApiKey: newApiKey, }; }); }; renderEmptyList() { const { isAdding } = this.state; return (
{!isAdding && ( )} {this.renderAddApiKeyForm()}
); } renderAddApiKeyForm() { const { newApiKey, isAdding } = this.state; return (
Add API Key
Key name this.onApiKeyStateUpdate(evt, ApiKeyStateProps.Name)} />
Role
); } renderApiKeyList() { const { isAdding } = this.state; const { apiKeys, searchQuery } = this.props; return (
{this.renderAddApiKeyForm()}

Existing Keys

{apiKeys.length > 0 ? ( {apiKeys.map(key => { return ( ); })} ) : null}
Name Role
{key.name} {key.role} this.onDeleteApiKey(key)} />
); } render() { const { hasFetched, navModel, apiKeysCount } = this.props; return (
{hasFetched ? ( apiKeysCount > 0 ? ( this.renderApiKeyList() ) : ( this.renderEmptyList() ) ) : ( )}
); } } function mapStateToProps(state) { return { navModel: getNavModel(state.navIndex, 'apikeys'), apiKeys: getApiKeys(state.apiKeys), searchQuery: state.apiKeys.searchQuery, apiKeysCount: getApiKeysCount(state.apiKeys), hasFetched: state.apiKeys.hasFetched, }; } const mapDispatchToProps = { loadApiKeys, deleteApiKey, setSearchQuery, addApiKey, }; export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(ApiKeysPage));