commandSource.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import {Component} from 'react';
  2. import {PlainRoute} from 'react-router';
  3. import {openHelpSearchModal, openSudo} from 'sentry/actionCreators/modal';
  4. import Access from 'sentry/components/acl/access';
  5. import {t, toggleLocaleDebug} from 'sentry/locale';
  6. import ConfigStore from 'sentry/stores/configStore';
  7. import {createFuzzySearch, Fuse} from 'sentry/utils/fuzzySearch';
  8. import {ChildProps, ResultItem} from './types';
  9. type Action = {
  10. action: () => void;
  11. description: string;
  12. requiresSuperuser: boolean;
  13. title: string;
  14. };
  15. const ACTIONS: Action[] = [
  16. {
  17. title: t('Open Sudo Modal'),
  18. description: t('Open Sudo Modal to re-identify yourself.'),
  19. requiresSuperuser: false,
  20. action: () =>
  21. openSudo({
  22. sudo: true,
  23. }),
  24. },
  25. {
  26. title: t('Open Superuser Modal'),
  27. description: t('Open Superuser Modal to re-identify yourself.'),
  28. requiresSuperuser: true,
  29. action: () =>
  30. openSudo({
  31. isSuperuser: true,
  32. }),
  33. },
  34. {
  35. title: t('Toggle dark mode'),
  36. description: t('Toggle dark mode (superuser only atm)'),
  37. requiresSuperuser: true,
  38. action: () =>
  39. ConfigStore.set('theme', ConfigStore.get('theme') === 'dark' ? 'light' : 'dark'),
  40. },
  41. {
  42. title: t('Toggle Translation Markers'),
  43. description: t('Toggles translation markers on or off in the application'),
  44. requiresSuperuser: true,
  45. action: () => {
  46. toggleLocaleDebug();
  47. window.location.reload();
  48. },
  49. },
  50. {
  51. title: t('Search Documentation and FAQ'),
  52. description: t('Open the Documentation and FAQ search modal.'),
  53. requiresSuperuser: false,
  54. action: () => {
  55. openHelpSearchModal();
  56. },
  57. },
  58. ];
  59. type Props = {
  60. children: (props: ChildProps) => React.ReactElement;
  61. isSuperuser: boolean;
  62. /**
  63. * search term
  64. */
  65. query: string;
  66. /**
  67. * Array of routes to search
  68. */
  69. searchMap?: PlainRoute[];
  70. /**
  71. * fuse.js options
  72. */
  73. searchOptions?: Fuse.IFuseOptions<Action>;
  74. };
  75. type State = {
  76. fuzzy: null | Fuse<Action>;
  77. };
  78. /**
  79. * This source is a hardcoded list of action creators and/or routes maybe
  80. */
  81. class CommandSource extends Component<Props, State> {
  82. static defaultProps = {
  83. searchMap: [],
  84. searchOptions: {},
  85. };
  86. state: State = {
  87. fuzzy: null,
  88. };
  89. componentDidMount() {
  90. this.createSearch(ACTIONS);
  91. }
  92. async createSearch(searchMap: Action[]) {
  93. const options = {
  94. ...this.props.searchOptions,
  95. keys: ['title', 'description'],
  96. };
  97. this.setState({
  98. fuzzy: await createFuzzySearch<Action>(searchMap || [], options),
  99. });
  100. }
  101. render() {
  102. const {searchMap, query, isSuperuser, children} = this.props;
  103. const {fuzzy} = this.state;
  104. const results =
  105. fuzzy
  106. ?.search(query)
  107. .filter(({item}) => !item.requiresSuperuser || isSuperuser)
  108. .map(value => {
  109. const {item, ...rest} = value;
  110. return {
  111. item: {
  112. ...item,
  113. sourceType: 'command',
  114. resultType: 'command',
  115. } as ResultItem,
  116. ...rest,
  117. };
  118. }) ?? [];
  119. return children({
  120. isLoading: searchMap === null,
  121. results,
  122. });
  123. }
  124. }
  125. const CommandSourceWithFeature = (props: Omit<Props, 'isSuperuser'>) => (
  126. <Access isSuperuser>
  127. {({hasSuperuser}) => <CommandSource {...props} isSuperuser={hasSuperuser} />}
  128. </Access>
  129. );
  130. export default CommandSourceWithFeature;
  131. export {CommandSource};