]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-13102 Use radio component consistently across the application
authorPhilippe Perrin <philippe.perrin@sonarsource.com>
Mon, 20 Apr 2020 07:53:42 +0000 (09:53 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 22 Apr 2020 20:03:36 +0000 (20:03 +0000)
13 files changed:
server/sonar-web/src/main/js/app/styles/init/icons.css
server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.css
server/sonar-web/src/main/js/apps/create/project/ManualProjectCreate.tsx
server/sonar-web/src/main/js/apps/projectBaseline/components/BranchAnalysisList.tsx
server/sonar-web/src/main/js/apps/projectBaseline/components/__tests__/__snapshots__/BranchAnalysisList-test.tsx.snap
server/sonar-web/src/main/js/apps/projectsManagement/ChangeDefaultVisibilityForm.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ChangeDefaultVisibilityForm-test.tsx
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/ChangeDefaultVisibilityForm-test.tsx.snap
server/sonar-web/src/main/js/apps/tutorials/components/TokenStep.tsx
server/sonar-web/src/main/js/apps/tutorials/components/__tests__/__snapshots__/TokenStep-test.tsx.snap
server/sonar-web/src/main/js/components/common/VisibilitySelector.tsx
server/sonar-web/src/main/js/components/common/__tests__/VisibilitySelector-test.tsx
server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/VisibilitySelector-test.tsx.snap

index 7a04513fabdb60c2617174ff94c3fc1923a7266c..b20ad3d96d0947bf2806c5e096bc58bb9578cc24 100644 (file)
@@ -47,44 +47,6 @@ a[class*=' icon-'] {
   color: var(--darkBlue);
 }
 
-/*
- * Radio
- */
-.icon-radio {
-  position: relative;
-  display: inline-block;
-  vertical-align: top;
-  width: 14px;
-  height: 14px;
-  margin: 1px;
-  border: 1px solid var(--gray80);
-  border-radius: 12px;
-  box-sizing: border-box;
-  transition: border-color 0.3s ease;
-}
-
-.icon-radio:after {
-  position: absolute;
-  top: 2px;
-  left: 2px;
-  display: block;
-  width: 8px;
-  height: 8px;
-  border-radius: 8px;
-  background-color: var(--darkBlue);
-  content: '';
-  opacity: 0;
-  transition: opacity 0.3s ease;
-}
-
-a:not(.disabled):hover > .icon-radio {
-  border-color: var(--blue);
-}
-
-.icon-radio.is-checked:after {
-  opacity: 1;
-}
-
 /*
  * Common
  */
index 5e078878994880081b53433e7bef1536dcaadaf3..1cc4d2e6d3dd3647fccf8a27a428c4393f14996c 100644 (file)
   max-width: 700px;
 }
 
-.manual-project-create .visibility-select-option {
-  margin-left: 0 !important;
-  margin-bottom: var(--gridSize);
-  display: flex;
-  align-items: center;
-  font-size: var(--mediumFontSize);
-}
-
-.manual-project-create .visibility-details {
-  display: block;
-  margin: var(--gridSize) 0;
-}
-
-.manual-project-create .visibility-select-wrapper {
-  padding: var(--gridSize) 0 calc(2 * var(--gridSize)) 0;
-}
-
 .manual-project-create .button {
   margin-top: var(--gridSize);
 }
index 3d983abd485a88fa8aff8679fc0be9748433200c..b14cf5d70da08d00a9813c0c9f8f6555ff0765b2 100644 (file)
@@ -25,7 +25,6 @@ import ValidationInput from 'sonar-ui-common/components/controls/ValidationInput
 import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 import { createProject, doesComponentExists } from '../../../api/components';
-import VisibilitySelector from '../../../components/common/VisibilitySelector';
 import { isSonarCloud } from '../../../helpers/system';
 import UpgradeOrganizationBox from '../components/UpgradeOrganizationBox';
 import CreateProjectPageHeader from './CreateProjectPageHeader';
@@ -324,20 +323,6 @@ export default class ManualProjectCreate extends React.PureComponent<Props, Stat
                 />
               </ValidationInput>
 
-              {isSonarCloud() && selectedOrganization && (
-                <div
-                  className={classNames('visibility-select-wrapper', {
-                    open: Boolean(this.state.selectedOrganization)
-                  })}>
-                  <VisibilitySelector
-                    canTurnToPrivate={canChoosePrivate}
-                    onChange={this.handleVisibilityChange}
-                    showDetails={true}
-                    visibility={canChoosePrivate ? this.state.selectedVisibility : 'public'}
-                  />
-                </div>
-              )}
-
               <SubmitButton disabled={!this.canSubmit(this.state) || submitting}>
                 {translate('set_up')}
               </SubmitButton>
index f90565f4dbde8416e45271556bda4bd78f72ea6c..3d5388bdafbd5eb70744d0e5030644f375437e25 100644 (file)
@@ -21,6 +21,7 @@ import * as classNames from 'classnames';
 import { subDays } from 'date-fns';
 import { throttle } from 'lodash';
 import * as React from 'react';
+import Radio from 'sonar-ui-common/components/controls/Radio';
 import Select from 'sonar-ui-common/components/controls/Select';
 import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
 import DateFormatter from 'sonar-ui-common/components/intl/DateFormatter';
@@ -251,10 +252,10 @@ export default class BranchAnalysisList extends React.PureComponent<Props, State
                                     )}
 
                                     <div className="analysis-selection-button">
-                                      <i
-                                        className={classNames('icon-radio', {
-                                          'is-checked': analysis.key === this.props.analysis
-                                        })}
+                                      <Radio
+                                        checked={analysis.key === this.props.analysis}
+                                        onCheck={() => {}}
+                                        value=""
                                       />
                                     </div>
                                   </li>
index 46a6219e94d8b6f42c661aa58aaeae730766bba2..6bdc18ba4815eda1d62154e4653adb81609573ab 100644 (file)
@@ -76,8 +76,10 @@ exports[`should render correctly 1`] = `
                   <div
                     className="analysis-selection-button"
                   >
-                    <i
-                      className="icon-radio"
+                    <Radio
+                      checked={false}
+                      onCheck={[Function]}
+                      value=""
                     />
                   </div>
                 </li>
@@ -130,8 +132,10 @@ exports[`should render correctly 1`] = `
                   <div
                     className="analysis-selection-button"
                   >
-                    <i
-                      className="icon-radio"
+                    <Radio
+                      checked={false}
+                      onCheck={[Function]}
+                      value=""
                     />
                   </div>
                 </li>
@@ -231,8 +235,10 @@ exports[`should render correctly 1`] = `
                   <div
                     className="analysis-selection-button"
                   >
-                    <i
-                      className="icon-radio"
+                    <Radio
+                      checked={false}
+                      onCheck={[Function]}
+                      value=""
                     />
                   </div>
                 </li>
@@ -255,8 +261,10 @@ exports[`should render correctly 1`] = `
                   <div
                     className="analysis-selection-button"
                   >
-                    <i
-                      className="icon-radio"
+                    <Radio
+                      checked={false}
+                      onCheck={[Function]}
+                      value=""
                     />
                   </div>
                 </li>
index 0f495b6410d8ba42b1cf96c3fbfba6e6caf2460a..f7d4c2e89c6ac943d3637472525fdb501e2ace38 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import * as classNames from 'classnames';
 import * as React from 'react';
 import { Button, ResetButtonLink } from 'sonar-ui-common/components/controls/buttons';
 import Modal from 'sonar-ui-common/components/controls/Modal';
+import Radio from 'sonar-ui-common/components/controls/Radio';
 import { Alert } from 'sonar-ui-common/components/ui/Alert';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 
@@ -45,10 +45,7 @@ export default class ChangeDefaultVisibilityForm extends React.PureComponent<Pro
     this.props.onClose();
   };
 
-  handleVisibilityClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
-    event.preventDefault();
-    event.currentTarget.blur();
-    const visibility = event.currentTarget.dataset.visibility as T.Visibility;
+  handleVisibilityChange = (visibility: T.Visibility) => {
     this.setState({ visibility });
   };
 
@@ -63,34 +60,20 @@ export default class ChangeDefaultVisibilityForm extends React.PureComponent<Pro
         <div className="modal-body">
           {['public', 'private'].map(visibility => (
             <div className="big-spacer-bottom" key={visibility}>
-              <p>
-                {visibility === 'private' && !organization.canUpdateProjectsVisibilityToPrivate ? (
-                  <span className="text-muted cursor-not-allowed">
-                    <i
-                      className={classNames('icon-radio', 'spacer-right', {
-                        'is-checked': this.state.visibility === visibility
-                      })}
-                    />
-                    {translate('visibility', visibility)}
-                  </span>
-                ) : (
-                  <a
-                    className="link-base-color link-no-underline"
-                    data-visibility={visibility}
-                    href="#"
-                    onClick={this.handleVisibilityClick}>
-                    <i
-                      className={classNames('icon-radio', 'spacer-right', {
-                        'is-checked': this.state.visibility === visibility
-                      })}
-                    />
-                    {translate('visibility', visibility)}
-                  </a>
-                )}
-              </p>
-              <p className="text-muted spacer-top" style={{ paddingLeft: 22 }}>
-                {translate('visibility', visibility, 'description.short')}
-              </p>
+              <Radio
+                value={visibility}
+                checked={this.state.visibility === visibility}
+                onCheck={this.handleVisibilityChange}
+                disabled={
+                  visibility === 'private' && !organization.canUpdateProjectsVisibilityToPrivate
+                }>
+                <div>
+                  {translate('visibility', visibility)}
+                  <p className="text-muted spacer-top">
+                    {translate('visibility', visibility, 'description.short')}
+                  </p>
+                </div>
+              </Radio>
             </div>
           ))}
 
index f7f334cf2aa534040e30a6b7d6deeb5fb9f6cbb2..d83e82d95c4b0325214d214995f6da460d40fa65 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
+import Radio from 'sonar-ui-common/components/controls/Radio';
 import { click } from 'sonar-ui-common/helpers/testUtils';
 import ChangeDefaultVisibilityForm from '../ChangeDefaultVisibilityForm';
 
@@ -49,12 +50,11 @@ it('changes visibility', () => {
   const wrapper = shallowRender({ onConfirm });
   expect(wrapper).toMatchSnapshot();
 
-  click(wrapper.find('a[data-visibility="private"]'), {
-    currentTarget: {
-      blur() {},
-      dataset: { visibility: 'private' }
-    }
-  });
+  wrapper
+    .find(Radio)
+    .first()
+    .props()
+    .onCheck('private');
   expect(wrapper).toMatchSnapshot();
 
   click(wrapper.find('.js-confirm'));
index a80e794b95a2ee5f3da76ccab176c705e4a3f4f1..756189b1ca5a0c88e82d224c5d5501b5c5a9d8ce 100644 (file)
@@ -19,57 +19,41 @@ exports[`changes visibility 1`] = `
       className="big-spacer-bottom"
       key="public"
     >
-      <p>
-        <a
-          className="link-base-color link-no-underline"
-          data-visibility="public"
-          href="#"
-          onClick={[Function]}
-        >
-          <i
-            className="icon-radio spacer-right is-checked"
-          />
-          visibility.public
-        </a>
-      </p>
-      <p
-        className="text-muted spacer-top"
-        style={
-          Object {
-            "paddingLeft": 22,
-          }
-        }
+      <Radio
+        checked={true}
+        disabled={false}
+        onCheck={[Function]}
+        value="public"
       >
-        visibility.public.description.short
-      </p>
+        <div>
+          visibility.public
+          <p
+            className="text-muted spacer-top"
+          >
+            visibility.public.description.short
+          </p>
+        </div>
+      </Radio>
     </div>
     <div
       className="big-spacer-bottom"
       key="private"
     >
-      <p>
-        <a
-          className="link-base-color link-no-underline"
-          data-visibility="private"
-          href="#"
-          onClick={[Function]}
-        >
-          <i
-            className="icon-radio spacer-right"
-          />
-          visibility.private
-        </a>
-      </p>
-      <p
-        className="text-muted spacer-top"
-        style={
-          Object {
-            "paddingLeft": 22,
-          }
-        }
+      <Radio
+        checked={false}
+        disabled={false}
+        onCheck={[Function]}
+        value="private"
       >
-        visibility.private.description.short
-      </p>
+        <div>
+          visibility.private
+          <p
+            className="text-muted spacer-top"
+          >
+            visibility.private.description.short
+          </p>
+        </div>
+      </Radio>
     </div>
     <Alert
       variant="warning"
@@ -115,57 +99,41 @@ exports[`changes visibility 2`] = `
       className="big-spacer-bottom"
       key="public"
     >
-      <p>
-        <a
-          className="link-base-color link-no-underline"
-          data-visibility="public"
-          href="#"
-          onClick={[Function]}
-        >
-          <i
-            className="icon-radio spacer-right"
-          />
-          visibility.public
-        </a>
-      </p>
-      <p
-        className="text-muted spacer-top"
-        style={
-          Object {
-            "paddingLeft": 22,
-          }
-        }
+      <Radio
+        checked={false}
+        disabled={false}
+        onCheck={[Function]}
+        value="public"
       >
-        visibility.public.description.short
-      </p>
+        <div>
+          visibility.public
+          <p
+            className="text-muted spacer-top"
+          >
+            visibility.public.description.short
+          </p>
+        </div>
+      </Radio>
     </div>
     <div
       className="big-spacer-bottom"
       key="private"
     >
-      <p>
-        <a
-          className="link-base-color link-no-underline"
-          data-visibility="private"
-          href="#"
-          onClick={[Function]}
-        >
-          <i
-            className="icon-radio spacer-right is-checked"
-          />
-          visibility.private
-        </a>
-      </p>
-      <p
-        className="text-muted spacer-top"
-        style={
-          Object {
-            "paddingLeft": 22,
-          }
-        }
+      <Radio
+        checked={true}
+        disabled={false}
+        onCheck={[Function]}
+        value="private"
       >
-        visibility.private.description.short
-      </p>
+        <div>
+          visibility.private
+          <p
+            className="text-muted spacer-top"
+          >
+            visibility.private.description.short
+          </p>
+        </div>
+      </Radio>
     </div>
     <Alert
       variant="warning"
@@ -211,54 +179,41 @@ exports[`renders disabled 1`] = `
       className="big-spacer-bottom"
       key="public"
     >
-      <p>
-        <a
-          className="link-base-color link-no-underline"
-          data-visibility="public"
-          href="#"
-          onClick={[Function]}
-        >
-          <i
-            className="icon-radio spacer-right is-checked"
-          />
-          visibility.public
-        </a>
-      </p>
-      <p
-        className="text-muted spacer-top"
-        style={
-          Object {
-            "paddingLeft": 22,
-          }
-        }
+      <Radio
+        checked={true}
+        disabled={false}
+        onCheck={[Function]}
+        value="public"
       >
-        visibility.public.description.short
-      </p>
+        <div>
+          visibility.public
+          <p
+            className="text-muted spacer-top"
+          >
+            visibility.public.description.short
+          </p>
+        </div>
+      </Radio>
     </div>
     <div
       className="big-spacer-bottom"
       key="private"
     >
-      <p>
-        <span
-          className="text-muted cursor-not-allowed"
-        >
-          <i
-            className="icon-radio spacer-right"
-          />
-          visibility.private
-        </span>
-      </p>
-      <p
-        className="text-muted spacer-top"
-        style={
-          Object {
-            "paddingLeft": 22,
-          }
-        }
+      <Radio
+        checked={false}
+        disabled={true}
+        onCheck={[Function]}
+        value="private"
       >
-        visibility.private.description.short
-      </p>
+        <div>
+          visibility.private
+          <p
+            className="text-muted spacer-top"
+          >
+            visibility.private.description.short
+          </p>
+        </div>
+      </Radio>
     </div>
   </div>
   <footer
index 1b5c20a3b5ce78ded384f6279d08ae16571d6fba..32da736ed300e3b886fdc924671b739d4950f9b8 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import * as classNames from 'classnames';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
 import { Link } from 'react-router';
 import { Button, DeleteButton, SubmitButton } from 'sonar-ui-common/components/controls/buttons';
+import Radio from 'sonar-ui-common/components/controls/Radio';
 import AlertErrorIcon from 'sonar-ui-common/components/icons/AlertErrorIcon';
 import AlertSuccessIcon from 'sonar-ui-common/components/icons/AlertSuccessIcon';
 import { translate } from 'sonar-ui-common/helpers/l10n';
@@ -141,6 +141,10 @@ export default class TokenStep extends React.PureComponent<Props, State> {
     this.setState({ selection: 'use-existing' });
   };
 
+  handleModeChange = (mode: string) => {
+    this.setState({ selection: mode });
+  };
+
   handleExisingTokenChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     this.setState({ existingToken: event.currentTarget.value });
   };
@@ -154,17 +158,12 @@ export default class TokenStep extends React.PureComponent<Props, State> {
   renderGenerateOption = () => (
     <div>
       {this.state.tokens !== undefined && this.state.tokens.length > 0 ? (
-        <a
-          className="js-new link-base-color link-no-underline"
-          href="#"
-          onClick={this.handleGenerateClick}>
-          <i
-            className={classNames('icon-radio', 'spacer-right', {
-              'is-checked': this.state.selection === 'generate'
-            })}
-          />
+        <Radio
+          checked={this.state.selection === 'generate'}
+          onCheck={this.handleModeChange}
+          value="generate">
           {translate('onboarding.token.generate_token')}
-        </a>
+        </Radio>
       ) : (
         translate('onboarding.token.generate_token')
       )}
@@ -199,17 +198,12 @@ export default class TokenStep extends React.PureComponent<Props, State> {
 
     return (
       <div className="big-spacer-top">
-        <a
-          className="js-new link-base-color link-no-underline"
-          href="#"
-          onClick={this.handleUseExistingClick}>
-          <i
-            className={classNames('icon-radio', 'spacer-right', {
-              'is-checked': this.state.selection === 'use-existing'
-            })}
-          />
+        <Radio
+          checked={this.state.selection === 'use-existing'}
+          onCheck={this.handleModeChange}
+          value="use-existing">
           {translate('onboarding.token.use_existing_token')}
-        </a>
+        </Radio>
         {this.state.selection === 'use-existing' && (
           <div className="big-spacer-top">
             <input
index 7748869a3515073d5954ee3ad560a5900253f07a..6ad2bfc2e0c0bbbd5c1e1f847c1c0fca5506eefd 100644 (file)
@@ -24,16 +24,13 @@ exports[`generates token 1`] = `
     >
       <div>
         <div>
-          <a
-            className="js-new link-base-color link-no-underline"
-            href="#"
-            onClick={[Function]}
+          <Radio
+            checked={true}
+            onCheck={[Function]}
+            value="generate"
           >
-            <i
-              className="icon-radio spacer-right is-checked"
-            />
             onboarding.token.generate_token
-          </a>
+          </Radio>
           <div
             className="big-spacer-top"
           >
@@ -61,16 +58,13 @@ exports[`generates token 1`] = `
         <div
           className="big-spacer-top"
         >
-          <a
-            className="js-new link-base-color link-no-underline"
-            href="#"
-            onClick={[Function]}
+          <Radio
+            checked={false}
+            onCheck={[Function]}
+            value="use-existing"
           >
-            <i
-              className="icon-radio spacer-right"
-            />
             onboarding.token.use_existing_token
-          </a>
+          </Radio>
         </div>
       </div>
       <div
@@ -122,16 +116,13 @@ exports[`generates token 2`] = `
     >
       <div>
         <div>
-          <a
-            className="js-new link-base-color link-no-underline"
-            href="#"
-            onClick={[Function]}
+          <Radio
+            checked={true}
+            onCheck={[Function]}
+            value="generate"
           >
-            <i
-              className="icon-radio spacer-right is-checked"
-            />
             onboarding.token.generate_token
-          </a>
+          </Radio>
           <div
             className="big-spacer-top"
           >
@@ -156,16 +147,13 @@ exports[`generates token 2`] = `
         <div
           className="big-spacer-top"
         >
-          <a
-            className="js-new link-base-color link-no-underline"
-            href="#"
-            onClick={[Function]}
+          <Radio
+            checked={false}
+            onCheck={[Function]}
+            value="use-existing"
           >
-            <i
-              className="icon-radio spacer-right"
-            />
             onboarding.token.use_existing_token
-          </a>
+          </Radio>
         </div>
       </div>
       <div
@@ -444,16 +432,13 @@ exports[`revokes token 3`] = `
     >
       <div>
         <div>
-          <a
-            className="js-new link-base-color link-no-underline"
-            href="#"
-            onClick={[Function]}
+          <Radio
+            checked={true}
+            onCheck={[Function]}
+            value="generate"
           >
-            <i
-              className="icon-radio spacer-right is-checked"
-            />
             onboarding.token.generate_token
-          </a>
+          </Radio>
           <div
             className="big-spacer-top"
           >
@@ -481,16 +466,13 @@ exports[`revokes token 3`] = `
         <div
           className="big-spacer-top"
         >
-          <a
-            className="js-new link-base-color link-no-underline"
-            href="#"
-            onClick={[Function]}
+          <Radio
+            checked={false}
+            onCheck={[Function]}
+            value="use-existing"
           >
-            <i
-              className="icon-radio spacer-right"
-            />
             onboarding.token.use_existing_token
-          </a>
+          </Radio>
         </div>
       </div>
       <div
index d9e6457f08163f84bc6c59da7f3721cda49b2e18..d33c12aba33ec6a0e66a76d66d84523ed547c1cf 100644 (file)
@@ -19,6 +19,7 @@
  */
 import * as classNames from 'classnames';
 import * as React from 'react';
+import Radio from 'sonar-ui-common/components/controls/Radio';
 import { translate } from 'sonar-ui-common/helpers/l10n';
 
 interface Props {
@@ -30,78 +31,25 @@ interface Props {
 }
 
 export default class VisibilitySelector extends React.PureComponent<Props> {
-  handlePublicClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
-    event.preventDefault();
-    event.currentTarget.blur();
-    this.props.onChange('public');
-  };
-
-  handlePrivateClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
-    event.preventDefault();
-    event.currentTarget.blur();
-    this.props.onChange('private');
-  };
-
   render() {
     return (
-      <div className={classNames('visibility-select', this.props.className)}>
-        <a
-          className="link-base-color link-no-underline visibility-select-option"
-          href="#"
-          id="visibility-public"
-          onClick={this.handlePublicClick}>
-          <i
-            className={classNames('icon-radio', {
-              'is-checked': this.props.visibility === 'public'
-            })}
-          />
-          <span className="spacer-left">{translate('visibility.public')}</span>
-        </a>
-        {this.props.showDetails && (
-          <span className="visibility-details note">
-            {translate('visibility.public.description.long')}
-          </span>
-        )}
-
-        {this.props.canTurnToPrivate ? (
-          <>
-            <a
-              className="link-base-color link-no-underline huge-spacer-left visibility-select-option"
-              href="#"
-              id="visibility-private"
-              onClick={this.handlePrivateClick}>
-              <i
-                className={classNames('icon-radio', {
-                  'is-checked': this.props.visibility === 'private'
-                })}
-              />
-              <span className="spacer-left">{translate('visibility.private')}</span>
-            </a>
-            {this.props.showDetails && (
-              <span className="visibility-details note">
-                {translate('visibility.private.description.long')}
-              </span>
-            )}
-          </>
-        ) : (
-          <>
-            <span
-              className="huge-spacer-left text-muted cursor-not-allowed visibility-select-option"
-              id="visibility-private">
-              <i
-                className={classNames('icon-radio', {
-                  'is-checked': this.props.visibility === 'private'
-                })}
-              />
-              <span className="spacer-left">{translate('visibility.private')}</span>
-            </span>
-            {this.props.showDetails && (
-              <span className="visibility-details note">
-                {translate('visibility.private.description.long')}
-              </span>
-            )}
-          </>
-        )}
+      <div className={classNames(this.props.className)}>
+        {['public', 'private'].map(visibility => (
+          <Radio
+            className={`huge-spacer-right visibility-${visibility}`}
+            key={visibility}
+            value={visibility}
+            checked={this.props.visibility === visibility}
+            onCheck={this.props.onChange}
+            disabled={visibility === 'private' && !this.props.canTurnToPrivate}>
+            <div>
+              {translate('visibility', visibility)}
+              {this.props.showDetails && (
+                <p className="note">{translate('visibility', visibility, 'description.long')}</p>
+              )}
+            </div>
+          </Radio>
+        ))}
       </div>
     );
   }
index 99a77e37ff7d163992078f3dc05b38f344531ff6..e42338a66affe312f8e0b38a1e708161a54a2529 100644 (file)
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
-import { click } from 'sonar-ui-common/helpers/testUtils';
+import Radio from 'sonar-ui-common/components/controls/Radio';
 import VisibilitySelector from '../VisibilitySelector';
 
 it('changes visibility', () => {
   const onChange = jest.fn();
-  const wrapper = shallow(
-    <VisibilitySelector canTurnToPrivate={true} onChange={onChange} visibility="public" />
-  );
+  const wrapper = shallowRender({ onChange });
   expect(wrapper).toMatchSnapshot();
 
-  click(wrapper.find('#visibility-private'));
+  wrapper
+    .find(Radio)
+    .first()
+    .props()
+    .onCheck('private');
   expect(onChange).toBeCalledWith('private');
 
   wrapper.setProps({ visibility: 'private' });
   expect(wrapper).toMatchSnapshot();
 
-  click(wrapper.find('#visibility-public'));
+  wrapper
+    .find(Radio)
+    .first()
+    .props()
+    .onCheck('public');
   expect(onChange).toBeCalledWith('public');
 });
 
 it('renders disabled', () => {
-  expect(
-    shallow(
-      <VisibilitySelector canTurnToPrivate={false} onChange={jest.fn()} visibility="public" />
-    )
-  ).toMatchSnapshot();
+  expect(shallowRender({ canTurnToPrivate: false })).toMatchSnapshot();
 });
+
+function shallowRender(props?: Partial<VisibilitySelector['props']>) {
+  return shallow<VisibilitySelector>(
+    <VisibilitySelector
+      className="test-classname"
+      canTurnToPrivate={true}
+      onChange={jest.fn()}
+      visibility="public"
+      {...props}
+    />
+  );
+}
index 98a9be4035cf93fff375b3088cbef8bec05e1ba0..4ee16f1a218647a7e032fbc5d9316450f8b072e5 100644 (file)
 
 exports[`changes visibility 1`] = `
 <div
-  className="visibility-select"
+  className="test-classname"
 >
-  <a
-    className="link-base-color link-no-underline visibility-select-option"
-    href="#"
-    id="visibility-public"
-    onClick={[Function]}
+  <Radio
+    checked={true}
+    className="huge-spacer-right visibility-public"
+    disabled={false}
+    key="public"
+    onCheck={[MockFunction]}
+    value="public"
   >
-    <i
-      className="icon-radio is-checked"
-    />
-    <span
-      className="spacer-left"
-    >
+    <div>
       visibility.public
-    </span>
-  </a>
-  <a
-    className="link-base-color link-no-underline huge-spacer-left visibility-select-option"
-    href="#"
-    id="visibility-private"
-    onClick={[Function]}
+    </div>
+  </Radio>
+  <Radio
+    checked={false}
+    className="huge-spacer-right visibility-private"
+    disabled={false}
+    key="private"
+    onCheck={[MockFunction]}
+    value="private"
   >
-    <i
-      className="icon-radio"
-    />
-    <span
-      className="spacer-left"
-    >
+    <div>
       visibility.private
-    </span>
-  </a>
+    </div>
+  </Radio>
 </div>
 `;
 
 exports[`changes visibility 2`] = `
 <div
-  className="visibility-select"
+  className="test-classname"
 >
-  <a
-    className="link-base-color link-no-underline visibility-select-option"
-    href="#"
-    id="visibility-public"
-    onClick={[Function]}
+  <Radio
+    checked={false}
+    className="huge-spacer-right visibility-public"
+    disabled={false}
+    key="public"
+    onCheck={
+      [MockFunction] {
+        "calls": Array [
+          Array [
+            "private",
+          ],
+        ],
+        "results": Array [
+          Object {
+            "type": "return",
+            "value": undefined,
+          },
+        ],
+      }
+    }
+    value="public"
   >
-    <i
-      className="icon-radio"
-    />
-    <span
-      className="spacer-left"
-    >
+    <div>
       visibility.public
-    </span>
-  </a>
-  <a
-    className="link-base-color link-no-underline huge-spacer-left visibility-select-option"
-    href="#"
-    id="visibility-private"
-    onClick={[Function]}
+    </div>
+  </Radio>
+  <Radio
+    checked={true}
+    className="huge-spacer-right visibility-private"
+    disabled={false}
+    key="private"
+    onCheck={
+      [MockFunction] {
+        "calls": Array [
+          Array [
+            "private",
+          ],
+        ],
+        "results": Array [
+          Object {
+            "type": "return",
+            "value": undefined,
+          },
+        ],
+      }
+    }
+    value="private"
   >
-    <i
-      className="icon-radio is-checked"
-    />
-    <span
-      className="spacer-left"
-    >
+    <div>
       visibility.private
-    </span>
-  </a>
+    </div>
+  </Radio>
 </div>
 `;
 
 exports[`renders disabled 1`] = `
 <div
-  className="visibility-select"
+  className="test-classname"
 >
-  <a
-    className="link-base-color link-no-underline visibility-select-option"
-    href="#"
-    id="visibility-public"
-    onClick={[Function]}
+  <Radio
+    checked={true}
+    className="huge-spacer-right visibility-public"
+    disabled={false}
+    key="public"
+    onCheck={[MockFunction]}
+    value="public"
   >
-    <i
-      className="icon-radio is-checked"
-    />
-    <span
-      className="spacer-left"
-    >
+    <div>
       visibility.public
-    </span>
-  </a>
-  <span
-    className="huge-spacer-left text-muted cursor-not-allowed visibility-select-option"
-    id="visibility-private"
+    </div>
+  </Radio>
+  <Radio
+    checked={false}
+    className="huge-spacer-right visibility-private"
+    disabled={true}
+    key="private"
+    onCheck={[MockFunction]}
+    value="private"
   >
-    <i
-      className="icon-radio"
-    />
-    <span
-      className="spacer-left"
-    >
+    <div>
       visibility.private
-    </span>
-  </span>
+    </div>
+  </Radio>
 </div>
 `;