]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9357 support two or more providers (#2259)
authorStas Vilchik <stas.vilchik@sonarsource.com>
Tue, 18 Jul 2017 12:08:11 +0000 (14:08 +0200)
committerGitHub <noreply@github.com>
Tue, 18 Jul 2017 12:08:11 +0000 (14:08 +0200)
server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js
server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js
server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/about/sonarqube-dot-com-styles.css
server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js
server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginForm-test.js.snap
server/sonar-web/src/main/less/pages/login.less
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index a4e39e093983281591527a4dea857d440be9d247..eadbc23ff02a67777c4c72a64ee1c6ee15d3b000 100644 (file)
@@ -40,8 +40,7 @@ type Props = {
   fetchMyOrganizations: () => Promise<*>,
   location: Object,
   organizations: Array<{ key: string, name: string }>,
-  router: { push: string => void },
-  sonarCloud: boolean
+  router: { push: string => void }
 };
 
 type State = {
@@ -157,24 +156,13 @@ export default class GlobalNavUser extends React.PureComponent {
   }
 
   renderAnonymous() {
-    return this.props.sonarCloud
-      ? <li>
-          <a href="/sessions/init/github">
-            <img
-              alt="GitHub"
-              className="navbar-global-login-github"
-              width="14"
-              height="14"
-              src="/static/authgithub/github.svg"
-            />
-            {translate('layout.login')}
-          </a>
-        </li>
-      : <li>
-          <a onClick={this.handleLogin} href="#">
-            {translate('layout.login')}
-          </a>
-        </li>;
+    return (
+      <li>
+        <a onClick={this.handleLogin} href="#">
+          {translate('layout.login')}
+        </a>
+      </li>
+    );
   }
 
   render() {
index 6072a5afb54f2a94e666791526953ab24b543b63..2e9eee74ed4e21acbd08132bb8aa1cb0ac10522b 100644 (file)
@@ -28,6 +28,7 @@ import AboutQualityGates from './AboutQualityGates';
 import AboutLeakPeriod from './AboutLeakPeriod';
 import AboutStandards from './AboutStandards';
 import AboutScanners from './AboutScanners';
+import SonarCloudGetStarted from './SonarCloudGetStarted';
 import '../sonarqube-dot-com-styles.css';
 
 type Props = {
@@ -55,11 +56,7 @@ export default function AboutAppForSonarQubeDotCom(props: Props) {
             <h1 className="big-spacer-bottom">
               Continuous Code Quality<br />as a Service
             </h1>
-            {!props.currentUser.isLoggedIn &&
-              <a className="sonarcloud-about-github-button" href="/sessions/init/github">
-                <img alt="GitHub" width="20" height="20" src="/static/authgithub/github.svg" />
-                Connect With GitHub to Get Started
-              </a>}
+            {!props.currentUser.isLoggedIn && <SonarCloudGetStarted />}
           </div>
 
           <div className="sqcom-about-page-instance">
diff --git a/server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js b/server/sonar-web/src/main/js/apps/about/components/SonarCloudGetStarted.js
new file mode 100644 (file)
index 0000000..e467dfc
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+// @flow
+import React from 'react';
+import OAuthProviders from '../../sessions/components/OAuthProviders';
+import { getIdentityProviders } from '../../../api/users';
+
+type State = {
+  identityProviders: Array<{
+    backgroundColor: string,
+    iconPath: string,
+    key: string,
+    name: string
+  }>,
+  loading: boolean
+};
+
+export default class SonarCloudGetStarted extends React.PureComponent {
+  mounted: boolean;
+  state: State = {
+    identityProviders: [],
+    loading: true
+  };
+
+  componentDidMount() {
+    this.mounted = true;
+    this.fetchIdentityProviders();
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  fetchIdentityProviders = () => {
+    this.setState({ loading: true });
+    getIdentityProviders().then(({ identityProviders }) => {
+      if (this.mounted) {
+        this.setState({ identityProviders, loading: false });
+      }
+    });
+  };
+
+  formatLabel = (name: string) => `Start with ${name}`;
+
+  render() {
+    if (this.state.loading) {
+      return null;
+    }
+
+    return (
+      <div className="sqcom-get-started">
+        <OAuthProviders
+          formatLabel={this.formatLabel}
+          identityProviders={this.state.identityProviders}
+        />
+      </div>
+    );
+  }
+}
index 1895646e681e67c7467370ea87abf2573f4c11c8..dc5a19e05594c3c10e397d7f73f03da6e11af1e2 100644 (file)
   align-items: center;
 }
 
-.sqcom-about-page-intro {}
+.sqcom-about-page-intro {
+}
 
 .sqcom-about-page-intro > h1 {
-  line-height: 56px;
+  line-height: 44px;
   color: #fff;
-  font-size: 44px;
+  font-size: 36px;
   font-weight: 300;
 }
 
 .sqcom-about-quality-model svg {
   transform: translateY(-3px) !important;
 }
+
+.sqcom-get-started .oauth-providers > ul {
+  width: 380px;
+  justify-content: space-between;
+  font-size: 14px;
+  margin-bottom: -30px;
+}
index 3ac61372fdf86cf24ad10fd9e75865a02f132b38..76d51dfcfd558c359f18ad36033411d0e4852805 100644 (file)
@@ -19,6 +19,7 @@
  */
 // @flow
 import React from 'react';
+import OAuthProviders from './OAuthProviders';
 import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer';
 import { translate } from '../../../helpers/l10n';
 
@@ -67,26 +68,7 @@ export default class LoginForm extends React.PureComponent {
         <h1 className="maintenance-title text-center">{translate('login.login_to_sonarqube')}</h1>
 
         {this.props.identityProviders.length > 0 &&
-          <section className="oauth-providers">
-            <ul>
-              {this.props.identityProviders.map(identityProvider => (
-                <li key={identityProvider.key}>
-                  <a
-                    href={`${window.baseUrl}/sessions/init/${identityProvider.key}`}
-                    style={{ backgroundColor: identityProvider.backgroundColor }}
-                    title={`Log in with ${identityProvider.name}`}>
-                    <img
-                      alt={identityProvider.name}
-                      width="20"
-                      height="20"
-                      src={window.baseUrl + identityProvider.iconPath}
-                    />
-                    <span>Log in with {identityProvider.name}</span>
-                  </a>
-                </li>
-              ))}
-            </ul>
-          </section>}
+          <OAuthProviders identityProviders={this.props.identityProviders} />}
 
         {this.state.collapsed
           ? <div className="text-center">
diff --git a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.js
new file mode 100644 (file)
index 0000000..096637e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+// @flow
+import React from 'react';
+import { translateWithParameters } from '../../../helpers/l10n';
+
+type Props = {
+  formatLabel?: string => string,
+  identityProviders: Array<{
+    backgroundColor: string,
+    iconPath: string,
+    key: string,
+    name: string
+  }>
+};
+
+export default function OAuthProviders(props: Props) {
+  return (
+    <section className="oauth-providers">
+      <ul>
+        {props.identityProviders.map(identityProvider => (
+          <li key={identityProvider.key}>
+            <a
+              href={`${window.baseUrl}/sessions/init/${identityProvider.key}`}
+              style={{ backgroundColor: identityProvider.backgroundColor }}
+              // $FlowFixMe formatLabel is always defined through defaultProps
+              title={props.formatLabel(identityProvider.name)}>
+              <img
+                alt={identityProvider.name}
+                width="20"
+                height="20"
+                src={window.baseUrl + identityProvider.iconPath}
+              />
+              {/* $FlowFixMe formatLabel is always defined through defaultProps */}
+              <span>{props.formatLabel(identityProvider.name)}</span>
+            </a>
+          </li>
+        ))}
+      </ul>
+    </section>
+  );
+}
+
+OAuthProviders.defaultProps = {
+  formatLabel: (name: string) => translateWithParameters('login.login_with_x', name)
+};
index 58c919aa1e85936bb5bf726373c320c067944851..42113f43dc0377ae9e474192c45eec80277961fa 100644 (file)
@@ -9,34 +9,19 @@ exports[`expands more options 1`] = `
   >
     login.login_to_sonarqube
   </h1>
-  <section
-    className="oauth-providers"
-  >
-    <ul>
-      <li>
-        <a
-          href="/sessions/init/foo"
-          style={
-            Object {
-              "backgroundColor": "#000",
-            }
-          }
-          title="Log in with foo"
-        >
-          <img
-            alt="foo"
-            height="20"
-            src="/some/path"
-            width="20"
-          />
-          <span>
-            Log in with 
-            foo
-          </span>
-        </a>
-      </li>
-    </ul>
-  </section>
+  <OAuthProviders
+    formatLabel={[Function]}
+    identityProviders={
+      Array [
+        Object {
+          "backgroundColor": "#000",
+          "iconPath": "/some/path",
+          "key": "foo",
+          "name": "foo",
+        },
+      ]
+    }
+  />
   <div
     className="text-center"
   >
@@ -60,34 +45,19 @@ exports[`expands more options 2`] = `
   >
     login.login_to_sonarqube
   </h1>
-  <section
-    className="oauth-providers"
-  >
-    <ul>
-      <li>
-        <a
-          href="/sessions/init/foo"
-          style={
-            Object {
-              "backgroundColor": "#000",
-            }
-          }
-          title="Log in with foo"
-        >
-          <img
-            alt="foo"
-            height="20"
-            src="/some/path"
-            width="20"
-          />
-          <span>
-            Log in with 
-            foo
-          </span>
-        </a>
-      </li>
-    </ul>
-  </section>
+  <OAuthProviders
+    formatLabel={[Function]}
+    identityProviders={
+      Array [
+        Object {
+          "backgroundColor": "#000",
+          "iconPath": "/some/path",
+          "key": "foo",
+          "name": "foo",
+        },
+      ]
+    }
+  />
   <form
     onSubmit={[Function]}
   >
@@ -165,34 +135,19 @@ exports[`logs in with identity provider 1`] = `
   >
     login.login_to_sonarqube
   </h1>
-  <section
-    className="oauth-providers"
-  >
-    <ul>
-      <li>
-        <a
-          href="/sessions/init/foo"
-          style={
-            Object {
-              "backgroundColor": "#000",
-            }
-          }
-          title="Log in with foo"
-        >
-          <img
-            alt="foo"
-            height="20"
-            src="/some/path"
-            width="20"
-          />
-          <span>
-            Log in with 
-            foo
-          </span>
-        </a>
-      </li>
-    </ul>
-  </section>
+  <OAuthProviders
+    formatLabel={[Function]}
+    identityProviders={
+      Array [
+        Object {
+          "backgroundColor": "#000",
+          "iconPath": "/some/path",
+          "key": "foo",
+          "name": "foo",
+        },
+      ]
+    }
+  />
   <div
     className="text-center"
   >
index 991fa4383b36e4b531e29873d98f9ca2e4384b77..a87804cb352d1c35fccb575980f2236eef3780cf 100644 (file)
@@ -90,6 +90,7 @@
         color: #fff;
         white-space: nowrap;
         overflow: hidden;
+        text-align: center;
         text-overflow: ellipsis;
 
         &:hover, &:focus {
index 6b132ffad972839103bb3de66823a86f07d40ccb..474ae2f9420986995f6a0ff03087af6a5eeae91e 100644 (file)
@@ -1867,6 +1867,7 @@ user.password_cant_be_changed_on_external_auth=Password cannot be changed when e
 
 login.login_to_sonarqube=Log In to SonarQube
 login.more_options=More options
+login.login_with_x=Log in with {0}
 
 #------------------------------------------------------------------------------
 #