pdf-compile-button.jsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { useTranslation } from 'react-i18next'
  2. import { memo } from 'react'
  3. import classNames from 'classnames'
  4. import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
  5. import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error'
  6. import SplitMenu from '../../../shared/components/split-menu'
  7. import Icon from '../../../shared/components/icon'
  8. import * as eventTracking from '../../../infrastructure/event-tracking'
  9. const modifierKey = /Mac/i.test(navigator.platform) ? 'Cmd' : 'Ctrl'
  10. function sendEventAndSet(value, setter, settingName) {
  11. eventTracking.sendMB('recompile-setting-changed', {
  12. setting: settingName,
  13. settingVal: value,
  14. })
  15. setter(value)
  16. }
  17. function PdfCompileButton() {
  18. const {
  19. animateCompileDropdownArrow,
  20. autoCompile,
  21. compiling,
  22. draft,
  23. hasChanges,
  24. setAnimateCompileDropdownArrow,
  25. setAutoCompile,
  26. setDraft,
  27. setStopOnValidationError,
  28. stopOnFirstError,
  29. stopOnValidationError,
  30. startCompile,
  31. stopCompile,
  32. recompileFromScratch,
  33. } = useCompileContext()
  34. const { enableStopOnFirstError, disableStopOnFirstError } =
  35. useStopOnFirstError({ eventSource: 'dropdown' })
  36. const { t } = useTranslation()
  37. const fromScratchWithEvent = () => {
  38. eventTracking.sendMB('recompile-setting-changed', {
  39. setting: 'from-scratch',
  40. })
  41. recompileFromScratch()
  42. }
  43. const compileButtonLabel = compiling ? `${t('compiling')}…` : t('recompile')
  44. const tooltipElement = (
  45. <>
  46. {t('recompile_pdf')}{' '}
  47. <span className="keyboard-shortcut">({modifierKey} + Enter)</span>
  48. </>
  49. )
  50. const dropdownToggleClassName = classNames({
  51. 'detach-compile-button-animate': animateCompileDropdownArrow,
  52. 'btn-striped-animated': hasChanges,
  53. 'no-left-border': true,
  54. })
  55. const buttonClassName = classNames({
  56. 'btn-striped-animated': hasChanges,
  57. 'no-left-radius': true,
  58. })
  59. return (
  60. <SplitMenu
  61. bsStyle="primary"
  62. bsSize="xs"
  63. disabled={compiling}
  64. button={{
  65. tooltip: {
  66. description: tooltipElement,
  67. id: 'compile',
  68. tooltipProps: { className: 'keyboard-tooltip' },
  69. overlayProps: { delayShow: 500 },
  70. },
  71. icon: { type: 'refresh', spin: compiling },
  72. onClick: () => startCompile(),
  73. text: compileButtonLabel,
  74. className: buttonClassName,
  75. }}
  76. dropdownToggle={{
  77. 'aria-label': t('toggle_compile_options_menu'),
  78. handleAnimationEnd: () => setAnimateCompileDropdownArrow(false),
  79. className: dropdownToggleClassName,
  80. }}
  81. dropdown={{
  82. id: 'pdf-recompile-dropdown',
  83. }}
  84. >
  85. <SplitMenu.Item header>{t('auto_compile')}</SplitMenu.Item>
  86. <SplitMenu.Item
  87. onSelect={() => sendEventAndSet(true, setAutoCompile, 'auto-compile')}
  88. >
  89. <Icon type={autoCompile ? 'check' : ''} fw />
  90. {t('on')}
  91. </SplitMenu.Item>
  92. <SplitMenu.Item
  93. onSelect={() => sendEventAndSet(false, setAutoCompile, 'auto-compile')}
  94. >
  95. <Icon type={!autoCompile ? 'check' : ''} fw />
  96. {t('off')}
  97. </SplitMenu.Item>
  98. <SplitMenu.Item header>{t('compile_mode')}</SplitMenu.Item>
  99. <SplitMenu.Item
  100. onSelect={() => sendEventAndSet(false, setDraft, 'compile-mode')}
  101. >
  102. <Icon type={!draft ? 'check' : ''} fw />
  103. {t('normal')}
  104. </SplitMenu.Item>
  105. <SplitMenu.Item
  106. onSelect={() => sendEventAndSet(true, setDraft, 'compile-mode')}
  107. >
  108. <Icon type={draft ? 'check' : ''} fw />
  109. {t('fast')} <span className="subdued">[draft]</span>
  110. </SplitMenu.Item>
  111. <SplitMenu.Item header>Syntax Checks</SplitMenu.Item>
  112. <SplitMenu.Item
  113. onSelect={() =>
  114. sendEventAndSet(true, setStopOnValidationError, 'syntax-check')
  115. }
  116. >
  117. <Icon type={stopOnValidationError ? 'check' : ''} fw />
  118. {t('stop_on_validation_error')}
  119. </SplitMenu.Item>
  120. <SplitMenu.Item
  121. onSelect={() =>
  122. sendEventAndSet(false, setStopOnValidationError, 'syntax-check')
  123. }
  124. >
  125. <Icon type={!stopOnValidationError ? 'check' : ''} fw />
  126. {t('ignore_validation_errors')}
  127. </SplitMenu.Item>
  128. <SplitMenu.Item header>{t('compile_error_handling')}</SplitMenu.Item>
  129. <SplitMenu.Item onSelect={enableStopOnFirstError}>
  130. <Icon type={stopOnFirstError ? 'check' : ''} fw />
  131. {t('stop_on_first_error')}
  132. </SplitMenu.Item>
  133. <SplitMenu.Item onSelect={disableStopOnFirstError}>
  134. <Icon type={!stopOnFirstError ? 'check' : ''} fw />
  135. {t('try_to_compile_despite_errors')}
  136. </SplitMenu.Item>
  137. <SplitMenu.Item divider />
  138. <SplitMenu.Item
  139. onSelect={() => stopCompile()}
  140. disabled={!compiling}
  141. aria-disabled={!compiling}
  142. >
  143. {t('stop_compile')}
  144. </SplitMenu.Item>
  145. <SplitMenu.Item
  146. onSelect={fromScratchWithEvent}
  147. disabled={compiling}
  148. aria-disabled={compiling}
  149. >
  150. {t('recompile_from_scratch')}
  151. </SplitMenu.Item>
  152. </SplitMenu>
  153. )
  154. }
  155. export default memo(PdfCompileButton)