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

Move Discussion List State into its own class #2150

Merged
merged 35 commits into from
Jun 18, 2020

Conversation

askvortsov1
Copy link
Sponsor Member

@askvortsov1 askvortsov1 commented May 8, 2020

Fixes Part Of #2144

Changes proposed in this pull request:

  • Separate the state of the discussion list out into it's own class (copied over David's code from the mithril/ts rewrite).
  • Always keep an instance of discussion list state active; refresh instead of setting it null

Reviewers should focus on:
Anything I missed?

Confirmed

  • Frontend changes: tested on a local Flarum installation.
  • Backend changes: tests are green (run composer test).

EDIT THIS BEFORE MERGING: #2151 (review)

js/src/forum/ForumApplication.js Outdated Show resolved Hide resolved
@askvortsov1 askvortsov1 changed the title Move Discussion List State into it's own class Move Discussion List State into its own class May 8, 2020
Copy link
Contributor

@franzliedke franzliedke left a comment

Choose a reason for hiding this comment

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

Again, this looks very sensible, but I have a few small remarks and one more high-level discussion point.

js/src/forum/components/DiscussionList.js Outdated Show resolved Hide resolved
js/src/forum/components/DiscussionList.js Outdated Show resolved Hide resolved
js/src/forum/components/IndexPage.js Outdated Show resolved Hide resolved
params.page = { offset };
params.include = params.include.join(',');

return app.store.find('discussions', params);
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 want to pass in the app (or store, or whatever dependencies there are) to the state as well? 🤔 That would make it easier to test them, potentially... 🤔

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Isn't that what's done here? App is globally available

Copy link
Contributor

Choose a reason for hiding this comment

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

That's the opposite of passing it in. We're accessing a global variable, I was suggesting to do dependency injection.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Redux, Meiosis, and most other state management methodologies are based around having a single, global state object. Now, typically the main reason for wanting to avoid globals is that anything, anywhere can modify them, leading to unintended consequences. That's where the main point of these methodologies comes in: the modification of the global state is controlled by the methodology. For instance, with Meiosis, http://meiosis.js.org/tutorial/01-introduction.html

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that concept, and the states and stores being a central place makes sense. I was discussing the method of accessing this central place: by calling on a global name (app.store) or by passing it in to the constructor (dependency injection). The latter not only makes tests easier, but it also allows passing in a different object with the same interface, should the need ever arise (and part of our extensibility philosophy is not knowing what use-cases might come up 😆 ).

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Alright, I see your point here. I'll change it so that if app is needed by the states, it gets passed in on initialization (or should app.store be passed in?)

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

After some more thought, I'm going to side with passing in the entire app. Pretty much every piece of the app could be reused in some way or another.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, thanks. No strong opinion there right now. We can revisit this when we have states everywhere, and see how it looks then / what patterns emerge / whether we want to refactor towards another solution.

Copy link
Contributor

Choose a reason for hiding this comment

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

I definitely like where this is going already.

js/src/forum/utils/DiscussionControls.js Outdated Show resolved Hide resolved
@flarum flarum deleted a comment from franzliedke May 23, 2020
Copy link
Contributor

@franzliedke franzliedke left a comment

Choose a reason for hiding this comment

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

I set out with the intention of approving this one, but found too many things to discuss. Sorry. 🙊

js/src/forum/ForumApplication.js Outdated Show resolved Hide resolved
js/src/forum/components/IndexPage.js Outdated Show resolved Hide resolved
@@ -37,7 +38,7 @@ export default class DiscussionPage extends Page {
// page, then we don't want Mithril to redraw the whole page – if it did,
// then the pane would which would be slow and would cause problems with
// event handlers.
if (app.cache.discussionList) {
if (app.cache.discussionList.hasDiscussions()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like slightly different behavior - "the discussion list being loaded" (i.e. present) is a different condition from "the discussion list having discussions". An empty list can be loaded as well, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this was brought up by David in another place before, so I might be misguided pointing this out again here.

Copy link
Member

Choose a reason for hiding this comment

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

Correct, I brought it up @ #2150 (comment).

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, right. This is the reverse condition, though, and here we now have an unhandled case of "results loaded, but none found"...

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

I don't see any benefit to showing the slideout when there's no discussions?

js/src/forum/components/DiscussionPage.js Outdated Show resolved Hide resolved
js/src/forum/components/IndexPage.js Outdated Show resolved Hide resolved
js/src/forum/state/DiscussionListState.js Show resolved Hide resolved
@askvortsov1 askvortsov1 mentioned this pull request May 28, 2020
2 tasks
@askvortsov1 askvortsov1 merged commit 5c1663d into master Jun 18, 2020
@askvortsov1 askvortsov1 deleted the as/frontend_rewrite_discussion_list_state branch June 18, 2020 23:53
const text = app.translator.trans('core.forum.discussion_list.empty_text');
return <div className="DiscussionList">{Placeholder.component({ text })}</div>;
}

return (
<div className={'DiscussionList' + (this.props.params.q ? ' DiscussionList--searchResults' : '')}>
<div className={'DiscussionList' + (state.isSearchResults() ? ' DiscussionList--searchResults' : '')}>
Copy link
Member

Choose a reason for hiding this comment

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

hasSearchResults? I don't know how something is a search results.

Copy link
Contributor

Choose a reason for hiding this comment

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

isFiltered?

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps searched? isSearching? isSearch? Either works yeah.

@@ -49,6 +50,7 @@ export default class DiscussionPage extends Page {
app.history.push('discussion');

this.bodyClass = 'App--discussion';
this.discussionListClass = DiscussionList;
Copy link
Member

Choose a reason for hiding this comment

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

What does this do?

Copy link
Contributor

Choose a reason for hiding this comment

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

That was a leftover an intermediate step which we decided to revert again. Good catch, removed in master.

@dsevillamartin
Copy link
Member

dsevillamartin commented Jun 19, 2020

Breaking changes:

  • Moved methods & properties from DiscussionList component to DiscussionState class
    • Accessible via app.discussions instead of app.cache.discussionList
    • Has helper methods to encapsulate possible future breaking changes
  • DiscussionList component requires state prop
  • Changed behavior, show discussion list pane if there are discussions in the discussion list
  • Maybe a few more I missed

franzliedke added a commit that referenced this pull request Jun 19, 2020
franzliedke added a commit to flarum/subscriptions that referenced this pull request Jun 26, 2020
askvortsov1 pushed a commit to flarum/pusher that referenced this pull request Mar 11, 2022
askvortsov1 pushed a commit to flarum/sticky that referenced this pull request Mar 11, 2022
askvortsov1 pushed a commit to flarum/subscriptions that referenced this pull request Mar 11, 2022
askvortsov1 pushed a commit to flarum/pusher that referenced this pull request May 10, 2022
askvortsov1 pushed a commit to flarum/sticky that referenced this pull request May 10, 2022
askvortsov1 pushed a commit to flarum/subscriptions that referenced this pull request May 10, 2022
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.

3 participants