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
Refactor SaveBar with hide Show button #43684
Conversation
creativeCommonsLicense: this.props.initialLessonData | ||
.creativeCommonsLicense, | ||
creativeCommonsLicense: | ||
this.props.initialLessonData.creativeCommonsLicense || '', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was to fix a warning about the select having an empty value
pathForShowButton: PropTypes.string | ||
}; | ||
|
||
SaveBar.defaultProps = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL about defaultProps! I read about these and I have a couple of questions/ideas for best practices:
- is there any reason to include
error
andhandleView
whose defaults areundefined
? this seems like it would have no effect. if not I'd suggest removing those lines. - propType resolution happens after defaultProps are applied, so props with an entry in defaultProps could be able to be marked as
isRequired
. I think our current practice is to use isRequired whenever possible, but others feel free to correct me here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good questions. I suppose we should norm on best practices, and it sounds like there already is a norm for isRequired
. I am accustomed to (a) only marking isRequired
for props that folks using the component need to provide, and then (b) providing defaults for all not-required props so that people can easily tell what's happening by default. I suppose I don't feel strongly about (b), but feel more strongly about (a): it feels like marking isRequired
for all of these, but then only having an error if a person doesn't provide handleSave, could be confusing. Then again, we have tests that pretty clearly show that, and it sounds like that's a different norm from what we're already doing.
UPDATE: I did some research, and perhaps I'm not pulling (a) out of thin air: Someone on this Stack Overflow post writes, "The way it's usually thought of is the component is guaranteed to render without errors if all the required props are supplied. The props that are not required would only enhance the component with additional functionality."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice, I like that better - it does seem more useful that the isRequired props would only be the ones the caller has to provide. let's go with that!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davidsbailey, are you thinking I should remove the undefined
defaultProps? I'm good to do so––curious to hear what you think.
lastSaved, | ||
pathForShowButton | ||
}) { | ||
const isShowButtonRendered = handleView || pathForShowButton !== '/'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks like it might be going against the premise of "no special values". is there a case where this '/' is getting used? I would expect there not to be, since my understanding of the new business logic is that we don't want to use this value if it is missing, and it looks like the programming expressions editor uses its own handleView method.
If that's correct, I would suggest letting pathForShowButton
be undefined
by default, and then just testing || pathForShowButton
or similar here.
if that all works... then you could also get rid of handleView and just have the ProgrammingExpressionEditor pass in pathForShowButton: '/'
, if that's the logic we still want there.
maybe @bethanyaconnor you can confirm what the best behavior is for the show button in ProgrammingExpressionEditor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that's a great call –– also, then if people want a show button but don't want it to go anywhere, they can use '/' for the path to get it to show up. Bethany, would still love to hear your ideas!
UPDATE: The "/" for the path causes the redirect to go to the home page since we aren't using linkWithQueryParams, so the change is quite good. I realized that navigateToHref(pathForShowButton)
where pathForShowButton
might be undefined
is a little wonky, even if onClick
shouldn't run in that case because the button won't be visible. Still, I made an anonymous function to fall back to. Could also make the button disabled if it's not visible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an interesting situation, where we're hiding the button but we're still trying to handle what happens if something calls the click handler anyway. I don't have a great example to offer, other than that we have typically preferred conditional rendering and so this problem doesn't come up. there's a lack of clear advice on the internet about when to use conditional rendering, but I would say our current most common practice is to prefer conditional rendering, unless you are optimizing for an expensive component that changes visibility a lot in which case using css to hide the component is cheaper.
I don't feel super strongly about preferring conditional rendering over css visibility per se, but if it would make it clearer that we could never hit the click handler when the component is hidden then it could be a good option in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you do want to keep using css visibility then I would argue for NOT taking extra steps to handle the click in the case where the element is hidden -- if we think that hiding the css element doesn't really convince us that its not clickable then I would take that to mean that conditional rendering would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call––I was using visibility: hidden
to be sure I wasn't causing unintentional styling changes. I've changed it to render an empty <span \>
which is perhaps clunky, but (a) doesn't render a button if we don't need it, and (b) avoids the other buttons moving around.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI for ProgrammingExpressionEditor
the /
path is being replaced in https://github.com/code-dot-org/code-dot-org/pull/43659/files, which I hope to merge today
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent! I didn't want to change anything in that file because I knew you were updating it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call––I was using visibility: hidden to be sure I wasn't causing unintentional styling changes. I've changed it to render an empty <span > which is perhaps clunky, but (a) doesn't render a button if we don't need it, and (b) avoids the other buttons moving around.
Ahh, yes, that is a very good reason to use css visibility which I had not considered. empty span sounds like a winner to me. thanks for all the thoughtful conversation here!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM after considering the follow-up on the button visibility.
Refactor SaveBar with hide Show button
Hides the "show" button on the Lesson Edit page if there's no lesson plan. On the Lesson Edit side, I checked for a lesson plan inside initialLessonData––this doesn't ensure the path actually works.
On the SaveBar side, I did the following:
I updated CourseEditor, LessonEditor, and UnitEditor to take into account these changes. I didn't change ProgrammingExpressionsEditor.
I suppose it's possible someone will want to show the button even if they don't pass in a function or a path. Do we want to allow more control to show/hide it?
Links
Testing story
I tested manually and added/refactored some unit tests.
Deployment strategy
Follow-up work
Privacy
Security
Caching
PR Checklist: