ApiKeysTable.tsx 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. import { css } from '@emotion/css';
  2. import React, { FC } from 'react';
  3. import { dateTimeFormat, GrafanaTheme2, TimeZone } from '@grafana/data';
  4. import { DeleteButton, Icon, IconName, Tooltip, useTheme2 } from '@grafana/ui';
  5. import { contextSrv } from 'app/core/core';
  6. import { AccessControlAction } from 'app/types';
  7. import { ApiKey } from '../../types';
  8. interface Props {
  9. apiKeys: ApiKey[];
  10. timeZone: TimeZone;
  11. onDelete: (apiKey: ApiKey) => void;
  12. }
  13. export const ApiKeysTable: FC<Props> = ({ apiKeys, timeZone, onDelete }) => {
  14. const theme = useTheme2();
  15. const styles = getStyles(theme);
  16. return (
  17. <table className="filter-table">
  18. <thead>
  19. <tr>
  20. <th>Name</th>
  21. <th>Role</th>
  22. <th>Expires</th>
  23. <th style={{ width: '34px' }} />
  24. </tr>
  25. </thead>
  26. {apiKeys.length > 0 ? (
  27. <tbody>
  28. {apiKeys.map((key) => {
  29. const isExpired = Boolean(key.expiration && Date.now() > new Date(key.expiration).getTime());
  30. return (
  31. <tr key={key.id} className={styles.tableRow(isExpired)}>
  32. <td>{key.name}</td>
  33. <td>{key.role}</td>
  34. <td>
  35. {formatDate(key.expiration, timeZone)}
  36. {isExpired && (
  37. <span className={styles.tooltipContainer}>
  38. <Tooltip content="This API key has expired.">
  39. <Icon name={'exclamation-triangle' as IconName} />
  40. </Tooltip>
  41. </span>
  42. )}
  43. </td>
  44. <td>
  45. <DeleteButton
  46. aria-label="Delete API key"
  47. size="sm"
  48. onConfirm={() => onDelete(key)}
  49. disabled={!contextSrv.hasPermissionInMetadata(AccessControlAction.ActionAPIKeysDelete, key)}
  50. />
  51. </td>
  52. </tr>
  53. );
  54. })}
  55. </tbody>
  56. ) : null}
  57. </table>
  58. );
  59. };
  60. function formatDate(expiration: string | undefined, timeZone: TimeZone): string {
  61. if (!expiration) {
  62. return 'No expiration date';
  63. }
  64. return dateTimeFormat(expiration, { timeZone });
  65. }
  66. const getStyles = (theme: GrafanaTheme2) => ({
  67. tableRow: (isExpired: boolean) => css`
  68. color: ${isExpired ? theme.colors.text.secondary : theme.colors.text.primary};
  69. `,
  70. tooltipContainer: css`
  71. margin-left: ${theme.spacing(1)};
  72. `,
  73. });