apiTokenRow.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import styled from '@emotion/styled';
  2. import {Button} from 'sentry/components/button';
  3. import DateTime from 'sentry/components/dateTime';
  4. import PanelItem from 'sentry/components/panels/panelItem';
  5. import {IconSubtract} from 'sentry/icons';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. import {InternalAppApiToken} from 'sentry/types';
  9. import getDynamicText from 'sentry/utils/getDynamicText';
  10. import {tokenPreview} from 'sentry/views/settings/organizationAuthTokens';
  11. type Props = {
  12. onRemove: (token: InternalAppApiToken) => void;
  13. token: InternalAppApiToken;
  14. tokenPrefix?: string;
  15. };
  16. // TODO: After the BE portion of code changes have been released, remove the conditional rendering of the token.
  17. // We are currently doing the conditional logic to do safe blue/green deploys and handle contract changes.
  18. function ApiTokenRow({token, onRemove, tokenPrefix = ''}: Props) {
  19. return (
  20. <StyledPanelItem>
  21. <Controls>
  22. <TokenPreview aria-label={t('Token preview')}>
  23. {tokenPreview(
  24. getDynamicText({
  25. value: token.tokenLastCharacters,
  26. fixed: 'ABCD',
  27. }),
  28. tokenPrefix
  29. )}
  30. </TokenPreview>
  31. <ButtonWrapper>
  32. <Button
  33. onClick={() => onRemove(token)}
  34. icon={<IconSubtract isCircled size="xs" />}
  35. >
  36. {t('Remove')}
  37. </Button>
  38. </ButtonWrapper>
  39. </Controls>
  40. <Details>
  41. <ScopesWrapper>
  42. <Heading>{t('Scopes')}</Heading>
  43. <ScopeList>{token.scopes.join(', ')}</ScopeList>
  44. </ScopesWrapper>
  45. <div>
  46. <Heading>{t('Created')}</Heading>
  47. <Time>
  48. <DateTime
  49. date={getDynamicText({
  50. value: token.dateCreated,
  51. fixed: new Date(1508208080000), // National Pasta Day
  52. })}
  53. />
  54. </Time>
  55. </div>
  56. </Details>
  57. </StyledPanelItem>
  58. );
  59. }
  60. const StyledPanelItem = styled(PanelItem)`
  61. flex-direction: column;
  62. padding: ${space(2)};
  63. `;
  64. const Controls = styled('div')`
  65. display: flex;
  66. align-items: center;
  67. margin-bottom: ${space(1)};
  68. `;
  69. const Details = styled('div')`
  70. display: flex;
  71. margin-top: ${space(1)};
  72. `;
  73. const ScopesWrapper = styled('div')`
  74. flex: 1;
  75. `;
  76. const ScopeList = styled('div')`
  77. font-size: ${p => p.theme.fontSizeRelativeSmall};
  78. line-height: 1.4;
  79. `;
  80. const Time = styled('time')`
  81. font-size: ${p => p.theme.fontSizeRelativeSmall};
  82. line-height: 1.4;
  83. `;
  84. const Heading = styled('div')`
  85. font-size: ${p => p.theme.fontSizeMedium};
  86. text-transform: uppercase;
  87. color: ${p => p.theme.subText};
  88. margin-bottom: ${space(1)};
  89. `;
  90. const TokenPreview = styled('div')`
  91. color: ${p => p.theme.gray300};
  92. `;
  93. const ButtonWrapper = styled('div')`
  94. margin-left: auto;
  95. display: flex;
  96. flex-direction: column;
  97. align-items: flex-end;
  98. justify-content: flex-end;
  99. font-size: ${p => p.theme.fontSizeSmall};
  100. gap: ${space(1)};
  101. `;
  102. export default ApiTokenRow;