123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import React, { PureComponent } from 'react';
- import { connect, ConnectedProps } from 'react-redux';
- // Utils
- import { rangeUtil } from '@grafana/data';
- import { InlineField, InlineSwitch, VerticalGroup } from '@grafana/ui';
- import appEvents from 'app/core/app_events';
- import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
- import Page from 'app/core/components/Page/Page';
- import config from 'app/core/config';
- import { contextSrv } from 'app/core/core';
- import { getNavModel } from 'app/core/selectors/navModel';
- import { getTimeZone } from 'app/features/profile/state/selectors';
- import { AccessControlAction, ApiKey, NewApiKey, StoreState } from 'app/types';
- import { ShowModalReactEvent } from 'app/types/events';
- import { ApiKeysActionBar } from './ApiKeysActionBar';
- import { ApiKeysAddedModal } from './ApiKeysAddedModal';
- import { ApiKeysController } from './ApiKeysController';
- import { ApiKeysForm } from './ApiKeysForm';
- import { ApiKeysTable } from './ApiKeysTable';
- import { addApiKey, deleteApiKey, loadApiKeys, toggleIncludeExpired } from './state/actions';
- import { setSearchQuery } from './state/reducers';
- import { getApiKeys, getApiKeysCount, getIncludeExpired, getIncludeExpiredDisabled } from './state/selectors';
- function mapStateToProps(state: StoreState) {
- const canCreate = contextSrv.hasAccess(AccessControlAction.ActionAPIKeysCreate, true);
- return {
- navModel: getNavModel(state.navIndex, 'apikeys'),
- apiKeys: getApiKeys(state.apiKeys),
- searchQuery: state.apiKeys.searchQuery,
- apiKeysCount: getApiKeysCount(state.apiKeys),
- hasFetched: state.apiKeys.hasFetched,
- timeZone: getTimeZone(state.user),
- includeExpired: getIncludeExpired(state.apiKeys),
- includeExpiredDisabled: getIncludeExpiredDisabled(state.apiKeys),
- canCreate: canCreate,
- };
- }
- const mapDispatchToProps = {
- loadApiKeys,
- deleteApiKey,
- setSearchQuery,
- toggleIncludeExpired,
- addApiKey,
- };
- const connector = connect(mapStateToProps, mapDispatchToProps);
- interface OwnProps {}
- export type Props = OwnProps & ConnectedProps<typeof connector>;
- interface State {
- isAdding: boolean;
- }
- export class ApiKeysPageUnconnected extends PureComponent<Props, State> {
- constructor(props: Props) {
- super(props);
- }
- componentDidMount() {
- this.fetchApiKeys();
- }
- async fetchApiKeys() {
- await this.props.loadApiKeys();
- }
- onDeleteApiKey = (key: ApiKey) => {
- this.props.deleteApiKey(key.id!);
- };
- onSearchQueryChange = (value: string) => {
- this.props.setSearchQuery(value);
- };
- onIncludeExpiredChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
- this.props.toggleIncludeExpired();
- };
- onAddApiKey = (newApiKey: NewApiKey) => {
- const openModal = (apiKey: string) => {
- const rootPath = window.location.origin + config.appSubUrl;
- appEvents.publish(
- new ShowModalReactEvent({
- props: {
- apiKey,
- rootPath,
- },
- component: ApiKeysAddedModal,
- })
- );
- };
- const secondsToLive = newApiKey.secondsToLive;
- try {
- const secondsToLiveAsNumber = secondsToLive ? rangeUtil.intervalToSeconds(secondsToLive) : null;
- const apiKey: ApiKey = {
- ...newApiKey,
- secondsToLive: secondsToLiveAsNumber,
- };
- this.props.addApiKey(apiKey, openModal);
- this.setState((prevState: State) => {
- return {
- ...prevState,
- isAdding: false,
- };
- });
- } catch (err) {
- console.error(err);
- }
- };
- render() {
- const {
- hasFetched,
- navModel,
- apiKeysCount,
- apiKeys,
- searchQuery,
- timeZone,
- includeExpired,
- includeExpiredDisabled,
- canCreate,
- } = this.props;
- if (!hasFetched) {
- return (
- <Page navModel={navModel}>
- <Page.Contents isLoading={true}>{}</Page.Contents>
- </Page>
- );
- }
- return (
- <Page navModel={navModel}>
- <Page.Contents isLoading={false}>
- <ApiKeysController>
- {({ isAdding, toggleIsAdding }) => {
- const showCTA = !isAdding && apiKeysCount === 0;
- const showTable = apiKeysCount > 0;
- return (
- <>
- {showCTA ? (
- <EmptyListCTA
- title="You haven't added any API keys yet."
- buttonIcon="key-skeleton-alt"
- onClick={toggleIsAdding}
- buttonTitle="New API key"
- proTip="Remember, you can provide view-only API access to other applications."
- buttonDisabled={!canCreate}
- />
- ) : null}
- {showTable ? (
- <ApiKeysActionBar
- searchQuery={searchQuery}
- disabled={isAdding || !canCreate}
- onAddClick={toggleIsAdding}
- onSearchChange={this.onSearchQueryChange}
- />
- ) : null}
- <ApiKeysForm
- show={isAdding}
- onClose={toggleIsAdding}
- onKeyAdded={this.onAddApiKey}
- disabled={!canCreate}
- />
- {showTable ? (
- <VerticalGroup>
- <InlineField disabled={includeExpiredDisabled} label="Include expired keys">
- <InlineSwitch id="showExpired" value={includeExpired} onChange={this.onIncludeExpiredChange} />
- </InlineField>
- <ApiKeysTable apiKeys={apiKeys} timeZone={timeZone} onDelete={this.onDeleteApiKey} />
- </VerticalGroup>
- ) : null}
- </>
- );
- }}
- </ApiKeysController>
- </Page.Contents>
- </Page>
- );
- }
- }
- const ApiKeysPage = connector(ApiKeysPageUnconnected);
- export default ApiKeysPage;
|