From a8fd935e8321f946737324aa37d6a62e58f136d5 Mon Sep 17 00:00:00 2001 From: Jeremy Davis Date: Mon, 1 Nov 2021 14:01:02 +0100 Subject: [PATCH] SONAR-15587 Sonarlint Promotion --- server/sonar-web/public/images/sq-sl.png | Bin 0 -> 2704 bytes .../js/app/components/GlobalContainer.tsx | 2 + .../GlobalContainer-test.tsx.snap | 1 + .../PromotionNotification.css | 34 ++++++++++ .../PromotionNotification.tsx | 61 ++++++++++++++++++ .../__tests__/PromotionNotification-test.tsx | 36 +++++++++++ .../PromotionNotification-test.tsx.snap | 46 +++++++++++++ server/sonar-web/src/main/js/app/theme.js | 5 ++ server/sonar-web/src/main/js/types/types.d.ts | 1 + .../resources/org/sonar/l10n/core.properties | 8 +++ .../ws/client/users/UsersService.java | 14 ++++ 11 files changed, 208 insertions(+) create mode 100644 server/sonar-web/public/images/sq-sl.png create mode 100644 server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.css create mode 100644 server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx create mode 100644 server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/PromotionNotification-test.tsx create mode 100644 server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/__snapshots__/PromotionNotification-test.tsx.snap diff --git a/server/sonar-web/public/images/sq-sl.png b/server/sonar-web/public/images/sq-sl.png new file mode 100644 index 0000000000000000000000000000000000000000..af6b984afea0b69bb9487c61c9441c18de7298ea GIT binary patch literal 2704 zcmV;B3UBp^P)0zqfioAUNtdIG>^#`O?&`GZDK{J@fA(m#8{_eh_xnZYp1c+ zgz~c5(I}$UF+)u|MPs8Pi}*mn0d>Jwji{g^xchzg|0pOf*K#p@D3+ZXPx-bA z`XQ6kZ>$8ifQkV`b)8=Cvv}*=uuG~wapN9edDV9gXY3aS;*8BH)-O6rsJA9zDI)L5 zK>mPgEeu&8k?TX%4r+dcuG(^!o?V$+wRJwErb<T|DdPHCpy4PCL>(MMz*pd=k5^*|m66Z+9 zuz@_XDn7kZc}T6i;bMug4y`9pgTw z*=b@cN!w^Lx~9J2>f2w;{>c?p7oSlyoq+;w`w`1!ptG!xWNuUKPi^4M1*Sp7>#El!hR9$XLbQUmNNn!mgKHD}#$u?C*rPIW4 z);Z+Z=DIqCkiyQSkqw)Yho%6?>f5;U zOxZzWN#}s$RGE$>#=Y8h38DJyy^hks?Huj=<5bvMYuhD+^5zYqV=topLU8*VB7EpC4O!G`B5#trFTZAiS?hgMX36 zSeIU8*Xa%PU9b8}YlmLAP}f@DeL>;jf-8^0t8P1#6PXofKbFQ6#f}oPMMsx>RIFhE|byvu_@#pJqg!Wp7Sct`nY>@Es9nFI!EQJQpYWdR7!PB)VnW&0y;j z(u*TZY%H<==2e#b6FLbR=!?ihuE{`2!I{t=LfFeRf@0nHx{ER+RZWggg4JGrkV043 zNC;j!MGGyoMTjx+OcOP%zv=sxy0Zm77I5g{C+=7fZGnM)%?D@xh!I+mIU+2zncf2P z;Nbiw9K!%-kg|*P8&3P+PooC9m!hnlpylm6JS+3#Pul)`@!GAJIeQk!+3> zLbweX5=?CpA~vpEC=EKZhAfsmkr!Q6w%y-XY$K&MA~II(O?Bo+7RH<`J3<}SQu%r6 z;%7)>SyV;EMS2*O5sD;jkE`5%6ouZ~=^#%*C`b9jTedX3(k3B^;Er*uUN6=dT%@Q% z#Ia)zp*hA7!8uGiUmUq}r|xQWs&p9WQK(cs0f4*ADhMuiB z<0U0!w|Nh@EzN;dEjZ*(6qv(OI0IKIQU@{eNqfmo=tR)o_BmZt0=Smltmz+f{``&G z>+cSkCfw5!OeiNnC*nY8Xg_r2{z1*2!scXJBoud|p}mA+8VBb#7dHlz zi_Bq5;5)z;64Hy#*V{>(I)fuhw(wqU?|B|V;h^IJt860mn?iHg?>+I<*TG?CMDP8y zFg9*83_pymJeGH__N^LFD=im1hi)xRt#g?ZKZrR~b_CkM;h>;C4czw)2K*f=4pcG; zxXyVUXFgqh{2F*dNMUc#;Ncn<>&Z_prSukYT{6t2gzg57IrduZ_FEqslm`og1_d)= z8cl&oB9YZyN9)pB;i#F}(#+}*A%%T?LwoWbUKyOpcv`J*53@R&RM77nrN4ah$q*&`x+XoeRuQ z1T*H0qxl<4J_=_H`_iKu6sEIOE=JA^M1b$^n4%&lbfX(xjBf$bZU!6f?NU?#0000< KMNUMnLSTX_bPq`Y literal 0 HcmV?d00001 diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx index e31bf86e066..3ecf5816e69 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx @@ -28,6 +28,7 @@ import IndexationContextProvider from './indexation/IndexationContextProvider'; import IndexationNotification from './indexation/IndexationNotification'; import GlobalNav from './nav/global/GlobalNav'; import StartupModal from './StartupModal'; +import PromotionNotification from './promotion-notification/PromotionNotification'; import UpdateNotification from './update-notification/UpdateNotification'; export interface Props { @@ -58,6 +59,7 @@ export default function GlobalContainer(props: Props) { + {footer} diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap index 7f04cba74c2..03e12641665 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap @@ -37,6 +37,7 @@ exports[`should render correctly 1`] = ` + diff --git a/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.css b/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.css new file mode 100644 index 00000000000..52217e8226d --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.css @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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. + */ +.toaster { + position: fixed; + right: 10px; + bottom: 10px; + max-width: 550px; + background-color: var(--darkBackground); + z-index: var(--popupZIndex); + box-shadow: 1px 1px 5px 0px black; + color: var(--darkBackgroundFontColor); + border-radius: 4px; +} + +.toaster-content { + border-right: 1px solid var(--darkBackgroundSeparator); +} diff --git a/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx b/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx new file mode 100644 index 00000000000..92765402c3c --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx @@ -0,0 +1,61 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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. + */ +import * as React from 'react'; +import { withCurrentUser } from '../../../components/hoc/withCurrentUser'; +import { translate } from '../../../helpers/l10n'; +import { isLoggedIn } from '../../../helpers/users'; +import './PromotionNotification.css'; + +export interface PromotionNotificationProps { + currentUser: T.CurrentUser; +} + +export function PromotionNotification(props: PromotionNotificationProps) { + const { currentUser } = props; + + if (!isLoggedIn(currentUser) || currentUser.sonarLintAdSeen) { + return null; + } + + return ( +
+
+ SonarQube + SonarLint +
+
+ + {translate('promotion.sonarlint.title')} + +

