AddPanelPanel.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import React from 'react';
  2. import _ from 'lodash';
  3. import config from 'app/core/config';
  4. import { PanelModel } from '../panel_model';
  5. import { PanelContainer } from './PanelContainer';
  6. import ScrollBar from 'app/core/components/ScrollBar/ScrollBar';
  7. import store from 'app/core/store';
  8. import { LS_PANEL_COPY_KEY } from 'app/core/constants';
  9. import Highlighter from 'react-highlight-words';
  10. export interface AddPanelPanelProps {
  11. panel: PanelModel;
  12. getPanelContainer: () => PanelContainer;
  13. }
  14. export interface AddPanelPanelState {
  15. filter: string;
  16. panelPlugins: any[];
  17. copiedPanelPlugins: any[];
  18. tab: string;
  19. }
  20. export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelPanelState> {
  21. constructor(props) {
  22. super(props);
  23. this.handleCloseAddPanel = this.handleCloseAddPanel.bind(this);
  24. this.renderPanelItem = this.renderPanelItem.bind(this);
  25. this.state = {
  26. panelPlugins: this.getPanelPlugins(''),
  27. copiedPanelPlugins: this.getCopiedPanelPlugins(''),
  28. filter: '',
  29. tab: 'Add',
  30. };
  31. }
  32. getPanelPlugins(filter) {
  33. let panels = _.chain(config.panels)
  34. .filter({ hideFromList: false })
  35. .map(item => item)
  36. .value();
  37. // add special row type
  38. panels.push({ id: 'row', name: 'Row', sort: 8, info: { logos: { small: 'public/img/icn-row.svg' } } });
  39. panels = this.filterPanels(panels, filter);
  40. // add sort by sort property
  41. return _.sortBy(panels, 'sort');
  42. }
  43. getCopiedPanelPlugins(filter) {
  44. let panels = _.chain(config.panels)
  45. .filter({ hideFromList: false })
  46. .map(item => item)
  47. .value();
  48. let copiedPanels = [];
  49. let copiedPanelJson = store.get(LS_PANEL_COPY_KEY);
  50. if (copiedPanelJson) {
  51. let copiedPanel = JSON.parse(copiedPanelJson);
  52. let pluginInfo = _.find(panels, { id: copiedPanel.type });
  53. if (pluginInfo) {
  54. let pluginCopy = _.cloneDeep(pluginInfo);
  55. pluginCopy.name = copiedPanel.title;
  56. pluginCopy.sort = -1;
  57. pluginCopy.defaults = copiedPanel;
  58. copiedPanels.push(pluginCopy);
  59. }
  60. }
  61. copiedPanels = this.filterPanels(copiedPanels, filter);
  62. return _.sortBy(copiedPanels, 'sort');
  63. }
  64. onAddPanel = panelPluginInfo => {
  65. const panelContainer = this.props.getPanelContainer();
  66. const dashboard = panelContainer.getDashboard();
  67. const { gridPos } = this.props.panel;
  68. var newPanel: any = {
  69. type: panelPluginInfo.id,
  70. title: 'Panel Title',
  71. gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
  72. };
  73. if (panelPluginInfo.id === 'row') {
  74. newPanel.title = 'Row title';
  75. newPanel.gridPos = { x: 0, y: 0 };
  76. }
  77. // apply panel template / defaults
  78. if (panelPluginInfo.defaults) {
  79. _.defaults(newPanel, panelPluginInfo.defaults);
  80. newPanel.gridPos.w = panelPluginInfo.defaults.gridPos.w;
  81. newPanel.gridPos.h = panelPluginInfo.defaults.gridPos.h;
  82. newPanel.title = panelPluginInfo.defaults.title;
  83. store.delete(LS_PANEL_COPY_KEY);
  84. }
  85. dashboard.addPanel(newPanel);
  86. dashboard.removePanel(this.props.panel);
  87. };
  88. handleCloseAddPanel(evt) {
  89. evt.preventDefault();
  90. const panelContainer = this.props.getPanelContainer();
  91. const dashboard = panelContainer.getDashboard();
  92. dashboard.removePanel(dashboard.panels[0]);
  93. }
  94. renderText(text: string) {
  95. let searchWords = this.state.filter.split('');
  96. return <Highlighter highlightClassName="highlight-search-match" textToHighlight={text} searchWords={searchWords} />;
  97. }
  98. renderPanelItem(panel, index) {
  99. return (
  100. <div key={index} className="add-panel__item" onClick={() => this.onAddPanel(panel)} title={panel.name}>
  101. <img className="add-panel__item-img" src={panel.info.logos.small} />
  102. <div className="add-panel__item-name">{this.renderText(panel.name)}</div>
  103. </div>
  104. );
  105. }
  106. noCopiedPanelPlugins() {
  107. return <div className="add-panel__no-panels">No copied panels yet.</div>;
  108. }
  109. filterChange(evt) {
  110. this.setState({
  111. filter: evt.target.value,
  112. panelPlugins: this.getPanelPlugins(evt.target.value),
  113. copiedPanelPlugins: this.getCopiedPanelPlugins(evt.target.value),
  114. });
  115. }
  116. filterPanels(panels, filter) {
  117. let regex = new RegExp(filter, 'i');
  118. return panels.filter(panel => {
  119. return regex.test(panel.name);
  120. });
  121. }
  122. openCopy() {
  123. this.setState({
  124. tab: 'Copy',
  125. filter: '',
  126. panelPlugins: this.getPanelPlugins(''),
  127. copiedPanelPlugins: this.getCopiedPanelPlugins(''),
  128. });
  129. }
  130. openAdd() {
  131. this.setState({
  132. tab: 'Add',
  133. filter: '',
  134. panelPlugins: this.getPanelPlugins(''),
  135. copiedPanelPlugins: this.getCopiedPanelPlugins(''),
  136. });
  137. }
  138. render() {
  139. let addClass;
  140. let copyClass;
  141. let panelTab;
  142. if (this.state.tab === 'Add') {
  143. addClass = 'active active--panel';
  144. copyClass = '';
  145. panelTab = this.state.panelPlugins.map(this.renderPanelItem);
  146. } else if (this.state.tab === 'Copy') {
  147. addClass = '';
  148. copyClass = 'active active--panel';
  149. console.log(this.state.copiedPanelPlugins);
  150. if (this.state.copiedPanelPlugins.length > 0) {
  151. panelTab = this.state.copiedPanelPlugins.map(this.renderPanelItem);
  152. } else {
  153. panelTab = this.noCopiedPanelPlugins();
  154. }
  155. }
  156. return (
  157. <div className="panel-container">
  158. <div className="add-panel">
  159. <div className="add-panel__header">
  160. <i className="gicon gicon-add-panel" />
  161. <span className="add-panel__title">New Panel</span>
  162. <ul className="gf-tabs">
  163. <li className="gf-tabs-item">
  164. <div className={'gf-tabs-link pointer ' + addClass} onClick={this.openAdd.bind(this)}>
  165. Add
  166. </div>
  167. </li>
  168. <li className="gf-tabs-item">
  169. <div className={'gf-tabs-link pointer ' + copyClass} onClick={this.openCopy.bind(this)}>
  170. Paste
  171. </div>
  172. </li>
  173. </ul>
  174. <button className="add-panel__close" onClick={this.handleCloseAddPanel}>
  175. <i className="fa fa-close" />
  176. </button>
  177. </div>
  178. <ScrollBar className="add-panel__items">
  179. <div className="add-panel__searchbar">
  180. <label className="gf-form gf-form--grow gf-form--has-input-icon">
  181. <input
  182. type="text"
  183. className="gf-form-input max-width-20"
  184. placeholder="Panel Search Filter"
  185. value={this.state.filter}
  186. onChange={this.filterChange.bind(this)}
  187. />
  188. <i className="gf-form-input-icon fa fa-search" />
  189. </label>
  190. </div>
  191. {panelTab}
  192. </ScrollBar>
  193. </div>
  194. </div>
  195. );
  196. }
  197. }