aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-web/src/main/js/api/mocks/CodingRulesMock.ts4
-rw-r--r--server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts4
-rw-r--r--server/sonar-web/src/main/js/api/users.ts6
-rw-r--r--server/sonar-web/src/main/js/app/components/current-user/CurrentUserContext.ts4
-rw-r--r--server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx11
-rw-r--r--server/sonar-web/src/main/js/app/components/promotion-notification/PromotionNotification.tsx18
-rw-r--r--server/sonar-web/src/main/js/app/components/promotion-notification/__tests__/PromotionNotification-test.tsx39
-rw-r--r--server/sonar-web/src/main/js/components/hoc/__tests__/whenLoggedIn-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/components/rules/TabViewer.tsx4
-rw-r--r--server/sonar-web/src/main/js/types/users.ts2
10 files changed, 52 insertions, 42 deletions
diff --git a/server/sonar-web/src/main/js/api/mocks/CodingRulesMock.ts b/server/sonar-web/src/main/js/api/mocks/CodingRulesMock.ts
index f23c2913c7c..0f6d6af4791 100644
--- a/server/sonar-web/src/main/js/api/mocks/CodingRulesMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/CodingRulesMock.ts
@@ -40,7 +40,7 @@ import {
SearchQualityProfilesResponse
} from '../quality-profiles';
import { getRuleDetails, getRulesApp, searchRules, updateRule } from '../rules';
-import { dismissNotification, getCurrentUser } from '../users';
+import { dismissNotice, getCurrentUser } from '../users';
interface FacetFilter {
languages?: string;
@@ -184,7 +184,7 @@ export default class CodingRulesMock {
(bulkDeactivateRules as jest.Mock).mockImplementation(this.handleBulkDeactivateRules);
(getFacet as jest.Mock).mockImplementation(this.handleGetGacet);
(getCurrentUser as jest.Mock).mockImplementation(this.handleGetCurrentUser);
- (dismissNotification as jest.Mock).mockImplementation(this.handleDismissNotification);
+ (dismissNotice as jest.Mock).mockImplementation(this.handleDismissNotification);
this.rules = cloneDeep(this.defaultRules);
}
diff --git a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
index 7b83314b8d3..0188a721882 100644
--- a/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
@@ -46,7 +46,7 @@ import { NoticeType } from '../../types/users';
import { getComponentForSourceViewer, getSources } from '../components';
import { getIssueFlowSnippets, searchIssues } from '../issues';
import { getRuleDetails } from '../rules';
-import { dismissNotification, getCurrentUser } from '../users';
+import { dismissNotice, getCurrentUser } from '../users';
function mockReferenceComponent(override?: Partial<ReferencedComponent>) {
return {
@@ -200,7 +200,7 @@ export default class IssuesServiceMock {
this.handleGetComponentForSourceViewer
);
(getCurrentUser as jest.Mock).mockImplementation(this.handleGetCurrentUser);
- (dismissNotification as jest.Mock).mockImplementation(this.handleDismissNotification);
+ (dismissNotice as jest.Mock).mockImplementation(this.handleDismissNotification);
}
async getStandards(): Promise<Standards> {
diff --git a/server/sonar-web/src/main/js/api/users.ts b/server/sonar-web/src/main/js/api/users.ts
index dae13297e64..a5154d91839 100644
--- a/server/sonar-web/src/main/js/api/users.ts
+++ b/server/sonar-web/src/main/js/api/users.ts
@@ -26,7 +26,7 @@ export function getCurrentUser(): Promise<CurrentUser> {
return getJSON('/api/users/current', undefined, true);
}
-export function dismissNotification(notice: NoticeType) {
+export function dismissNotice(notice: NoticeType) {
return post('/api/users/dismiss_notice', { notice }).catch(throwGlobalError);
}
@@ -99,7 +99,3 @@ export function deactivateUser(data: { login: string }): Promise<User> {
export function setHomePage(homepage: HomePage): Promise<void | Response> {
return post('/api/users/set_homepage', homepage).catch(throwGlobalError);
}
-
-export function dismissSonarlintAd(): Promise<void | Response> {
- return post('/api/users/dismiss_sonarlint_ad').catch(throwGlobalError);
-}
diff --git a/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContext.ts b/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContext.ts
index efb10534705..ec40a19e7bb 100644
--- a/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContext.ts
+++ b/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContext.ts
@@ -18,12 +18,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { CurrentUser, HomePage } from '../../../types/users';
+import { CurrentUser, HomePage, NoticeType } from '../../../types/users';
export interface CurrentUserContextInterface {
currentUser: CurrentUser;
updateCurrentUserHomepage: (homepage: HomePage) => void;
- updateCurrentUserSonarLintAdSeen: () => void;
+ updateDismissedNotices: (key: NoticeType, value: boolean) => void;
}
export const CurrentUserContext = React.createContext<CurrentUserContextInterface | undefined>(
diff --git a/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx b/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx
index fb70ec97b91..2ec9e3de4f7 100644
--- a/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx
+++ b/server/sonar-web/src/main/js/app/components/current-user/CurrentUserContextProvider.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { CurrentUser, HomePage } from '../../../types/users';
+import { CurrentUser, HomePage, NoticeType } from '../../../types/users';
import { CurrentUserContext } from './CurrentUserContext';
interface Props {
@@ -41,9 +41,12 @@ export default class CurrentUserContextProvider extends React.PureComponent<Prop
}));
};
- updateCurrentUserSonarLintAdSeen = () => {
+ updateDismissedNotices = (key: NoticeType, value: boolean) => {
this.setState(prevState => ({
- currentUser: { ...prevState.currentUser, sonarLintAdSeen: true }
+ currentUser: {
+ ...prevState.currentUser,
+ dismissedNotices: { ...prevState.currentUser.dismissedNotices, [key]: value }
+ }
}));
};
@@ -53,7 +56,7 @@ export default class CurrentUserContextProvider extends React.PureComponent<Prop
value={{
currentUser: this.state.currentUser,
updateCurrentUserHomepage: this.updateCurrentUserHomepage,
- updateCurrentUserSonarLintAdSeen: this.updateCurrentUserSonarLintAdSeen
+ updateDismissedNotices: this.updateDismissedNotices
}}>
{this.props.children}
</CurrentUserContext.Provider>
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
index 924b1da4cae..e4f4934f5ba 100644
--- 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
@@ -18,28 +18,32 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { dismissSonarlintAd } from '../../../api/users';
+import { dismissNotice } from '../../../api/users';
import { ButtonLink } from '../../../components/controls/buttons';
import { translate } from '../../../helpers/l10n';
import { getBaseUrl } from '../../../helpers/system';
-import { isLoggedIn } from '../../../types/users';
+import { isLoggedIn, NoticeType } from '../../../types/users';
import { CurrentUserContextInterface } from '../current-user/CurrentUserContext';
import withCurrentUserContext from '../current-user/withCurrentUserContext';
import './PromotionNotification.css';
-export interface PromotionNotificationProps
- extends Pick<CurrentUserContextInterface, 'currentUser' | 'updateCurrentUserSonarLintAdSeen'> {}
+export interface PromotionNotificationProps extends CurrentUserContextInterface {}
export function PromotionNotification(props: PromotionNotificationProps) {
const { currentUser } = props;
- if (!isLoggedIn(currentUser) || currentUser.sonarLintAdSeen) {
+ if (!isLoggedIn(currentUser) || currentUser.dismissedNotices[NoticeType.SONARLINT_AD]) {
return null;
}
const onClick = () => {
- dismissSonarlintAd();
- props.updateCurrentUserSonarLintAdSeen();
+ dismissNotice(NoticeType.SONARLINT_AD)
+ .then(() => {
+ props.updateDismissedNotices(NoticeType.SONARLINT_AD, true);
+ })
+ .catch(() => {
+ /* noop */
+ });
};
return (
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
index 059d0560dbf..e686ef86c74 100644
--- 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
@@ -19,12 +19,14 @@
*/
import { shallow } from 'enzyme';
import React from 'react';
-import { dismissSonarlintAd } from '../../../../api/users';
+import { dismissNotice } from '../../../../api/users';
import { mockCurrentUser, mockLoggedInUser } from '../../../../helpers/testMocks';
+import { waitAndUpdate } from '../../../../helpers/testUtils';
+import { NoticeType } from '../../../../types/users';
import { PromotionNotification, PromotionNotificationProps } from '../PromotionNotification';
jest.mock('../../../../api/users', () => ({
- dismissSonarlintAd: jest.fn()
+ dismissNotice: jest.fn().mockResolvedValue({})
}));
beforeEach(() => {
@@ -34,38 +36,43 @@ beforeEach(() => {
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('anonymous');
expect(
- shallowRender({ currentUser: mockLoggedInUser({ sonarLintAdSeen: true }) })
+ shallowRender({
+ currentUser: mockLoggedInUser({ dismissedNotices: { [NoticeType.SONARLINT_AD]: true } })
+ })
).toMatchSnapshot('adAlreadySeen');
expect(shallowRender({ currentUser: mockLoggedInUser() })).toMatchSnapshot('loggedIn');
});
-it('should remove the toaster when click on dismiss', () => {
- const updateCurrentUserSonarLintAdSeen = jest.fn();
+it('should remove the toaster when click on dismiss', async () => {
+ const updateDismissedNotices = jest.fn();
const wrapper = shallowRender({
- currentUser: mockLoggedInUser({ sonarLintAdSeen: false }),
- updateCurrentUserSonarLintAdSeen
+ currentUser: mockLoggedInUser({ dismissedNotices: { [NoticeType.SONARLINT_AD]: false } }),
+ updateDismissedNotices
});
wrapper.find('.toaster-actions ButtonLink').simulate('click');
- expect(dismissSonarlintAd).toBeCalled();
- expect(updateCurrentUserSonarLintAdSeen).toBeCalled();
+ expect(dismissNotice).toBeCalled();
+ await waitAndUpdate(wrapper);
+ expect(updateDismissedNotices).toBeCalled();
});
-it('should remove the toaster and navigate to sonarlint when click on learn more', () => {
- const updateCurrentUserSonarLintAdSeen = jest.fn();
+it('should remove the toaster and navigate to sonarlint when click on learn more', async () => {
+ const updateDismissedNotices = jest.fn();
const wrapper = shallowRender({
- currentUser: mockLoggedInUser({ sonarLintAdSeen: false }),
- updateCurrentUserSonarLintAdSeen
+ currentUser: mockLoggedInUser({ dismissedNotices: { [NoticeType.SONARLINT_AD]: false } }),
+ updateDismissedNotices
});
wrapper.find('.toaster-actions .button-primary').simulate('click');
- expect(dismissSonarlintAd).toBeCalled();
- expect(updateCurrentUserSonarLintAdSeen).toBeCalled();
+ expect(dismissNotice).toBeCalled();
+ await waitAndUpdate(wrapper);
+ expect(updateDismissedNotices).toBeCalled();
});
function shallowRender(props: Partial<PromotionNotificationProps> = {}) {
return shallow(
<PromotionNotification
currentUser={mockCurrentUser()}
- updateCurrentUserSonarLintAdSeen={jest.fn()}
+ updateDismissedNotices={jest.fn()}
+ updateCurrentUserHomepage={jest.fn()}
{...props}
/>
);
diff --git a/server/sonar-web/src/main/js/components/hoc/__tests__/whenLoggedIn-test.tsx b/server/sonar-web/src/main/js/components/hoc/__tests__/whenLoggedIn-test.tsx
index fef59735274..94948c10831 100644
--- a/server/sonar-web/src/main/js/components/hoc/__tests__/whenLoggedIn-test.tsx
+++ b/server/sonar-web/src/main/js/components/hoc/__tests__/whenLoggedIn-test.tsx
@@ -57,7 +57,7 @@ function shallowRender(isLoggedIn = true) {
value={{
currentUser: { isLoggedIn, dismissedNotices: {} },
updateCurrentUserHomepage: () => {},
- updateCurrentUserSonarLintAdSeen: () => {}
+ updateDismissedNotices: () => {}
}}>
<UnderTest />
</CurrentUserContext.Provider>
diff --git a/server/sonar-web/src/main/js/components/rules/TabViewer.tsx b/server/sonar-web/src/main/js/components/rules/TabViewer.tsx
index 0d781222ee1..47c7ac8210c 100644
--- a/server/sonar-web/src/main/js/components/rules/TabViewer.tsx
+++ b/server/sonar-web/src/main/js/components/rules/TabViewer.tsx
@@ -20,7 +20,7 @@
import classNames from 'classnames';
import { debounce, Dictionary } from 'lodash';
import * as React from 'react';
-import { dismissNotification, getCurrentUser } from '../../api/users';
+import { dismissNotice, getCurrentUser } from '../../api/users';
import { RuleDescriptionSection, RuleDescriptionSections } from '../../apps/coding-rules/rule';
import { RuleDetails } from '../../types/types';
import { CurrentUser, NoticeType } from '../../types/users';
@@ -112,7 +112,7 @@ export default class TabViewer extends React.PureComponent<Props, State> {
const rect = this.educationPrinciplesRef.current.getBoundingClientRect();
const isView = rect.top <= (window.innerHeight || document.documentElement.clientHeight);
if (isView && this.showNotification) {
- dismissNotification(NoticeType.EDUCATION_PRINCIPLES)
+ dismissNotice(NoticeType.EDUCATION_PRINCIPLES)
.then(() => {
document.removeEventListener('scroll', this.checkIfConceptIsVisible, { capture: true });
this.showNotification = false;
diff --git a/server/sonar-web/src/main/js/types/users.ts b/server/sonar-web/src/main/js/types/users.ts
index 00537801159..e8aeae81218 100644
--- a/server/sonar-web/src/main/js/types/users.ts
+++ b/server/sonar-web/src/main/js/types/users.ts
@@ -32,7 +32,7 @@ export interface Notice {
export enum NoticeType {
EDUCATION_PRINCIPLES = 'educationPrinciples',
- SONARLINT_AD_SEEN = 'sonarlint_ad_seen'
+ SONARLINT_AD = 'sonarlintAd'
}
export interface LoggedInUser extends CurrentUser, UserActive {