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.

ApplyTemplate.tsx 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 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 { translateWithParameters, translate } from 'sonar-ui-common/helpers/l10n';
  22. import { SubmitButton, ResetButtonLink } from 'sonar-ui-common/components/controls/buttons';
  23. import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
  24. import SimpleModal from 'sonar-ui-common/components/controls/SimpleModal';
  25. import { Alert } from 'sonar-ui-common/components/ui/Alert';
  26. import Select from 'sonar-ui-common/components/controls/Select';
  27. import { getPermissionTemplates, applyTemplateToProject } from '../../../../api/permissions';
  28. interface Props {
  29. onApply?: () => void;
  30. onClose: () => void;
  31. organization: string | undefined;
  32. project: { key: string; name: string };
  33. }
  34. interface State {
  35. done: boolean;
  36. loading: boolean;
  37. permissionTemplate?: string;
  38. permissionTemplates?: T.PermissionTemplate[];
  39. }
  40. export default class ApplyTemplate extends React.PureComponent<Props, State> {
  41. mounted = false;
  42. state: State = { done: false, loading: true };
  43. componentDidMount() {
  44. this.mounted = true;
  45. this.fetchPermissionTemplates();
  46. }
  47. componentWillUnmount() {
  48. this.mounted = false;
  49. }
  50. fetchPermissionTemplates = () => {
  51. getPermissionTemplates(this.props.organization).then(
  52. ({ permissionTemplates }) => {
  53. if (this.mounted) {
  54. this.setState({ loading: false, permissionTemplates });
  55. }
  56. },
  57. () => {
  58. if (this.mounted) {
  59. this.setState({ loading: false });
  60. }
  61. }
  62. );
  63. };
  64. handleSubmit = () => {
  65. if (this.state.permissionTemplate) {
  66. return applyTemplateToProject({
  67. organization: this.props.organization,
  68. projectKey: this.props.project.key,
  69. templateId: this.state.permissionTemplate
  70. }).then(() => {
  71. if (this.mounted) {
  72. if (this.props.onApply) {
  73. this.props.onApply();
  74. }
  75. this.setState({ done: true });
  76. }
  77. });
  78. } else {
  79. return Promise.reject(undefined);
  80. }
  81. };
  82. handlePermissionTemplateChange = ({ value }: { value: string }) => {
  83. this.setState({ permissionTemplate: value });
  84. };
  85. render() {
  86. const header = translateWithParameters(
  87. 'projects_role.apply_template_to_xxx',
  88. this.props.project.name
  89. );
  90. return (
  91. <SimpleModal
  92. header={header}
  93. onClose={this.props.onClose}
  94. onSubmit={this.handleSubmit}
  95. size="small">
  96. {({ onCloseClick, onFormSubmit, submitting }) => (
  97. <form id="project-permissions-apply-template-form" onSubmit={onFormSubmit}>
  98. <header className="modal-head">
  99. <h2>{header}</h2>
  100. </header>
  101. <div className="modal-body">
  102. {this.state.done ? (
  103. <Alert variant="success">{translate('projects_role.apply_template.success')}</Alert>
  104. ) : (
  105. <>
  106. {this.state.loading ? (
  107. <i className="spinner" />
  108. ) : (
  109. <div className="modal-field">
  110. <label htmlFor="project-permissions-template">
  111. {translate('template')}
  112. <em className="mandatory">*</em>
  113. </label>
  114. {this.state.permissionTemplates && (
  115. <Select
  116. clearable={false}
  117. id="project-permissions-template"
  118. onChange={this.handlePermissionTemplateChange}
  119. options={this.state.permissionTemplates.map(permissionTemplate => ({
  120. label: permissionTemplate.name,
  121. value: permissionTemplate.id
  122. }))}
  123. value={this.state.permissionTemplate}
  124. />
  125. )}
  126. </div>
  127. )}
  128. </>
  129. )}
  130. </div>
  131. <footer className="modal-foot">
  132. <DeferredSpinner className="spacer-right" loading={submitting} />
  133. {!this.state.done && (
  134. <SubmitButton disabled={submitting || !this.state.permissionTemplate}>
  135. {translate('apply')}
  136. </SubmitButton>
  137. )}
  138. <ResetButtonLink onClick={onCloseClick}>
  139. {translate(this.state.done ? 'close' : 'cancel')}
  140. </ResetButtonLink>
  141. </footer>
  142. </form>
  143. )}
  144. </SimpleModal>
  145. );
  146. }
  147. }