{translate('promotion.sonarlint.content')}

+
+ +
+ ); +} + +export default withCurrentUser(PromotionNotification); diff --git a/server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/PromotionNotification-test.tsx b/server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/PromotionNotification-test.tsx new file mode 100644 index 00000000000..cbc90b77fc1 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/PromotionNotification-test.tsx @@ -0,0 +1,36 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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. + */ + +import { shallow } from 'enzyme'; +import React from 'react'; +import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks'; +import { PromotionNotification, PromotionNotificationProps } from '../PromotionNotification'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('anonymous'); + expect( + shallowRender({ currentUser: mockLoggedInUser({ sonarLintAdSeen: true }) }) + ).toMatchSnapshot('adAlreadySeen'); + expect(shallowRender({ currentUser: mockLoggedInUser() })).toMatchSnapshot('loggedIn'); +}); + +function shallowRender(props: Partial = {}) { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/__snapshots__/PromotionNotification-test.tsx.snap b/server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/__snapshots__/PromotionNotification-test.tsx.snap new file mode 100644 index 00000000000..2726d40d53e --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/__snapshots__/PromotionNotification-test.tsx.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: adAlreadySeen 1`] = `""`; + +exports[`should render correctly: anonymous 1`] = `""`; + +exports[`should render correctly: loggedIn 1`] = ` +
+
+ SonarQube + SonarLint +
+
+ + promotion.sonarlint.title + +

+ promotion.sonarlint.content +

+
+ +
+`; diff --git a/server/sonar-web/src/main/js/app/theme.js b/server/sonar-web/src/main/js/app/theme.js index 21528195573..ee49a1f5451 100644 --- a/server/sonar-web/src/main/js/app/theme.js +++ b/server/sonar-web/src/main/js/app/theme.js @@ -120,6 +120,11 @@ module.exports = { // code/pre codeBackground: '#e6e6e6', + //promotion + darkBackground: '#292929', + darkBackgroundSeparator: '#413b3b', + darkBackgroundFontColor: '#f6f8fa', + // sonarcloud sonarcloudOrange500: '#fd6a00', sonarcloudOrange600: '#e26003', diff --git a/server/sonar-web/src/main/js/types/types.d.ts b/server/sonar-web/src/main/js/types/types.d.ts index 6884cc86435..3b82fbe999d 100644 --- a/server/sonar-web/src/main/js/types/types.d.ts +++ b/server/sonar-web/src/main/js/types/types.d.ts @@ -443,6 +443,7 @@ declare namespace T { local?: boolean; scmAccounts: string[]; settings?: CurrentUserSetting[]; + sonarLintAdSeen?: boolean; } export interface Measure extends MeasureIntern { diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 93db9defbea..36c73ff1e70 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2649,6 +2649,14 @@ permission_templates.bulk_apply_permission_template.apply_to_all=You're about to permission_templates.select_to_delete=You must select at least one item permission_templates.delete_selected=Delete all selected items +#------------------------------------------------------------------------------ +# +# Promotion +# +#------------------------------------------------------------------------------ + +promotion.sonarlint.title=Welcome to SonarQube! +promotion.sonarlint.content=To get the best experience, we recommend taking advantage of the entire ecosystem by also using SonarLint, a free IDE plugin that helps you find and fix issues earlier in your workflow. Connect it to SonarQube to sync rule sets and issue states. #------------------------------------------------------------------------------ # diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/users/UsersService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/users/UsersService.java index edcad0df8be..599b8689266 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/users/UsersService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/users/UsersService.java @@ -244,4 +244,18 @@ public class UsersService extends BaseService { .setMediaType(MediaTypes.JSON) ).content(); } + + /** + * + * This is part of the internal API. + * This is a POST request. + * @see Further information about this action online (including a response example) + * @since 9.2 + */ + public void dismissSonarlintAd() { + call( + new PostRequest(path("dismiss_sonarlint_ad")) + .setMediaType(MediaTypes.JSON) + ).content(); + } } -- 2.39.5