Skip to content

Commit

Permalink
Fix newsfeed unread notifications always on when reloading Kibana (#1…
Browse files Browse the repository at this point in the history
…00357)

* fix the implementation

* add unit tests

* add API unit tests

* fix public interface

* address review comments

* name convertItem to localizeItem

* use fetch instead of core.http and add tests
  • Loading branch information
pgayvallet authored Jun 2, 2021
1 parent 8cb3dbc commit ccc1485
Show file tree
Hide file tree
Showing 15 changed files with 936 additions and 866 deletions.
5 changes: 0 additions & 5 deletions src/plugins/newsfeed/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
*/

export const NEWSFEED_FALLBACK_LANGUAGE = 'en';
export const NEWSFEED_FALLBACK_FETCH_INTERVAL = 86400000; // 1 day
export const NEWSFEED_FALLBACK_MAIN_INTERVAL = 120000; // 2 minutes
export const NEWSFEED_LAST_FETCH_STORAGE_KEY = 'newsfeed.lastfetchtime';
export const NEWSFEED_HASH_SET_STORAGE_KEY = 'newsfeed.hashes';

export const NEWSFEED_DEFAULT_SERVICE_BASE_URL = 'https://feeds.elastic.co';
export const NEWSFEED_DEV_SERVICE_BASE_URL = 'https://feeds-staging.elastic.co';
export const NEWSFEED_DEFAULT_SERVICE_PATH = '/kibana/v{VERSION}.json';
Original file line number Diff line number Diff line change
Expand Up @@ -6,71 +6,69 @@
* Side Public License, v 1.
*/

import React, { useState, Fragment, useEffect } from 'react';
import * as Rx from 'rxjs';
import React, { useState, useEffect, useMemo, useCallback } from 'react';
import { EuiHeaderSectionItemButton, EuiIcon } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { NewsfeedApi } from '../lib/api';
import { NewsfeedFlyout } from './flyout_list';
import { FetchResult } from '../types';

export interface INewsfeedContext {
setFlyoutVisible: React.Dispatch<React.SetStateAction<boolean>>;
newsFetchResult: FetchResult | void | null;
}
export const NewsfeedContext = React.createContext({} as INewsfeedContext);

export type NewsfeedApiFetchResult = Rx.Observable<void | FetchResult | null>;
export const NewsfeedContext = React.createContext({} as INewsfeedContext);

export interface Props {
apiFetchResult: NewsfeedApiFetchResult;
newsfeedApi: NewsfeedApi;
}

export const NewsfeedNavButton = ({ apiFetchResult }: Props) => {
const [showBadge, setShowBadge] = useState<boolean>(false);
export const NewsfeedNavButton = ({ newsfeedApi }: Props) => {
const [flyoutVisible, setFlyoutVisible] = useState<boolean>(false);
const [newsFetchResult, setNewsFetchResult] = useState<FetchResult | null | void>(null);
const hasNew = useMemo(() => {
return newsFetchResult ? newsFetchResult.hasNew : false;
}, [newsFetchResult]);

useEffect(() => {
function handleStatusChange(fetchResult: FetchResult | void | null) {
if (fetchResult) {
setShowBadge(fetchResult.hasNew);
}
setNewsFetchResult(fetchResult);
}

const subscription = apiFetchResult.subscribe((res) => handleStatusChange(res));
const subscription = newsfeedApi.fetchResults$.subscribe((results) => {
setNewsFetchResult(results);
});
return () => subscription.unsubscribe();
}, [apiFetchResult]);
}, [newsfeedApi]);

function showFlyout() {
setShowBadge(false);
const showFlyout = useCallback(() => {
if (newsFetchResult) {
newsfeedApi.markAsRead(newsFetchResult.feedItems.map((item) => item.hash));
}
setFlyoutVisible(!flyoutVisible);
}
}, [newsfeedApi, newsFetchResult, flyoutVisible]);

return (
<NewsfeedContext.Provider value={{ setFlyoutVisible, newsFetchResult }}>
<Fragment>
<>
<EuiHeaderSectionItemButton
data-test-subj="newsfeed"
aria-controls="keyPadMenu"
aria-expanded={flyoutVisible}
aria-haspopup="true"
aria-label={
showBadge
hasNew
? i18n.translate('newsfeed.headerButton.unreadAriaLabel', {
defaultMessage: 'Newsfeed menu - unread items available',
})
: i18n.translate('newsfeed.headerButton.readAriaLabel', {
defaultMessage: 'Newsfeed menu - all items read',
})
}
notification={showBadge ? true : null}
notification={hasNew ? true : null}
onClick={showFlyout}
>
<EuiIcon type="cheer" size="m" />
</EuiHeaderSectionItemButton>
{flyoutVisible ? <NewsfeedFlyout /> : null}
</Fragment>
</>
</NewsfeedContext.Provider>
);
};
20 changes: 20 additions & 0 deletions src/plugins/newsfeed/public/lib/api.test.mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { storageMock } from './storage.mock';
import { driverMock } from './driver.mock';

export const storageInstanceMock = storageMock.create();
jest.doMock('./storage', () => ({
NewsfeedStorage: jest.fn().mockImplementation(() => storageInstanceMock),
}));

export const driverInstanceMock = driverMock.create();
jest.doMock('./driver', () => ({
NewsfeedApiDriver: jest.fn().mockImplementation(() => driverInstanceMock),
}));
Loading

0 comments on commit ccc1485

Please sign in to comment.