Commit 725de03c authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Delete PendingUpdatesButton and remove references to pending_updates_notification ff

parent 1b9e8c7a
......@@ -11,7 +11,6 @@ import { useSidebarStore } from '../store';
import NotebookFilters from './NotebookFilters';
import NotebookResultCount from './NotebookResultCount';
import PaginatedThreadList from './PaginatedThreadList';
import PendingUpdatesButton from './PendingUpdatesButton';
import PendingUpdatesNotification from './PendingUpdatesNotification';
import { useRootThread } from './hooks/use-root-thread';
......@@ -34,9 +33,6 @@ function NotebookView({ loadAnnotationsService, streamer }: NotebookViewProps) {
const hasAppliedFilter = store.hasAppliedFilter();
const isLoading = store.isLoading();
const resultCount = store.annotationResultCount();
const pendingUpdatesNotification = store.isFeatureEnabled(
'pending_updates_notification',
);
const { rootThread } = useRootThread();
......@@ -143,14 +139,13 @@ function NotebookView({ loadAnnotationsService, streamer }: NotebookViewProps) {
'right-[4rem]',
)}
>
{pendingUpdatesNotification && <PendingUpdatesNotification />}
<PendingUpdatesNotification />
</div>
</div>
<div className="justify-self-start">
<NotebookFilters />
</div>
<div className="flex items-center lg:justify-self-end text-md font-medium">
{!pendingUpdatesNotification && <PendingUpdatesButton />}
<NotebookResultCount
forcedVisibleCount={forcedVisibleCount}
isFiltered={hasAppliedFilter}
......
import { IconButton, RefreshIcon } from '@hypothesis/frontend-shared';
import { useCallback, useEffect } from 'preact/hooks';
import { useShortcut } from '../../shared/shortcut';
import { withServices } from '../service-context';
import type { AnalyticsService } from '../services/analytics';
import type { StreamerService } from '../services/streamer';
import type { ToastMessengerService } from '../services/toast-messenger';
import { useSidebarStore } from '../store';
export type PendingUpdatesButtonProps = {
// Injected
analytics: AnalyticsService;
streamer: StreamerService;
toastMessenger: ToastMessengerService;
};
function PendingUpdatesButton({
analytics,
streamer,
toastMessenger,
}: PendingUpdatesButtonProps) {
const store = useSidebarStore();
const pendingUpdateCount = store.pendingUpdateCount();
const hasPendingUpdates = store.hasPendingUpdates();
const applyPendingUpdates = useCallback(() => {
streamer.applyPendingUpdates();
analytics.trackEvent('client.realtime.apply_updates');
}, [analytics, streamer]);
useShortcut('l', () => hasPendingUpdates && applyPendingUpdates());
useEffect(() => {
if (hasPendingUpdates) {
toastMessenger.notice('New annotations are available.', {
visuallyHidden: true,
});
toastMessenger.notice('Press "l" to load new annotations.', {
visuallyHidden: true,
delayed: true,
});
}
}, [hasPendingUpdates, toastMessenger]);
if (!hasPendingUpdates) {
return null;
}
return (
<IconButton
icon={RefreshIcon}
onClick={applyPendingUpdates}
size="xs"
variant="primary"
title={`Show ${pendingUpdateCount} new/updated ${
pendingUpdateCount === 1 ? 'annotation' : 'annotations'
}`}
/>
);
}
export default withServices(PendingUpdatesButton, [
'analytics',
'streamer',
'toastMessenger',
]);
......@@ -39,9 +39,6 @@ function SidebarView({
const focusedGroupId = store.focusedGroupId();
const isLoading = store.isLoading();
const isLoggedIn = store.isLoggedIn();
const pendingUpdatesNotification = store.isFeatureEnabled(
'pending_updates_notification',
);
const linkedAnnotationId = store.directLinkedAnnotationId();
const linkedAnnotation = linkedAnnotationId
......@@ -133,7 +130,6 @@ function SidebarView({
return (
<div className="relative">
<h2 className="sr-only">Annotations</h2>
{pendingUpdatesNotification && (
<div
className={classnames(
'fixed z-1',
......@@ -145,7 +141,6 @@ function SidebarView({
>
<PendingUpdatesNotification />
</div>
)}
{showFilterControls && <FilterControls withCardContainer />}
<LoginPromptPanel onLogin={onLogin} onSignUp={onSignUp} />
{hasDirectLinkedAnnotationError && (
......
......@@ -8,7 +8,6 @@ import { withServices } from '../service-context';
import type { FrameSyncService } from '../services/frame-sync';
import { useSidebarStore } from '../store';
import GroupList from './GroupList';
import PendingUpdatesButton from './PendingUpdatesButton';
import SortMenu from './SortMenu';
import TopBarToggleButton from './TopBarToggleButton';
import UserMenu from './UserMenu';
......@@ -50,9 +49,6 @@ function TopBar({
const store = useSidebarStore();
const isLoggedIn = store.isLoggedIn();
const hasFetchedProfile = store.hasFetchedProfile();
const pendingUpdatesNotification = store.isFeatureEnabled(
'pending_updates_notification',
);
const toggleSharePanel = () => {
store.toggleSidebarPanel('shareGroupAnnotations');
......@@ -96,7 +92,6 @@ function TopBar({
<div className="grow flex items-center justify-end">
{isSidebar && (
<>
{!pendingUpdatesNotification && <PendingUpdatesButton />}
<SearchIconButton />
<SortMenu />
<TopBarToggleButton
......
......@@ -36,7 +36,6 @@ describe('NotebookView', () => {
annotationResultCount: sinon.stub().returns(0),
setSortKey: sinon.stub(),
hasFetchedProfile: sinon.stub().returns(true),
isFeatureEnabled: sinon.stub().returns(false),
};
fakeStreamer = {
......@@ -152,22 +151,6 @@ describe('NotebookView', () => {
assert.isTrue(wrapper.find('NotebookFilters').exists());
});
[true, false].forEach(pendingUpdatesNotificationEnabled => {
it('shows expected pending updates component', () => {
fakeStore.isFeatureEnabled.returns(pendingUpdatesNotificationEnabled);
const wrapper = createComponent();
assert.equal(
wrapper.exists('PendingUpdatesNotification'),
pendingUpdatesNotificationEnabled,
);
assert.equal(
wrapper.exists('PendingUpdatesButton'),
!pendingUpdatesNotificationEnabled,
);
});
});
describe('pagination', () => {
it('passes the current pagination page to `PaginatedThreadList`', () => {
const wrapper = createComponent();
......
import { mount } from 'enzyme';
import PendingUpdatesButton, { $imports } from '../PendingUpdatesButton';
describe('PendingUpdatesButton', () => {
let fakeToastMessenger;
let fakeStore;
let fakeStreamer;
let fakeAnalytics;
beforeEach(() => {
fakeToastMessenger = {
notice: sinon.stub(),
};
fakeStore = {
pendingUpdateCount: sinon.stub().returns(0),
hasPendingUpdates: sinon.stub().returns(true),
};
fakeStreamer = {
applyPendingUpdates: sinon.stub(),
};
fakeAnalytics = {
trackEvent: sinon.stub(),
};
$imports.$mock({
'../store': { useSidebarStore: () => fakeStore },
});
});
afterEach(() => {
$imports.$restore();
});
const createButton = count => {
fakeStore.pendingUpdateCount.returns(count);
fakeStore.hasPendingUpdates.returns(count > 0);
return mount(
<PendingUpdatesButton
streamer={fakeStreamer}
toastMessenger={fakeToastMessenger}
analytics={fakeAnalytics}
/>,
);
};
it('shows an empty wrapper when there are no pending updates', () => {
const wrapper = createButton(0);
assert.isFalse(wrapper.find('IconButton').exists());
assert.notCalled(fakeToastMessenger.notice);
});
[1, 10, 50].forEach(pendingUpdateCount => {
it('shows the pending update count', () => {
const wrapper = createButton(pendingUpdateCount);
assert.isTrue(wrapper.find('IconButton').exists());
assert.calledWith(
fakeToastMessenger.notice,
'New annotations are available.',
{
visuallyHidden: true,
},
);
assert.calledWith(
fakeToastMessenger.notice,
'Press "l" to load new annotations.',
{
visuallyHidden: true,
delayed: true,
},
);
});
});
it('shows the pending update count', () => {
const wrapper = createButton(1);
assert.isTrue(wrapper.find('IconButton').exists());
});
it('applies updates when clicked', () => {
const wrapper = createButton(1);
const applyBtn = wrapper.find('IconButton');
applyBtn.props().onClick();
assert.called(fakeStreamer.applyPendingUpdates);
assert.calledWith(
fakeAnalytics.trackEvent,
'client.realtime.apply_updates',
);
});
it('applies updates when keyboard shortcut is pressed', () => {
createButton(1);
document.body.dispatchEvent(
new KeyboardEvent('keydown', {
key: 'l',
bubbles: true,
}),
);
assert.called(fakeStreamer.applyPendingUpdates);
assert.calledWith(
fakeAnalytics.trackEvent,
'client.realtime.apply_updates',
);
});
});
......@@ -59,7 +59,6 @@ describe('SidebarView', () => {
profile: sinon.stub().returns({ userid: null }),
searchUris: sinon.stub().returns([]),
toggleFocusMode: sinon.stub(),
isFeatureEnabled: sinon.stub().returns(false),
};
fakeTabsUtil = {
......@@ -277,19 +276,6 @@ describe('SidebarView', () => {
});
});
context('when pending_updates_notification is enabled', () => {
[true, false].forEach(pendingUpdatesNotificationEnabled => {
it('shows PendingUpdatesNotification', () => {
fakeStore.isFeatureEnabled.returns(pendingUpdatesNotificationEnabled);
const wrapper = createComponent();
assert.equal(
wrapper.exists('PendingUpdatesNotification'),
pendingUpdatesNotificationEnabled,
);
});
});
});
it(
'should pass a11y checks',
checkAccessibility({
......
......@@ -19,7 +19,6 @@ describe('TopBar', () => {
isLoggedIn: sinon.stub().returns(false),
isSidebarPanelOpen: sinon.stub().returns(false),
toggleSidebarPanel: sinon.stub(),
isFeatureEnabled: sinon.stub().returns(true),
};
fakeFrameSync = {
......@@ -194,17 +193,6 @@ describe('TopBar', () => {
});
});
[true, false].forEach(pendingUpdatesNotificationEnabled => {
it('renders PendingUpdatesButton when pending_updates_notification feature is not enabled', () => {
fakeStore.isFeatureEnabled.returns(pendingUpdatesNotificationEnabled);
const wrapper = createTopBar();
assert.equal(
wrapper.exists('PendingUpdatesButton'),
!pendingUpdatesNotificationEnabled,
);
});
});
it(
'should pass a11y checks',
checkAccessibility([
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment