Skip to content

fix(contentpicker): correctly clear old item when maxSelectable=1 and parent reloaded#1706

Open
cgrdavies wants to merge 6 commits into
box:masterfrom
cgrdavies:fix-single-select-multiple-selection-bug
Open

fix(contentpicker): correctly clear old item when maxSelectable=1 and parent reloaded#1706
cgrdavies wants to merge 6 commits into
box:masterfrom
cgrdavies:fix-single-select-multiple-selection-bug

Conversation

@cgrdavies
Copy link
Copy Markdown

This change fixes #1705, which was preventing the prior selection from being properly cleared when the content picker was in single file selection mode and the folder enclosing the previously selected item had been reloaded before changing the selection.

Problem

Because the content picker relied on a mutating a reference to the previously selected item, when the items were reloaded from the server, that reference was no longer valid and the item within currentCollection was not updated.

Solution

Scan the currentCollection for an item that matches the prior selection based on the item's id. If found, remove the selected keyword from that item directly.

@cgrdavies cgrdavies requested review from a team as code owners November 5, 2019 17:35
@boxcla
Copy link
Copy Markdown

boxcla commented Nov 5, 2019

Hi @cgrdavies, thanks for the pull request. Before we can merge it, we need you to sign our Contributor License Agreement. You can do so electronically here: http://opensource.box.com/cla

Once you have signed, just add a comment to this pull request saying, "CLA signed". Thanks!

@cgrdavies
Copy link
Copy Markdown
Author

cgrdavies commented Nov 5, 2019

CLA signed

const priorSelection = selected[priorSelectionIndex];
const matchingItem = items.find(potentialMatch => potentialMatch.id === priorSelection.id);

if (matchingItem) delete matchingItem.selected;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if (matchingItem) {
...
}

@priyajeet
Copy link
Copy Markdown
Contributor

BTW there is a possibility this issue applies to multi-selection. Trying to see when it broke, likely when we switched to paging.

@priyajeet
Copy link
Copy Markdown
Contributor

In order to properly fix this, and frankly make it less confusing, we may have to get rid of the reference mutations and keep selected isolated from currentCollection.items. I am trying a few things, will report back.

@priyajeet
Copy link
Copy Markdown
Contributor

priyajeet commented Nov 5, 2019

Roughly something along these lines might be better https://github.com/box/box-ui-elements/pull/1709/files. We still can use a map to prevent multiple find()s so that its a O(1) lookup or we can just keep the find()s as in practice selected will always be a small-ish array. Do you want to update your PR following this appraoch?

@cgrdavies
Copy link
Copy Markdown
Author

cgrdavies commented Nov 6, 2019

Roughly something along these lines might be better https://github.com/box/box-ui-elements/pull/1709/files. We still can use a map to prevent multiple find()s so that its a O(1) lookup or we can just keep the find()s as in practice selected will always be a small-ish array. Do you want to update your PR following this appraoch?

@priyajeet Thanks for taking a look at this! I agree that removing the reference mutations is a better approach, but I was originally hesitant to do so given the magnitude of the change that would be required. With your outline though I'm happy to update this PR.

@cgrdavies cgrdavies force-pushed the fix-single-select-multiple-selection-bug branch from 6b4c481 to 4c32a45 Compare November 7, 2019 19:46
@cgrdavies
Copy link
Copy Markdown
Author

@priyajeet: should be all set for another look on this!

Copy link
Copy Markdown
Contributor

@priyajeet priyajeet left a comment

Choose a reason for hiding this comment

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

lgtm mostly, some minor stylistic comments. Thanks for pulling this in.

* @author Box
*/

export function containsItem(item: BoxItem) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you move these exports to the bottom. It's our new convention. So

function foo() {}

function bar() {}

export { foo, bar };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also if you have time can you add a couple of unit tests for this file for these new functions

return (selected: BoxItem) => selected.id === id && selected.type === type;
}

export function isSelected(item: BoxItem, selectedItems: Array<BoxItem>) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For both of these functions probably should add a return type, so : boolean here and : (item: BoxItem) => boolean above

const { name = '', selected = false } = rowData;
const { name = '' } = rowData;
const Component = isRadio ? RadioButton : Checkbox;
const isSelected = !!isRowSelected(rowData, selected);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

!! is probably unnecessary since the function returns a boolean

Comment thread src/elements/content-picker/ItemList.js Outdated
const { selected, type } = items[index];
const isSelectable = isRowSelectable(selectableType, extensionsWhitelist, hasHitSelectionLimit, items[index]);
const { type } = items[index];
const isSelected = !!isRowSelected(items[index], selected);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

!! not needed here either

Comment thread src/elements/content-picker/ItemList.js Outdated
index: number,
rowData: BoxItem,
}) => {
const isSelected = !!isRowSelected(rowData, selected);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

likewise

const cacheKey = this.api.getAPI(type).getCacheKey(id);
// if shared link already exists, update the collection in state
this.updateItemInCollection(item);
if (item.selected && item !== selected[cacheKey]) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually removing this part may cause a problem, since the item object in question has changed, it needs to be the one that is returned, so one will have to change the choose() function to return items from the updated collection and not whats inside selected.

Further simplification would be to make selected array just an array of IDs and Types, since thats what is really used everywhere to check if a row is selected or not. So that when choose button is pressed, then we build the returned array with latest item objects.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Alternatively, updateItemInCollection() function can be changed to also update selected array with the updated item.

@priyajeet
Copy link
Copy Markdown
Contributor

BTW, if you dont have time to make more changes, we can take over the PR...

@cgrdavies cgrdavies force-pushed the fix-single-select-multiple-selection-bug branch from f82b52d to 5a28b52 Compare November 13, 2019 19:20
@cgrdavies
Copy link
Copy Markdown
Author

@priyajeet should be all set from a code perspective. I changed updateItemInCollection to replace the matching item in the selected array.

I do have a failing test though that seems unrelated, and I can't immediately figure out what's going on. Any chance someone could take a look at that? I don't have enough overall context to be able to fix it expediently.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@sahiga
Copy link
Copy Markdown
Contributor

sahiga commented Mar 31, 2020

Hey @cgrdavies, sorry we've taken so long to merge this PR. I'm looking into the failing tests right now. Is it okay with you if I add commits to your PR? Also, could you sign the new CLA? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Folder Picker maxSelectable: 1 gives the appearance of allowing multiple selections

5 participants