]> source.dussan.org Git - sonarqube.git/commitdiff
Merge remote-tracking branch 'origin/branch-6.7'
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 3 Nov 2017 12:54:44 +0000 (13:54 +0100)
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 3 Nov 2017 12:54:44 +0000 (13:54 +0100)
17 files changed:
1  2 
server/sonar-web/src/main/js/app/components/nav/settings/SettingsEditionsNotif.tsx
server/sonar-web/src/main/js/app/components/nav/settings/__tests__/SettingsEditionsNotif-test.tsx
server/sonar-web/src/main/js/app/styles/init/misc.css
server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx
server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx
server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx
server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionSet.tsx
server/sonar-web/src/main/js/apps/marketplace/components/PluginAvailable.tsx
server/sonar-web/src/main/js/apps/marketplace/components/UninstallEditionForm.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionSet-test.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/UninstallEditionForm-test.tsx
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/UninstallEditionForm-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 2c4cebc6a29da0ffcef4e534fb0139c30594ff13,d2e8548ff72b63400d8d9150e321a135a0254aad..9df1a73d51b27a218586ab72a742bafc336e1d3e
@@@ -46,18 -47,57 +47,53 @@@ export default class SettingsEditionsNo
        () => {}
      );
  
 -          {edition ? (
 -            translateWithParameters(
 -              'marketplace.status_x.' + editionStatus.installationStatus,
 -              edition.name
 -            )
 -          ) : (
 -            translate('marketplace.status', editionStatus.installationStatus)
 -          )}
+   renderStatusMsg(edition?: Edition) {
+     const { editionStatus } = this.props;
+     return (
+       <NavBarNotif className="alert alert-info">
+         <i className="spinner spacer-right text-bottom" />
+         <span>
++          {edition
++            ? translateWithParameters(
++                'marketplace.status_x.' + editionStatus.installationStatus,
++                edition.name
++              )
++            : translate('marketplace.status', editionStatus.installationStatus)}
+         </span>
+       </NavBarNotif>
+     );
+   }
    renderRestartMsg(edition?: Edition) {
      const { editionStatus, preventRestart } = this.props;
      return (
        <NavBarNotif className="alert alert-success">
          <span>
 -          {edition ? (
 -            translateWithParameters(
 -              'marketplace.status_x.' + editionStatus.installationStatus,
 -              edition.name
 -            )
 -          ) : (
 -            translate('marketplace.status', editionStatus.installationStatus)
 -          )}
 +          {edition
 +            ? translateWithParameters(
 +                'marketplace.status_x.' + editionStatus.installationStatus,
 +                edition.name
 +              )
 +            : translate('marketplace.status', editionStatus.installationStatus)}
          </span>
 -        edition.key === 'datacenter' && (
 -          <span className="little-spacer-left">
 -            <FormattedMessage
 -              defaultMessage={translate('marketplace.see_documentation_to_enable_cluster')}
 -              id="marketplace.see_documentation_to_enable_cluster"
 -              values={{
 -                url: (
 -                  <a
 -                    href="https://redirect.sonarsource.com/doc/data-center-edition.html"
 -                    target="_blank">
 -                    {edition.name}
 -                  </a>
 -                )
 -              }}
 -            />
 -          </span>
 -        )}
+         {edition &&
++          edition.key === 'datacenter' && (
++            <span className="little-spacer-left">
++              <FormattedMessage
++                defaultMessage={translate('marketplace.see_documentation_to_enable_cluster')}
++                id="marketplace.see_documentation_to_enable_cluster"
++                values={{
++                  url: (
++                    <a
++                      href="https://redirect.sonarsource.com/doc/data-center-edition.html"
++                      target="_blank">
++                      {edition.name}
++                    </a>
++                  )
++                }}
++              />
++            </span>
++          )}
          {!preventRestart && (
            <button className="js-restart spacer-left" onClick={this.handleOpenRestart}>
              {translate('marketplace.restart')}
      const { editionStatus } = this.props;
      return (
        <NavBarNotif className="alert alert-danger">
 -        {edition ? (
 -          translateWithParameters(
 -            'marketplace.status_x.' + editionStatus.installationStatus,
 -            edition.name
 -          )
 -        ) : (
 -          translate('marketplace.status', editionStatus.installationStatus)
 -        )}
 +        {edition
 +          ? translateWithParameters(
 +              'marketplace.status_x.' + editionStatus.installationStatus,
 +              edition.name
 +            )
 +          : translate('marketplace.status', editionStatus.installationStatus)}
+         <a
+           className="spacer-left"
+           href={
 -            edition && edition.key === 'datacenter' ? (
 -              'https://redirect.sonarsource.com/doc/data-center-edition.html'
 -            ) : (
 -              'https://redirect.sonarsource.com/doc/how-to-install-an-edition.html'
 -            )
++            edition && edition.key === 'datacenter'
++              ? 'https://redirect.sonarsource.com/doc/data-center-edition.html'
++              : 'https://redirect.sonarsource.com/doc/how-to-install-an-edition.html'
+           }
+           target="_blank">
+           {translate('marketplace.how_to_install')}
+         </a>
          {edition && (
            <a
              className="button spacer-left"
index a0b1dfabb17b20fa3ccb42730c9f1b8f7959197c,0000000000000000000000000000000000000000..bdb9435384c638b729a3c9487d6c472990fdb2c8
mode 100644,000000..100644
--- /dev/null
@@@ -1,342 -1,0 +1,347 @@@
- .diplay-flex-row {
 +/*
 + * SonarQube
 + * Copyright (C) 2009-2017 SonarSource SA
 + * mailto:info AT sonarsource DOT com
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 3 of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public License
 + * along with this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + */
 +.vertical-top {
 +  vertical-align: top;
 +}
 +
 +.vertical-bottom {
 +  vertical-align: bottom;
 +}
 +
 +.vertical-middle {
 +  vertical-align: middle;
 +}
 +
 +.nowrap {
 +  white-space: nowrap;
 +}
 +
 +table.nowrap td,
 +td.nowrap,
 +th.nowrap {
 +  white-space: nowrap;
 +}
 +
 +.hidden {
 +  display: none !important;
 +  visibility: hidden !important;
 +}
 +
 +.note {
 +  color: var(--secondFontColor);
 +  font-size: var(--smallFontSize);
 +}
 +
 +.note a {
 +  color: var(--secondFontColor);
 +}
 +
 +.spacer-left {
 +  margin-left: 8px;
 +}
 +
 +.spacer-right {
 +  margin-right: 8px;
 +}
 +
 +.spacer-bottom {
 +  margin-bottom: 8px;
 +}
 +
 +.spacer-top {
 +  margin-top: 8px;
 +}
 +
 +.big-spacer-left {
 +  margin-left: 16px;
 +}
 +
 +.big-spacer-right {
 +  margin-right: 16px;
 +}
 +
 +.big-spacer-bottom {
 +  margin-bottom: 16px;
 +}
 +
 +.big-spacer-top {
 +  margin-top: 16px;
 +}
 +
 +.huge-spacer-top {
 +  margin-top: 40px;
 +}
 +
 +.huge-spacer-left {
 +  margin-left: 40px;
 +}
 +
 +.little-spacer-left {
 +  margin-left: 4px;
 +}
 +
 +.little-spacer-right {
 +  margin-right: 4px;
 +}
 +
 +.little-spacer-bottom {
 +  margin-bottom: 4px;
 +}
 +
 +.little-spacer-top {
 +  margin-top: 4px;
 +}
 +
 +td.little-spacer-left {
 +  padding-left: 4px;
 +}
 +
 +td.little-spacer-right {
 +  padding-right: 4px;
 +}
 +
 +td.spacer-left {
 +  padding-left: 8px;
 +}
 +
 +td.spacer-right {
 +  padding-right: 8px;
 +}
 +
 +td.spacer-bottom {
 +  padding-bottom: 8px;
 +}
 +
 +td.spacer-top {
 +  padding-top: 8px;
 +}
 +
 +td.big-spacer-left {
 +  padding-left: 16px;
 +}
 +
 +td.big-spacer-right {
 +  padding-right: 16px;
 +}
 +
 +td.big-spacer-bottom {
 +  padding-bottom: 16px;
 +}
 +
 +td.big-spacer-top {
 +  padding-top: 16px;
 +}
 +
 +.pull-left {
 +  float: left !important;
 +}
 +
 +.pull-right {
 +  float: right !important;
 +}
 +
 +.bordered {
 +  border: 1px solid var(--barBorderColor);
 +}
 +
 +.bordered-left {
 +  border-left: 1px solid var(--barBorderColor);
 +}
 +
 +.bordered-right {
 +  border-right: 1px solid var(--barBorderColor);
 +}
 +
 +.bordered-bottom {
 +  border-bottom: 1px solid var(--barBorderColor);
 +}
 +
 +.bordered-top {
 +  border-top: 1px solid var(--barBorderColor);
 +}
 +
 +.overflow-hidden {
 +  overflow: hidden;
 +}
 +
 +.width-100 {
 +  width: 100%;
 +}
 +
 +.width-80 {
 +  width: 80%;
 +}
 +
 +.width-60 {
 +  width: 60%;
 +}
 +
 +.width-55 {
 +  width: 55%;
 +}
 +
 +.width-50 {
 +  width: 50%;
 +}
 +
 +.width-40 {
 +  width: 40%;
 +}
 +
 +.width-30 {
 +  width: 30%;
 +}
 +
 +.width-25 {
 +  width: 25%;
 +}
 +
 +.width-20 {
 +  width: 20%;
 +}
 +
 +.width-15 {
 +  width: 15%;
 +}
 +
 +.width-10 {
 +  width: 10%;
 +}
 +
 +.abs-width-150 {
 +  width: 150px;
 +}
 +.abs-width-240 {
 +  width: 240px;
 +}
 +
 +.abs-width-300 {
 +  width: 300px;
 +}
 +
 +.abs-width-400 {
 +  width: 400px;
 +}
 +
 +.justify {
 +  margin-bottom: -1em;
 +  text-align: justify;
 +}
 +
 +.justify > .ib {
 +  display: inline-block;
 +}
 +
 +.justify:after {
 +  display: inline-block;
 +  width: 100%;
 +  content: ' ';
 +}
 +
 +.first-letter-uppercase::first-letter {
 +  text-transform: uppercase;
 +}
 +
 +.disabled-pointer-events {
 +  pointer-events: none !important;
 +}
 +
 +.display-block {
 +  display: block !important;
 +}
 +
 +.display-inline-block {
 +  display: inline-block !important;
 +}
 +
++.display-flex-row {
 +  display: flex !important;
 +  flex-direction: row;
 +}
 +
++.display-flex-center {
++  display: flex !important;
++  align-items: center;
++}
++
 +.rounded {
 +  border-radius: 2px;
 +}
 +
 +.flex-1 {
 +  flex: 1;
 +}
 +
 +.space-between {
 +  justify-content: space-between !important;
 +}
 +
 +.new-loading {
 +  opacity: 0.5;
 +  transition: opacity 0.5s ease;
 +}
 +
 +.slash-separator {
 +  margin-left: 5px;
 +  margin-right: 5px;
 +}
 +
 +.slash-separator:after {
 +  content: '/';
 +  color: rgba(68, 68, 68, 0.3);
 +}
 +
 +.capitalize {
 +  text-transform: capitalize;
 +}
 +
 +.cursor-not-allowed {
 +  cursor: not-allowed;
 +}
 +
 +.no-outline,
 +.no-outline:focus {
 +  outline: none;
 +}
 +
 +.bg-danger {
 +  background-color: var(--red);
 +  color: #fff;
 +}
 +
 +.bg-warning {
 +  background-color: var(--orange);
 +  color: #fff;
 +}
 +
 +.bg-info {
 +  background-color: var(--blue);
 +  color: #fff;
 +}
 +
 +.bg-success {
 +  background-color: var(--green);
 +  color: #fff;
 +}
 +
 +.bg-muted {
 +  background-color: var(--barBackgroundColor);
 +  color: inherit;
 +}
index ddba3af1b7240509b60b32f885fa70d7a14cea60,1dbbefc1153f3b4f4bf0c07396512dd3234002b3..8fab4b9d34b4e964371212e3a842bae1a6a00665
@@@ -114,23 -114,47 +114,45 @@@ export default class EditionBoxes exten
      }
  
      const sortedEditions = sortEditions(editions);
-     const installedIdx =
-       editionStatus &&
-       sortedEditions.findIndex(edition => edition.key === editionStatus.currentEditionKey);
+     const status = this.props.editionStatus || { installationStatus: 'NONE' };
+     const inProgressStatus = [
+       'AUTOMATIC_IN_PROGRESS',
+       'AUTOMATIC_READY',
+       'UNINSTALL_IN_PROGRESS'
+     ].includes(status.installationStatus);
+     const installedIdx = sortedEditions.findIndex(
+       edition => edition.key === status.currentEditionKey
+     );
+     const nextIdx = sortedEditions.findIndex(edition => edition.key === status.nextEditionKey);
+     const currentIdx = inProgressStatus ? nextIdx : installedIdx;
      return (
        <div className="spacer-bottom marketplace-editions">
-         {sortedEditions.map((edition, idx) => (
-           <EditionBox
-             canInstall={canInstall}
-             canUninstall={canUninstall}
-             edition={edition}
-             editionStatus={editionStatus}
-             isDowngrade={installedIdx !== undefined && idx < installedIdx}
-             key={edition.key}
-             onInstall={this.handleOpenLicenseForm}
-             onUninstall={this.handleOpenUninstallForm}
-           />
-         ))}
+         <EditionBox
+           actionLabel={translate('marketplace.downgrade')}
+           disableAction={inProgressStatus}
+           displayAction={canUninstall && currentIdx > 0}
+           edition={sortedEditions[0]}
+           editionStatus={status}
+           key={sortedEditions[0].key}
+           onAction={this.handleOpenUninstallForm}
+         />
+         {sortedEditions
+           .slice(1)
+           .map((edition, idx) => (
+             <EditionBox
+               actionLabel={
 -                currentIdx > idx + 1 ? (
 -                  translate('marketplace.downgrade')
 -                ) : (
 -                  translate('marketplace.upgrade')
 -                )
++                currentIdx > idx + 1
++                  ? translate('marketplace.downgrade')
++                  : translate('marketplace.upgrade')
+               }
+               disableAction={inProgressStatus}
+               displayAction={canInstall && currentIdx !== idx + 1}
+               edition={edition}
+               editionStatus={status}
+               key={edition.key}
+               onAction={this.handleOpenLicenseForm}
+             />
+           ))}
  
          {this.renderForms(sortedEditions, installedIdx)}
        </div>
index bd62c3de370a087893ba6976e17fda975cf5b6d8,644471ccdcad0cbdd3cf9e70b1b47f530c38c034..85ba8946957a6c404f3f633f2b2f26ab5f9faa3e
@@@ -55,14 -56,12 +56,13 @@@ exports[`should display the edition box
          "nextEditionKey": "",
        }
      }
-     isDowngrade={true}
 +    key="comunity"
-     onInstall={[Function]}
-     onUninstall={[Function]}
+     onAction={[Function]}
    />
    <EditionBox
-     canInstall={true}
-     canUninstall={true}
+     actionLabel="marketplace.upgrade"
+     disableAction={false}
+     displayAction={false}
      edition={
        Object {
          "downloadUrl": "download_url",
          "nextEditionKey": "",
        }
      }
-     isDowngrade={false}
 +    key="developer"
-     onInstall={[Function]}
-     onUninstall={[Function]}
+     onAction={[Function]}
    />
  </div>
  `;
index 47b3e767fe2fba5e5765c0c5690b8f692c03d108,e58c8edf24a859cf4844f73d3e10d0d84d367ac8..62c2efabcacdcfafae1281a7035401dd8a1714fb
@@@ -28,25 -28,33 +28,31 @@@ interface Props 
  }
  
  export default function EditionBoxBadge({ editionKey, status }: Props) {
-   const inProgress = ['AUTOMATIC_IN_PROGRESS', 'AUTOMATIC_READY'].includes(
-     status.installationStatus
-   );
-   const isInstalling = inProgress && status.nextEditionKey === editionKey;
+   const isInstalled =
+     status.currentEditionKey === editionKey ||
+     (!status.currentEditionKey && editionKey === 'community');
+   const isProgressing =
+     status.nextEditionKey === editionKey || (!status.nextEditionKey && editionKey === 'community');
+   const inProgressStatus = [
+     'AUTOMATIC_READY',
+     'AUTOMATIC_IN_PROGRESS',
+     'UNINSTALL_IN_PROGRESS'
+   ].includes(status.installationStatus);
  
-   if (isInstalling) {
-     const installReady = status.installationStatus === 'AUTOMATIC_READY';
+   if (inProgressStatus) {
+     if (isProgressing) {
+       return (
+         <span className="marketplace-edition-badge badge badge-normal-size">
 -          {status.installationStatus === 'AUTOMATIC_IN_PROGRESS' ? (
 -            translate('marketplace.installing')
 -          ) : (
 -            translate('marketplace.pending')
 -          )}
++          {status.installationStatus === 'AUTOMATIC_IN_PROGRESS'
++            ? translate('marketplace.installing')
++            : translate('marketplace.pending')}
+         </span>
+       );
+     }
+   } else if (isInstalled) {
      return (
-       <span className="marketplace-edition-badge badge badge-normal-size">
-         {installReady ? translate('marketplace.pending') : translate('marketplace.installing')}
-       </span>
-     );
-   }
-   const isInstalled = status.currentEditionKey === editionKey;
-   if (isInstalled) {
-     return (
-       <span className="marketplace-edition-badge badge badge-normal-size">
-         <CheckIcon size={14} className="little-spacer-right text-bottom" />
+       <span className="marketplace-edition-badge badge badge-normal-size display-flex-center">
+         <CheckIcon size={14} className="little-spacer-right" />
          {translate('marketplace.installed')}
        </span>
      );
index ea1320d082a59acae46e5208006964cc66244540,edcd13a3d037f2b1ce3406e8b7d40f686205e60a..f33cb6a39118a584076ba772a433c86675a1467c
   * along with this program; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   */
 +import { stringify } from 'querystring';
  import * as React from 'react';
  import * as classNames from 'classnames';
 -import { stringify } from 'querystring';
+ import { FormattedMessage } from 'react-intl';
  import { debounce } from 'lodash';
  import DeferredSpinner from '../../../components/common/DeferredSpinner';
  import { omitNil } from '../../../helpers/request';
@@@ -146,6 -147,25 +147,25 @@@ export default class LicenseEditionSet 
            'marketplace.license_preview_status.' + previewStatus,
            licenseEdition ? licenseEdition.name : translate('marketplace.commercial_edition')
          )}
 -        licenseEdition.key === 'datacenter' &&
 -        previewStatus !== 'NO_INSTALL' && (
 -          <span className="little-spacer-left">
 -            <FormattedMessage
 -              defaultMessage={translate('marketplace.how_to_setup_cluster_url')}
 -              id="marketplace.how_to_setup_cluster_url"
 -              values={{
 -                url: (
 -                  <a
 -                    href="https://redirect.sonarsource.com/doc/data-center-edition.html"
 -                    target="_blank">
 -                    {licenseEdition.name}
 -                  </a>
 -                )
 -              }}
 -            />
 -          </span>
 -        )}
+         {licenseEdition &&
++          licenseEdition.key === 'datacenter' &&
++          previewStatus !== 'NO_INSTALL' && (
++            <span className="little-spacer-left">
++              <FormattedMessage
++                defaultMessage={translate('marketplace.how_to_setup_cluster_url')}
++                id="marketplace.how_to_setup_cluster_url"
++                values={{
++                  url: (
++                    <a
++                      href="https://redirect.sonarsource.com/doc/data-center-edition.html"
++                      target="_blank">
++                      {licenseEdition.name}
++                    </a>
++                  )
++                }}
++              />
++            </span>
++          )}
        </p>
      );
    }
index c2bd0bf77111908f014f92b0f8cef12de03a2efb,2802634d264919c7480742dc98f4aa49d88ebb00..483d2fc9f071cf1c40d86ae34e342c89c14b5d7a
@@@ -73,9 -73,14 +73,9 @@@ export default class UninstallEditionFo
      const { edition } = this.props;
      const { loading } = this.state;
      const currentEdition = edition ? edition.name : translate('marketplace.commercial_edition');
-     const header = translateWithParameters('marketplace.uninstall_x', currentEdition);
+     const header = translateWithParameters('marketplace.downgrade_to_community_edition');
      return (
 -      <Modal
 -        isOpen={true}
 -        contentLabel={header}
 -        className="modal"
 -        overlayClassName="modal-overlay"
 -        onRequestClose={this.props.onClose}>
 +      <Modal contentLabel={header} onRequestClose={this.props.onClose}>
          <header className="modal-head">
            <h2>{header}</h2>
          </header>
index 0d5724e6fc1728bb47fa60b036e5750aa8a83882,7e824591e0212286c46458dc47a3e25bd0afe075..733b0062157b3dd288d41f964d21e46e7233eccf
@@@ -1,29 -1,9 +1,29 @@@
  // Jest Snapshot v1, https://goo.gl/fbAQLP
  
 -exports[`should display installed badge 1`] = `null`;
 +exports[`should display installed badge 1`] = `
 +<span
-   className="marketplace-edition-badge badge badge-normal-size"
++  className="marketplace-edition-badge badge badge-normal-size display-flex-center"
 +>
 +  <CheckIcon
-     className="little-spacer-right text-bottom"
++    className="little-spacer-right"
 +    size={14}
 +  />
 +  marketplace.installed
 +</span>
 +`;
  
 -exports[`should display installing badge 1`] = `null`;
 +exports[`should display installing badge 1`] = `
 +<span
 +  className="marketplace-edition-badge badge badge-normal-size"
 +>
 +  marketplace.installing
 +</span>
 +`;
  
 -exports[`should display pending badge 1`] = `null`;
 -
 -exports[`should not display a badge 1`] = `null`;
 +exports[`should display pending badge 1`] = `
 +<span
 +  className="marketplace-edition-badge badge badge-normal-size"
 +>
 +  marketplace.pending
 +</span>
 +`;
index 0b3ad80dd5cbd2bdbc9014938970e0cdab4abff0,a8d55e70b19cc08de9013c6fa4179349cd1aeb2b..0493fdbf245dc1622774646ba9a2f82cae4446da
@@@ -2,8 -2,17 +2,8 @@@
  
  exports[`should display correctly 1`] = `
  <Modal
-   contentLabel="marketplace.uninstall_x.Foo"
 -  ariaHideApp={true}
 -  bodyOpenClassName="ReactModal__Body--open"
 -  className="modal"
 -  closeTimeoutMS={0}
+   contentLabel="marketplace.downgrade_to_community_edition."
 -  isOpen={true}
    onRequestClose={[Function]}
 -  overlayClassName="modal-overlay"
 -  parentSelector={[Function]}
 -  portalClassName="ReactModalPortal"
 -  shouldCloseOnOverlayClick={true}
  >
    <header
      className="modal-head"