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

Don't include default value in url grid state #9190

Merged
merged 3 commits into from
Nov 17, 2020

Conversation

maxime-rainville
Copy link
Contributor

@maxime-rainville maxime-rainville commented Aug 23, 2019

Parent issue

To do (from reviews)

  • Remove isDirty
  • Restore original toArray behaviour and create getChangesArray
  • [ ] Set this->defaults for getState's 2nd argument
  • [ ] Restore default application in GridFieldPaginator line 145
  • Implement GridField_StateProvider (sminnee)
  • Fix manual-page-selection feature and ensure that tests for the underlying issues are included.
  • Consider whether to hoist GridFieldStateAware functionally up from individual components to GridField itslef

@maxime-rainville maxime-rainville changed the title Don't include default value in url grid state Don't include default value in url grid state (WIP) Aug 23, 2019
foreach ($this->data as $name => $datum) {
if ($datum instanceof self && $datum->isDirty()) {
return true;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need the else here, since you've returned already

Copy link
Member

Choose a reason for hiding this comment

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

If datum instance of self but it's not dirty, should you drop down into the second test or simply return clean?

@maxime-rainville
Copy link
Contributor Author

Added some unit test, but I don't quite have them working.

@sminnee
Copy link
Member

sminnee commented Jul 9, 2020

Oh I had no idea that you PRed my bug from last year lol. This would be great for my project; I might see if I have commit rights to open-sausages to rebase this and see if I can fix.

@sminnee sminnee self-assigned this Jul 9, 2020
@sminnee sminnee self-requested a review July 9, 2020 21:57
Copy link
Member

@sminnee sminnee left a comment

Choose a reason for hiding this comment

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

A few changes recommended

src/Forms/GridField/GridState_Data.php Outdated Show resolved Hide resolved
*/
public function initDefaults(array $defaults): void
{
foreach ($defaults as $key => $name) {
Copy link
Member

Choose a reason for hiding this comment

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

$name should be $value, I think?

@@ -46,7 +65,7 @@ public function getData($name, $default = null)
$this->data[$name] = $default;
Copy link
Member

Choose a reason for hiding this comment

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

As suggested here, we should probably set $this->defaults too

src/Forms/GridField/GridState_Data.php Show resolved Hide resolved
foreach ($this->data as $name => $datum) {
if ($datum instanceof self && $datum->isDirty()) {
return true;
} else {
Copy link
Member

Choose a reason for hiding this comment

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

If datum instance of self but it's not dirty, should you drop down into the second test or simply return clean?

src/Forms/GridField/GridFieldPaginator.php Show resolved Hide resolved
src/Forms/GridField/GridState_Data.php Show resolved Hide resolved
* be considered dirty.
* @return bool
*/
public function isDirty(): bool
Copy link
Member

Choose a reason for hiding this comment

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

What's the benefit of using isDirty() instead of relying on the content of toArray to do this work?

@sminnee
Copy link
Member

sminnee commented Aug 10, 2020

One final thing for this: it still suffixes ?gridState-risk-0=%5B%5D on URLs.

@sminnee
Copy link
Member

sminnee commented Aug 10, 2020

OK there is one major issue still remaining on this. In short, 'better buttons' are broken now.

That is because in GridFieldDetailForm_ItemRequest, this is called:

        $data = $state->getData();
        $paginator = $data->getData('GridFieldPaginator');
        if (!$paginator) {
            return false;
        }

This call doesn't trigger the generation of default values for GridFieldPaginator.

@sminnee
Copy link
Member

sminnee commented Aug 10, 2020

Probably the best bet here is yet another GridField component interface, GridField_StateProvider, with an initDefaultState method. It can be called before GridState::getData() returns a value.

Keen to get feedback on that, as adding another interface is non-trivial, but it's an opt-in feature for component providers.

@sminnee
Copy link
Member

sminnee commented Aug 12, 2020

@silverstripe/core-team any feedback on adding GridField_StateProvider as another GridField component interface, to let components define default state?

@robbieaverill
Copy link
Contributor

Sounds like a decent idea to me. I'd be keen to hear @unclecheese's thoughts, as someone who probably has a good idea of where GridField is likely to go in React land

@sminnee
Copy link
Member

sminnee commented Aug 12, 2020

Can I challenge the idea that GridField will go anywhere in React land? I imagine that starting from scratch with a grid-like control would be 100 times easier and you'd break everyone's plug-one regardless.

Perhaps Aaron has thoughts on that, though.

@ScopeyNZ
Copy link
Contributor

Sounds good as long as it's GridField\StateProvider 😉

@sminnee
Copy link
Member

sminnee commented Aug 12, 2020

Sounds good as long as it's GridField\StateProvider 😉

Is it worth being inconsistent with the rest of them to do that, though? Happy to go with consensus but consistency is what prompted my use of underscore.

@unclecheese
Copy link

Been a while since I've thought about this issue, but to my recollection, all the research on react gridfield was based on the assumption that it would be a parallel api to the traditional gridfield that devs could opt into (or more likely, out of).

It does mean a rewrite of components, but not as much as you'd think, and some may not even be affected. A lot of those plugins never touch the UI and only do backend work which affords more room for backward compatibility.

@robbieaverill
Copy link
Contributor

I agree with @sminnee, consistency is more important.

We could create new namespaced interfaces and extend them from the old ones to prevent semver violations, but that could be done separately to this PR.

@sminnee
Copy link
Member

sminnee commented Aug 12, 2020

OK I'll take "implement GridField_StateProvider" as an action and we can review in more detail when I have some code.

@sminnee sminnee changed the title Don't include default value in url grid state (WIP) [WIP] Don't include default value in url grid state Aug 12, 2020
@sminnee
Copy link
Member

sminnee commented Aug 13, 2020

@maxime-rainville with the new initDefaultState() method, the changes you made introducing getXXXState() methods isn't really necessary any more. I'm inclined to revert these changes and re-test, for two reasons:

  • Reduce the scope of the change to only the necessary stuff
  • Confirm that these changes aren't inadvertently papering over some required changes due to an API accidentally being changed.

Happy to get your feedback on that idea, though...

@sminnee sminnee changed the title [WIP] Don't include default value in url grid state Don't include default value in url grid state Aug 16, 2020
src/Forms/GridField/GridState_Data.php Outdated Show resolved Hide resolved
src/Forms/GridField/GridField.php Outdated Show resolved Hide resolved
Copy link
Contributor Author

@maxime-rainville maxime-rainville left a comment

Choose a reason for hiding this comment

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

Humm ... look likes pagination is not working any more. When you try to punch in a page number to jump to, it won't let you do it if you're on page no 1. You can still use the arrows to navigate.

If you switch to a different page using the arrow, than it will allow you to jump to a specific page.

https://youtu.be/jqVGO22j4IA

I'll have a look. See if I can fix it.

@sminnee sminnee changed the title Don't include default value in url grid state [WIP] Don't include default value in url grid state Aug 17, 2020
@maxime-rainville
Copy link
Contributor Author

Last commit should fix it. json_encode([]) outputs [] by default. We want it to output {} otherwise the front end gets confused and treats the empty state has an array instead of as an object.

I'll do some more manual testing tomorrow, to make sure everything works.

@sminnee
Copy link
Member

sminnee commented Aug 17, 2020

Cheers; I might patch this PR into an internal production project as well to get some further testing. Given the number of "oops, found one more bug" iterations we've had it could use some more in-app testing before merge I think ;-)

@sminnee
Copy link
Member

sminnee commented Aug 18, 2020

Nice find, Max! My initial testing confirms that this is working.

I've noticed a related bug that is pre-existing but might be worth looking into as part of this PR.

  • Open a modeladmin
  • Go to page 2
  • Open a detail record
  • Go back to the list by clicking the top menu

Result: The get param says page 2, but page 1 is shown

@sminnee
Copy link
Member

sminnee commented Aug 18, 2020

OK I've had a look at this bug. It's a bit odd — there are 4 components that each take responsibility for fetching grid state from the URL, rather than GridField doing this for us...

@sminnee
Copy link
Member

sminnee commented Aug 18, 2020

It looks like this was introduced by a couple of key commits:

  • cc71289 Betterbuttons was imported into the framework, which first required that gridstate was passed in a get var
  • b3093b7 GridFieldStateManager was created to allow nested gridfields and provide some abstraction for this

@unclecheese was the leader of both of these so would be good to get his view on whether the GridFieldStateAware should be hoisted up to the new GridField::initState() method that this PR creates.

A few things that need to be considered:

  • Use the history API to populate state in the URL when it changes
  • Check that going from page 4 to page 1 clears the grid state

@sminnee
Copy link
Member

sminnee commented Aug 18, 2020

I've flagged 3 tickets above that might also be fixed by this.

@maxime-rainville
Copy link
Contributor Author

Yeah ... there's a few things that are weird in the better-button/gridifield interaction.

Did some testing on this PR this afternoon. It doesn't introduce any new weirdness and makes the URLs definitively better. So my instinct would be to merge it as is and look at the other issues independently.

@maxime-rainville maxime-rainville changed the title [WIP] Don't include default value in url grid state Don't include default value in url grid state Aug 18, 2020
@maxime-rainville
Copy link
Contributor Author

I've developed a fix for a related issue while working on this one silverstripe/silverstripe-admin#1103

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.

GridField: Exclude default values from persisted state (esp in URL)
7 participants