Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(preview-sidebar): fix preview versions behavior #3203

Merged
merged 6 commits into from Aug 10, 2023

Conversation

Machoper
Copy link
Contributor

@Machoper Machoper commented Jan 4, 2023

Overview

This PR is built on #3095, so I'm borrowing the same description with a few small changes:

Currently, if a version is selected in the Preview sidebar and the Preview sidebar is closed, it reverts to the latest version of the document.

This creates problems for small screens where the Preview sidebar is moved to the bottom and becomes a vertical sliding drawer. When an old version is selected and the drawer is closed, a user cannot view the old version because it reverts to the latest version of the document.

This PR fixes the issue by adjusting the logic to reset the current version only when the user navigates away from version history.

Note this would also affect the regular desktop experience. If a user closes the Preview Sidebar after selecting the version, it would remain on that version instead of changing back to the latest version (approved by relevant stakeholders). This would not affect the current behavior when switching to other sidebars like "Details" or "Metadata".

Demo

Before

small screen

before_small

large screen

before_large

After

small screen

after_small

large screen

after_large

@Machoper Machoper requested review from a team as code owners January 4, 2023 18:35
@Machoper Machoper force-pushed the fix-preview-versions-behavior branch from d6fe805 to 03d3117 Compare January 4, 2023 22:57
tjuanitas
tjuanitas previously approved these changes Aug 5, 2023
Copy link
Contributor

@tjuanitas tjuanitas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good from my testing

one thing to note: there seems to be an existing bug where if you go to an older file version and click the Next/Previous buttons, the version number of the previous file is still in the URL for the new file. but this is not a regression from this change

src/constants.js Outdated
@@ -396,6 +396,9 @@ export const SIDEBAR_VIEW_METADATA: 'metadata' = 'metadata';
export const SIDEBAR_VIEW_ACTIVITY: 'activity' = 'activity';
export const SIDEBAR_VIEW_VERSIONS: 'versions' = 'versions';

/* ------------------ Sidebar Path ---------------------- */
export const SIDEBAR_PATH_VERSIONS = '/:sidebar(activity|details)/versions/:versionId?';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we store this in a module within the content-sidebar directory?

}

getVersionsMatchPath = (location: Location) => {
const pathname = getProp(location, 'pathname', '');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need getProp here? I think location is always defined.

@@ -111,8 +112,18 @@ class Sidebar extends React.Component<Props, State> {
this.setForcedByLocation();
this.setState({ isDirty: true });
}

// Reset the current version id if the wrapping versions route is no longer active
if (onVersionChange && this.getVersionsMatchPath(prevLocation) && !this.getVersionsMatchPath(location)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ContentSidebar already does a lot. I'm wondering if this would be better suited to live in SidebarPanels, since that's where we manage all of this already.

expect(onVersionChange).not.toBeCalled();

wrapper.setProps({ location: { pathname: '/details' } });
expect(onVersionChange).lastCalledWith(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would .toBeCalledWith(null) work here or is the number and order of calls important?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's from an earlier attempt to run a few assertions in series and I forgot to update it afterwards.
I just rearranged the tests and change it to .toBeCalledWith(null).

const onVersionChange = jest.fn();
const wrapper = getWrapper({ location: { pathname: '/activity' }, onVersionChange });

wrapper.setProps({ location: { pathname: '/activity/versions/123' }, isOpen: true });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add assertions for /activity/versions and /details/versions, as well?

isOpen
{...rest}
/>,
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, what was the reason for this change?

Copy link
Contributor Author

@Machoper Machoper Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setProps() can only be called on the root, which was MemoryRouter in the previous setup. So, this is more of a workaround to call setProps() on SidebarPanels instead and trigger componentDidUpdate().

@@ -102,6 +105,21 @@ class SidebarPanels extends React.Component<Props, State> {
this.setState({ isInitialized: true });
}

componentDidUpdate(prevProps: Props): void {
const { location, onVersionChange }: Props = this.props;
const { location: prevLocation }: Props = prevProps;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the : Props explicit types needed here? I would think the type would be inferred from the variables.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, they are not needed. I copy-pasted from Sidebar.js. Deleted!

Copy link
Contributor

@jstoffan jstoffan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job. 👍

Copy link
Contributor

@tjuanitas tjuanitas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@@ -144,4 +149,38 @@ describe('elements/content-sidebar/SidebarPanels', () => {
expect(instance.versionsSidebar.current.refresh).toHaveBeenCalledWith();
});
});

describe('componentDidUpdate', () => {
const onVersionChange = jest.fn();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to confirm, the call counts are reset between the tests right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. We have clearMocks: true in jest.config.js

@mergify mergify bot merged commit d940782 into box:master Aug 10, 2023
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants