help-panel.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import React from 'react';
  2. import { connect } from 'react-redux';
  3. import { searchableFieldsSelector } from '../selectors/search';
  4. import { canvasMarginsSelector } from '../selectors/canvas';
  5. import { hideHelp } from '../actions/app-actions';
  6. const GENERAL_SHORTCUTS = [
  7. { key: 'esc', label: 'Close active panel' },
  8. { key: '/', label: 'Activate search field' },
  9. { key: '?', label: 'Toggle shortcut menu' },
  10. { key: 'g', label: 'Switch to Graph view' },
  11. { key: 't', label: 'Switch to Table view' },
  12. { key: 'r', label: 'Switch to Resources view' },
  13. ];
  14. const CANVAS_METRIC_SHORTCUTS = [
  15. { key: '<', label: 'Select and pin previous metric' },
  16. { key: '>', label: 'Select and pin next metric' },
  17. { key: 'q', label: 'Unpin current metric' },
  18. ];
  19. function renderShortcuts(cuts) {
  20. return (
  21. <div>
  22. {cuts.map(({ key, label }) => (
  23. <div key={key} className="help-panel-shortcuts-shortcut">
  24. <div className="key"><kbd>{key}</kbd></div>
  25. <div className="label">{label}</div>
  26. </div>
  27. ))}
  28. </div>
  29. );
  30. }
  31. function renderShortcutPanel() {
  32. return (
  33. <div className="help-panel-shortcuts">
  34. <h2>Shortcuts</h2>
  35. <h3>General</h3>
  36. {renderShortcuts(GENERAL_SHORTCUTS)}
  37. <h3>Canvas Metrics</h3>
  38. {renderShortcuts(CANVAS_METRIC_SHORTCUTS)}
  39. </div>
  40. );
  41. }
  42. const BASIC_SEARCHES = [
  43. { label: 'All fields for foo', term: 'foo' },
  44. {
  45. label: (
  46. <span>
  47. Any field matching
  48. <b>pid</b>
  49. {' '}
  50. for the value 12345
  51. </span>
  52. ),
  53. term: 'pid: 12345'
  54. },
  55. ];
  56. const REGEX_SEARCHES = [
  57. {
  58. label: 'All fields for foo or bar',
  59. term: 'foo|bar'
  60. },
  61. {
  62. label: (
  63. <span>
  64. <b>command</b>
  65. {' '}
  66. field for foobar or foobaz
  67. </span>
  68. ),
  69. term: 'command: foo(bar|baz)'
  70. },
  71. ];
  72. const METRIC_SEARCHES = [
  73. {
  74. label: (
  75. <span>
  76. <b>CPU</b>
  77. {' '}
  78. greater than 4%
  79. </span>
  80. ),
  81. term: 'cpu > 4%'
  82. },
  83. {
  84. label: (
  85. <span>
  86. <b>Memory</b>
  87. {' '}
  88. less than 10 megabytes
  89. </span>
  90. ),
  91. term: 'memory < 10mb'
  92. },
  93. ];
  94. function renderSearches(searches) {
  95. return (
  96. <div>
  97. {searches.map(({ term, label }) => (
  98. <div key={term} className="help-panel-search-row">
  99. <div className="help-panel-search-row-term">
  100. <i className="fa fa-search search-label-icon" />
  101. {term}
  102. </div>
  103. <div className="help-panel-search-row-term-label">{label}</div>
  104. </div>
  105. ))}
  106. </div>
  107. );
  108. }
  109. function renderSearchPanel() {
  110. return (
  111. <div className="help-panel-search">
  112. <h2>Search</h2>
  113. <h3>Basics</h3>
  114. {renderSearches(BASIC_SEARCHES)}
  115. <h3>Regular expressions</h3>
  116. {renderSearches(REGEX_SEARCHES)}
  117. <h3>Metrics</h3>
  118. {renderSearches(METRIC_SEARCHES)}
  119. </div>
  120. );
  121. }
  122. function renderFieldsPanel(currentTopologyName, searchableFields) {
  123. const none = (
  124. <span style={{ fontStyle: 'italic' }}>None</span>
  125. );
  126. const currentTopology = (
  127. <span className="help-panel-fields-current-topology">
  128. {currentTopologyName}
  129. </span>
  130. );
  131. return (
  132. <div className="help-panel-fields">
  133. <h2>Fields and Metrics</h2>
  134. <p>
  135. Searchable fields and metrics in the
  136. {' '}
  137. <br />
  138. currently selected
  139. {' '}
  140. {currentTopology}
  141. {' '}
  142. topology:
  143. </p>
  144. <div className="help-panel-fields-fields">
  145. <div className="help-panel-fields-fields-column">
  146. <h3>Fields</h3>
  147. <div className="help-panel-fields-fields-column-content">
  148. {searchableFields.get('fields').map(f => (
  149. <div key={f}>{f}</div>
  150. ))}
  151. {searchableFields.get('fields').size === 0 && none}
  152. </div>
  153. </div>
  154. <div className="help-panel-fields-fields-column">
  155. <h3>Metrics</h3>
  156. <div className="help-panel-fields-fields-column-content">
  157. {searchableFields.get('metrics').map(m => (
  158. <div key={m}>{m}</div>
  159. ))}
  160. {searchableFields.get('metrics').size === 0 && none}
  161. </div>
  162. </div>
  163. </div>
  164. </div>
  165. );
  166. }
  167. function HelpPanel({
  168. currentTopologyName, searchableFields, onClickClose, canvasMargins
  169. }) {
  170. return (
  171. <div className="help-panel-wrapper">
  172. <div className="help-panel" style={{ marginTop: canvasMargins.top }}>
  173. <div className="help-panel-header">
  174. <h2>Help</h2>
  175. </div>
  176. <div className="help-panel-main">
  177. {renderShortcutPanel()}
  178. {renderSearchPanel()}
  179. {renderFieldsPanel(currentTopologyName, searchableFields)}
  180. </div>
  181. <div className="help-panel-tools">
  182. <i
  183. title="Close details"
  184. className="fa fa-times"
  185. onClick={onClickClose}
  186. />
  187. </div>
  188. </div>
  189. </div>
  190. );
  191. }
  192. function mapStateToProps(state) {
  193. return {
  194. canvasMargins: canvasMarginsSelector(state),
  195. currentTopologyName: state.getIn(['currentTopology', 'fullName']),
  196. searchableFields: searchableFieldsSelector(state)
  197. };
  198. }
  199. export default connect(mapStateToProps, {
  200. onClickClose: hideHelp
  201. })(HelpPanel);