correct animation for load prior dates button
When clicking on the load prior dates button in the dashboard list view, the focus should stay on the button and the button should stay in view. This means the scroll position will jump to the top of the page when the new items are loaded. If intead the window is scrolled to load the past by the scroll wheel or keyboard scrolling buttons, the scrolling position should be maintained and not jump to the top. closes ADMIN-781 test plan: - have lots of items in the past - make sure loading past items behaves as above Change-Id: Ib1e38e9eb487da56d395ae7f0ce3cf747defcb21 Reviewed-on: https://gerrit.instructure.com/144390 Reviewed-by: Mysti Sadler <mysti@instructure.com> Reviewed-by: Ed Schiebel <eschiebel@instructure.com> Tested-by: Jenkins QA-Review: Dan Sasaki <dsasaki@instructure.com> Product-Review: Jon Willesen <jonw+gerrit@instructure.com>
This commit is contained in:
parent
247143529c
commit
028169d345
|
@ -188,6 +188,7 @@ describe('api actions', () => {
|
|||
it('dispatches GETTING_PAST_ITEMS and starts the saga', () => {
|
||||
const mockDispatch = jest.fn();
|
||||
Actions.scrollIntoPast()(mockDispatch, getBasicState);
|
||||
expect(mockDispatch).toHaveBeenCalledWith(Actions.scrollIntoPastAction());
|
||||
expect(mockDispatch).toHaveBeenCalledWith(Actions.gettingPastItems());
|
||||
expect(mockDispatch).toHaveBeenCalledWith(Actions.startLoadingPastSaga());
|
||||
});
|
||||
|
@ -201,6 +202,16 @@ describe('api actions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('loadPastButtonClicked', () => {
|
||||
it('dispatches GETTING_PAST_ITEMS without the scroll into past action', () => {
|
||||
const mockDispatch = jest.fn();
|
||||
Actions.loadPastButtonClicked()(mockDispatch, getBasicState);
|
||||
expect(mockDispatch).not.toHaveBeenCalledWith(Actions.scrollIntoPastAction());
|
||||
expect(mockDispatch).toHaveBeenCalledWith(Actions.gettingPastItems());
|
||||
expect(mockDispatch).toHaveBeenCalledWith(Actions.startLoadingPastSaga());
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadPastUntilNewActivity', () => {
|
||||
it('dispatches getting past items and starts the saga', () => {
|
||||
const mockDispatch = jest.fn();
|
||||
|
|
|
@ -99,9 +99,12 @@ export function loadFutureItems () {
|
|||
};
|
||||
}
|
||||
|
||||
export function scrollIntoPast () {
|
||||
export const scrollIntoPastAction = createAction('SCROLL_INTO_PAST');
|
||||
|
||||
function loadPastItems (byScrolling) {
|
||||
return (dispatch, getState) => {
|
||||
if (getState().loading.allPastItemsLoaded) return;
|
||||
if (byScrolling) dispatch(scrollIntoPastAction());
|
||||
dispatch(gettingPastItems({
|
||||
seekingNewActivity: false,
|
||||
}));
|
||||
|
@ -109,12 +112,20 @@ export function scrollIntoPast () {
|
|||
};
|
||||
}
|
||||
|
||||
export function scrollIntoPast () {
|
||||
return loadPastItems(true);
|
||||
}
|
||||
|
||||
export function loadPastButtonClicked () {
|
||||
return loadPastItems(false);
|
||||
}
|
||||
|
||||
export const loadPastUntilNewActivity = () => (dispatch, getState) => {
|
||||
dispatch(gettingPastItems({
|
||||
seekingNewActivity: true,
|
||||
}));
|
||||
dispatch(startLoadingPastUntilNewActivitySaga());
|
||||
return 'loadPastUntilNewActivity';
|
||||
return 'loadPastUntilNewActivity'; // for testing
|
||||
};
|
||||
|
||||
export function sendFetchRequest (loadingOptions) {
|
||||
|
|
|
@ -29,7 +29,7 @@ import LoadingFutureIndicator from '../LoadingFutureIndicator';
|
|||
import LoadingPastIndicator from '../LoadingPastIndicator';
|
||||
import PlannerEmptyState from '../PlannerEmptyState';
|
||||
import formatMessage from '../../format-message';
|
||||
import {loadFutureItems, scrollIntoPast, loadPastUntilNewActivity, scrollToNewActivity, togglePlannerItemCompletion, updateTodo} from '../../actions';
|
||||
import {loadFutureItems, loadPastButtonClicked, loadPastUntilNewActivity, scrollToNewActivity, togglePlannerItemCompletion, updateTodo} from '../../actions';
|
||||
import {getFirstLoadedMoment} from '../../utilities/dateUtils';
|
||||
import {notifier} from '../../dynamic-ui';
|
||||
|
||||
|
@ -48,7 +48,7 @@ export class PlannerApp extends Component {
|
|||
loadingFuture: bool,
|
||||
allFutureItemsLoaded: bool,
|
||||
firstNewActivityDate: momentObj,
|
||||
scrollIntoPast: func,
|
||||
loadPastButtonClicked: func,
|
||||
loadPastUntilNewActivity: func,
|
||||
scrollToNewActivity: func,
|
||||
loadFutureItems: func,
|
||||
|
@ -148,7 +148,7 @@ export class PlannerApp extends Component {
|
|||
return (
|
||||
<ShowOnFocusButton
|
||||
buttonProps={{
|
||||
onClick: this.props.scrollIntoPast
|
||||
onClick: this.props.loadPastButtonClicked
|
||||
}}
|
||||
>
|
||||
{formatMessage('Load prior dates')}
|
||||
|
@ -221,5 +221,5 @@ const mapStateToProps = (state) => {
|
|||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = {loadFutureItems, scrollIntoPast, loadPastUntilNewActivity, scrollToNewActivity, togglePlannerItemCompletion, updateTodo};
|
||||
const mapDispatchToProps = {loadFutureItems, loadPastButtonClicked, loadPastUntilNewActivity, scrollToNewActivity, togglePlannerItemCompletion, updateTodo};
|
||||
export default notifier(connect(mapStateToProps, mapDispatchToProps)(PlannerApp));
|
||||
|
|
|
@ -214,17 +214,10 @@ describe('action handling', () => {
|
|||
});
|
||||
|
||||
describe('getting past items', () => {
|
||||
it('maintains the scroll position when loading past items', () => {
|
||||
it('records the fixed element on preTrigger', () => {
|
||||
const {manager, animator} = createManagerWithMocks();
|
||||
manager.handleAction(gettingPastItems({seekingNewActivity: false}));
|
||||
manager.handleAction(gotItemsSuccess(
|
||||
[{uniqueId: 'day-1-group-1-item-0'}, {uniqueId: 'day-1-group-0-item-0'}],
|
||||
));
|
||||
registerStandardDays(manager);
|
||||
manager.preTriggerUpdates('fixed-element', 'app');
|
||||
expect(animator.recordFixedElement).toHaveBeenCalledWith('fixed-element');
|
||||
manager.triggerUpdates();
|
||||
expect(animator.maintainViewportPosition).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
// MaintainScrollPosition,
|
||||
MaintainScrollPosition,
|
||||
ScrollToNewActivity,
|
||||
ScrollToLastLoadedNewActivity,
|
||||
|
||||
|
@ -44,14 +44,18 @@ export class AnimationCollection {
|
|||
],
|
||||
animation: ScrollToLastLoadedNewActivity
|
||||
},
|
||||
{
|
||||
expected: [
|
||||
'SCROLL_INTO_PAST',
|
||||
'START_LOADING_PAST_SAGA',
|
||||
'GOT_DAYS_SUCCESS',
|
||||
],
|
||||
animation: MaintainScrollPosition,
|
||||
},
|
||||
|
||||
|
||||
// animations for the future. no, the format doesn't match.
|
||||
|
||||
// [['SCROLL_INTO_PAST', // a new action to distinguish scrolling from "load more" button clicks
|
||||
// 'START_LOADING_PAST_SAGA',
|
||||
// 'GOT_DAYS_SUCCESS',
|
||||
// ], MaintainScrollPosition],
|
||||
|
||||
// [['LOAD_FUTURE_ITEMS',
|
||||
// 'GOT_DAYS_SUCCESS',
|
||||
// ], SetFocusToPriorLoadedItem],
|
||||
|
|
|
@ -18,3 +18,4 @@
|
|||
|
||||
export * from './scroll-to-last-loaded-new-activity';
|
||||
export * from './scroll-to-new-activity';
|
||||
export * from './maintain-scroll-position';
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2018 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas 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 Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Animation from '../animation';
|
||||
|
||||
export class MaintainScrollPosition extends Animation {
|
||||
uiDidUpdate () {
|
||||
this.animator().maintainViewportPosition();
|
||||
}
|
||||
}
|
|
@ -200,12 +200,6 @@ export class DynamicUiManager {
|
|||
if (handler) handler(action);
|
||||
}
|
||||
|
||||
handleGettingPastItems = (action) => {
|
||||
if (!action.payload.seekingNewActivity) {
|
||||
this.animationPlan.noScroll = true;
|
||||
}
|
||||
}
|
||||
|
||||
handleGotDaysSuccess = (action) => {
|
||||
const newDays = action.payload.internalDays;
|
||||
const newItems = daysToItems(newDays);
|
||||
|
|
Loading…
Reference in New Issue