You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

App.tsx 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. import * as React from 'react';
  21. import { Helmet } from 'react-helmet-async';
  22. import { createWebhook, deleteWebhook, searchWebhooks, updateWebhook } from '../../../api/webhooks';
  23. import withComponentContext from '../../../app/components/componentContext/withComponentContext';
  24. import Suggestions from '../../../components/embed-docs-modal/Suggestions';
  25. import { translate } from '../../../helpers/l10n';
  26. import { Component } from '../../../types/types';
  27. import { WebhookResponse } from '../../../types/webhook';
  28. import PageActions from './PageActions';
  29. import PageHeader from './PageHeader';
  30. import WebhooksList from './WebhooksList';
  31. interface Props {
  32. // eslint-disable-next-line react/no-unused-prop-types
  33. component?: Component;
  34. }
  35. interface State {
  36. loading: boolean;
  37. webhooks: WebhookResponse[];
  38. }
  39. export class App extends React.PureComponent<Props, State> {
  40. mounted = false;
  41. state: State = { loading: true, webhooks: [] };
  42. componentDidMount() {
  43. this.mounted = true;
  44. this.fetchWebhooks();
  45. }
  46. componentWillUnmount() {
  47. this.mounted = false;
  48. }
  49. fetchWebhooks = () => {
  50. return searchWebhooks(this.getScopeParams()).then(
  51. ({ webhooks }) => {
  52. if (this.mounted) {
  53. this.setState({ loading: false, webhooks });
  54. }
  55. },
  56. () => {
  57. if (this.mounted) {
  58. this.setState({ loading: false });
  59. }
  60. }
  61. );
  62. };
  63. getScopeParams = ({ component } = this.props) => {
  64. return {
  65. project: component && component.key,
  66. };
  67. };
  68. handleCreate = (data: { name: string; secret?: string; url: string }) => {
  69. const createData = {
  70. name: data.name,
  71. url: data.url,
  72. ...(data.secret && { secret: data.secret }),
  73. ...this.getScopeParams(),
  74. };
  75. return createWebhook(createData).then(({ webhook }) => {
  76. if (this.mounted) {
  77. this.setState(({ webhooks }) => ({ webhooks: [...webhooks, webhook] }));
  78. }
  79. });
  80. };
  81. handleDelete = (webhook: string) => {
  82. return deleteWebhook({ webhook }).then(() => {
  83. if (this.mounted) {
  84. this.setState(({ webhooks }) => ({
  85. webhooks: webhooks.filter((item) => item.key !== webhook),
  86. }));
  87. }
  88. });
  89. };
  90. handleUpdate = (data: { webhook: string; name: string; secret?: string; url: string }) => {
  91. const updateData = {
  92. webhook: data.webhook,
  93. name: data.name,
  94. url: data.url,
  95. secret: data.secret,
  96. };
  97. return updateWebhook(updateData).then(() => {
  98. if (this.mounted) {
  99. this.setState(({ webhooks }) => ({
  100. webhooks: webhooks.map((webhook) =>
  101. webhook.key === data.webhook
  102. ? {
  103. ...webhook,
  104. name: data.name,
  105. hasSecret: data.secret === undefined ? webhook.hasSecret : Boolean(data.secret),
  106. url: data.url,
  107. }
  108. : webhook
  109. ),
  110. }));
  111. }
  112. });
  113. };
  114. render() {
  115. const { loading, webhooks } = this.state;
  116. return (
  117. <>
  118. <Suggestions suggestions="webhooks" />
  119. <Helmet defer={false} title={translate('webhooks.page')} />
  120. <div className="page page-limited">
  121. <PageHeader loading={loading}>
  122. <PageActions
  123. loading={loading}
  124. onCreate={this.handleCreate}
  125. webhooksCount={webhooks.length}
  126. />
  127. </PageHeader>
  128. {!loading && (
  129. <div className="boxed-group boxed-group-inner">
  130. <WebhooksList
  131. onDelete={this.handleDelete}
  132. onUpdate={this.handleUpdate}
  133. webhooks={webhooks}
  134. />
  135. </div>
  136. )}
  137. </div>
  138. </>
  139. );
  140. }
  141. }
  142. export default withComponentContext(App);