AppConfigWrapper.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Libraries
  2. import React, { PureComponent } from 'react';
  3. import cloneDeep from 'lodash/cloneDeep';
  4. import extend from 'lodash/extend';
  5. import { PluginMeta, AppPlugin, Button } from '@grafana/ui';
  6. import { AngularComponent, getAngularLoader } from '@grafana/runtime';
  7. import { getBackendSrv } from 'app/core/services/backend_srv';
  8. import { css } from 'emotion';
  9. interface Props {
  10. app: AppPlugin;
  11. }
  12. interface State {
  13. angularCtrl: AngularComponent;
  14. refresh: number;
  15. }
  16. export class AppConfigCtrlWrapper extends PureComponent<Props, State> {
  17. element: HTMLElement; // for angular ctrl
  18. // Needed for angular scope
  19. preUpdateHook = () => Promise.resolve();
  20. postUpdateHook = () => Promise.resolve();
  21. model: PluginMeta;
  22. constructor(props: Props) {
  23. super(props);
  24. this.state = {
  25. angularCtrl: null,
  26. refresh: 0,
  27. };
  28. }
  29. componentDidMount() {
  30. // Force a reload after the first mount -- is there a better way to do this?
  31. setTimeout(() => {
  32. this.setState({ refresh: this.state.refresh + 1 });
  33. }, 5);
  34. }
  35. componentDidUpdate(prevProps: Props) {
  36. if (!this.element || this.state.angularCtrl) {
  37. return;
  38. }
  39. // Set a copy of the meta
  40. this.model = cloneDeep(this.props.app.meta);
  41. const loader = getAngularLoader();
  42. const template = '<plugin-component type="app-config-ctrl"></plugin-component>';
  43. const scopeProps = { ctrl: this };
  44. const angularCtrl = loader.load(this.element, scopeProps, template);
  45. this.setState({ angularCtrl });
  46. }
  47. render() {
  48. const model = this.model;
  49. const withRightMargin = css({ marginRight: '8px' });
  50. return (
  51. <div>
  52. <div ref={element => (this.element = element)} />
  53. <br />
  54. <br />
  55. {model && (
  56. <div className="gf-form">
  57. {!model.enabled && (
  58. <Button variant="primary" onClick={this.enable} className={withRightMargin}>
  59. Enable
  60. </Button>
  61. )}
  62. {model.enabled && (
  63. <Button variant="primary" onClick={this.update} className={withRightMargin}>
  64. Update
  65. </Button>
  66. )}
  67. {model.enabled && (
  68. <Button variant="danger" onClick={this.disable} className={withRightMargin}>
  69. Disable
  70. </Button>
  71. )}
  72. </div>
  73. )}
  74. </div>
  75. );
  76. }
  77. //-----------------------------------------------------------
  78. // Copied from plugin_edit_ctrl
  79. //-----------------------------------------------------------
  80. update = () => {
  81. const pluginId = this.model.id;
  82. this.preUpdateHook()
  83. .then(() => {
  84. const updateCmd = extend(
  85. {
  86. enabled: this.model.enabled,
  87. pinned: this.model.pinned,
  88. jsonData: this.model.jsonData,
  89. secureJsonData: this.model.secureJsonData,
  90. },
  91. {}
  92. );
  93. return getBackendSrv().post(`/api/plugins/${pluginId}/settings`, updateCmd);
  94. })
  95. .then(this.postUpdateHook)
  96. .then(res => {
  97. window.location.href = window.location.href;
  98. });
  99. };
  100. setPreUpdateHook = (callback: () => any) => {
  101. this.preUpdateHook = callback;
  102. };
  103. setPostUpdateHook = (callback: () => any) => {
  104. this.postUpdateHook = callback;
  105. };
  106. enable = () => {
  107. this.model.enabled = true;
  108. this.model.pinned = true;
  109. this.update();
  110. };
  111. disable = () => {
  112. this.model.enabled = false;
  113. this.model.pinned = false;
  114. this.update();
  115. };
  116. }