Skip to content

Editable project instructions#1387

Merged
outoftime merged 23 commits intopopcodeorg:masterfrom
ajgreenb:editable-project-instructions
Mar 23, 2018
Merged

Editable project instructions#1387
outoftime merged 23 commits intopopcodeorg:masterfrom
ajgreenb:editable-project-instructions

Conversation

@ajgreenb
Copy link
Copy Markdown
Contributor

@ajgreenb ajgreenb commented Mar 9, 2018

A basic first pass at making the Popcode instructions panel editable from within the app.

To Do

  • Add a Save button that updates the project's instructions state.
  • Add tests! 🙂
  • Add "Markdown supported" blurb at the bottom of InstructionsEditor.
  • See if it's possible to make the cursor: default for the instructions bar when in editing mode.
  • Polish up the styling.

Closes #1311

@outoftime outoftime requested a review from jwang1919 March 9, 2018 18:26
@outoftime
Copy link
Copy Markdown
Contributor

Nice! I think it makes sense for @jwang1919 to do the first review pass on this?

@outoftime outoftime changed the title [WIP] Editable project instructions Editable project instructions Mar 9, 2018
@jwang1919
Copy link
Copy Markdown
Contributor

Will see if I have time later to review later today. I will be out next week for work.

Copy link
Copy Markdown
Contributor

@jwang1919 jwang1919 left a comment

Choose a reason for hiding this comment

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

Some minor change requests and comments on functionality regarding the Hamburger menu and when isEditingInstructions is active.

Comment thread locales/en/translation.json Outdated
"export-gist": "Export Gist",
"export-repo": "Export Repo",
"share-to-classroom": "Share To Classroom",
"add-or-edit-instructions": "Add/Edit Instructions",
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.

I prefer having "Add Instructions" and "Edit Instructions" as two different strings. And have these strings show up whether or not instructions are present in the Popcode project.

Comment thread locales/en/translation.json Outdated
"output": "Output"
"output": "Output",
"instructions": {
"cancel": "Cancel"
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 quite sure why this string is separate from "add-or-edit-instructions".
Couldn't we do...

"instructions": {
    "add": "Add Instructions",
    "edit": "Edit Instructions",
    "cancel": "Cancel"
}

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.

Purposely omitted "Save" because you haven't accomplished that yet, but same deal as with the other strings.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I separated them because add-or-edit-instructions (soon to be split into two separate strings) is in the top-bar, while cancel and save are in the Instructions component. But I don't feel strongly about that separation, so I'm happy to group them all together if you think that would be better.

Comment thread src/css/application.css Outdated
}
}

.instructions-editor-menu {
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.

Suggest to follow BEM naming rules like the rest of the selectors.
.instructions-editor-menu to .instructions-editor__menu

Comment thread src/components/InstructionsEditor.jsx Outdated
export default function InstructionsEditor({instructions, onCancelEditing}) {
return (
<div className="instructions-editor">
<div className="instructions-editor-menu">
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.

Suggest to follow BEM naming rules like the rest of the selectors.
"instructions-editor-menu" to "instructions-editor__menu"

Comment thread src/components/TopBar/HamburgerMenu.jsx Outdated
items.push(
<MenuItem
key="addOrEditInstructions"
onClick={isEditingInstructions ? noop : onStartEditingInstructions}
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.

When isEditingInstructions is true, I think we should change the Menu Item in someway so it's clear that this menu item is active.

My ideas:

  1. Disable the Edit Menu Item
  2. Change the text to "Stop Editing Instructions" (this will cancel and close the instructions)
  3. Change the text to "Save Instructions" (this will save and close the instructions).

@ajgreenb
Copy link
Copy Markdown
Contributor Author

@jwang1919 I think I've addressed all your feedback (on one point I added a comment, but GitHub has collapsed it.)

I decided to opt for idea 1 when isEditingInstructions is true (disabling the menu item.) My reasoning is that

  1. It's not obvious whether saving or canceling should be the behavior of the menu item when isEditingInstructions is true.
  2. Saving and canceling are already afforded by the buttons in the InstructionsEditor and I've heard it's good to only have one way to do something when that's possible.

Let me know what you think!

@ajgreenb
Copy link
Copy Markdown
Contributor Author

ajgreenb commented Mar 11, 2018

Also, I added the ability to save the new instructions using a contenteditable pre. It works fine, but React is a little grudging:

Warning: A component is `contentEditable` and contains `children` managed by React. It is now your responsibility to guarantee that none of those nodes are unexpectedly modified or duplicated. This is probably not intentional.

The contentious "nodes" in this case aren't actually React elements. It's just a String. How do y'all feel about this?

@ajgreenb
Copy link
Copy Markdown
Contributor Author

Added a couple tests—let me know if there are any more you'd like to see!

@outoftime
Copy link
Copy Markdown
Contributor

@ajgreenb what’s the reasoning behind the contenteditable rather than just using a <textarea>?

@ajgreenb
Copy link
Copy Markdown
Contributor Author

I think it gets the job done more simply than using a textarea. With a textarea, I'd have to add more state management for state that is "ephemeral" in a sense. From my understanding, the goal is to to allow users to save and cancel, so I'd need to create separate state elements for both instructions and currentInstructionsBuffer (a better name, hopefully.) When the user saves, currentInstructionsBuffer gets copied to instructions and when the user cancels, it gets discarded.

Using contenteditable, that behavior can be contained within the InstructionsEditor component, which feels less leaky to me.

@outoftime
Copy link
Copy Markdown
Contributor

@ajgreenb so it looks like what you’ve got here is basically an uncontrolled component implementation using a contenteditable element—transient edit state lives purely in the DOM, and then is pulled out of a ref when it’s time to save changes. What you’re describing doing with a <textarea> is a controlled component implementation, which is indeed the preferred approach to forms in React.

However, there’s no reason you couldn’t have an uncontrolled <textarea>—in fact, I think that would be even simpler, since you could avoid messing with state at all, and just set the textarea’s defaultValue to the instructions prop.

WDYT? Definitely possible there is some subtlety I am missing here…

@ajgreenb
Copy link
Copy Markdown
Contributor Author

ajgreenb commented Mar 11, 2018 via email

@pwjablonski
Copy link
Copy Markdown
Contributor

@ajgreenb Checked this out - this is so awesome! Not sure if you addressed this already or have it on the backlog- I found myself wanting to have the "edit instructions" button appear in the instructions pane rather than having to go back to the hamburger menu. That way I could make changes to the markdown => save => edit to fix changes more quickly. I think "add instructions" should still live in the hamburger menu though. Thoughts?

@ajgreenb
Copy link
Copy Markdown
Contributor Author

ajgreenb commented Mar 12, 2018 via email

@pwjablonski
Copy link
Copy Markdown
Contributor

Cool! The upside to the current implementation is that the edit instructions button is less accessible to students under the hamburger menu. But as an instructor much prefer it in the instructions pane.

@outoftime
Copy link
Copy Markdown
Contributor

I think a fairly subtle (maybe only appearing on hover?) edit icon in the instructions would be the move here—not super eye-catching if you’re not looking for it, but easily accessible if you’re looking doing a quick edit-save-edit-save workflow. Anyway, seems like we could follow up with that.

@ajgreenb @jwang1919 please let me know when you’re ready for me to do final review on this—would love to get it released! Very excited to never export a gist just to add an INSTRUCTIONS.md again : D

@ajgreenb
Copy link
Copy Markdown
Contributor Author

Okay, in the interest of getting this out, let's leave the edit icon in the instructions for a small follow-up PR. This is pretty close to ready for final review—hopefully I'll have some time this weekend to put the final touches on it.

@ajgreenb ajgreenb force-pushed the editable-project-instructions branch from 1c2d44f to 3f986c0 Compare March 16, 2018 22:23
@ajgreenb
Copy link
Copy Markdown
Contributor Author

@outoftime I think this is ready for feedback! The styles could use some love, but they don't need to block a review.

@ajgreenb ajgreenb force-pushed the editable-project-instructions branch from 3f986c0 to 459cdf1 Compare March 17, 2018 19:39
Copy link
Copy Markdown
Contributor

@outoftime outoftime left a comment

Choose a reason for hiding this comment

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

@ajgreenb this looks great!! Left a couple of low-level bits of feedback and some thoughts on styles/CSS, but overall this feels very close to the launch tubes!

Comment thread src/components/InstructionsEditor.jsx Outdated
}

_ref(editorElement) {
this.editor = editorElement;
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.

We should underscore-prefix this._editor as well as it is “private” state

Comment thread src/components/TopBar/HamburgerMenu.jsx Outdated
</MenuItem>,
);

if (isExperimental) {
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.

I don’t think there’s any need to release this in experimental mode? Seems pretty ready for prime time to me!

Comment thread src/components/TopBar/HamburgerMenu.jsx Outdated
<MenuItem
isDisabled={isEditingInstructions}
key="addOrEditInstructions"
onClick={isEditingInstructions ? noop : onStartEditingInstructions}
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.

Shouldn’t the isDisabled prop be sufficient to make onClick a noop?

get(this.props, ['currentProject', 'projectKey']),
'instructions',
));
if (!this.props.isEditingInstructions) {
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.

Small thing, but if clicking the instructions bar doesn’t do anything when editing is enabled (which seems sensible), I think we should take away the cursor: pointer in that case too : )

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.

Oh lol this is one of your pending checklist items!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment thread src/actions/ui.js Outdated
'START_EDITING_INSTRUCTIONS',
);

export const stopEditingInstructions = createAction(
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.

I don’t feel strongly about this, but I think cancelEditingInstructions might be a clearer name here—stopEditingInstructions intuitively feels like it would be dispatched any time you are done editing instructions, whether or not you’re going to save your changes.

Comment thread src/css/application.css Outdated

/* postcss-bem-linter: ignore */
& textarea {
height: 100%;
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.

This doesn’t seem to be having the desired effect in Chrome 65—the editor is just a couple lines high. I find absolute positioning with all four sides pinned works wonders in this kind of situation ; )

Comment thread src/css/application.css Outdated
}

.instructions-editor__input {
padding: 1rem 1rem 0;
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.

I think we could do with less padding, and maybe none at all?

Comment thread src/css/application.css Outdated
width: 100%;
padding: 0.5rem;
box-sizing: border-box;
font-family: monospace;
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.

Let’s use Roboto to match the code editors?

Comment thread src/css/application.css Outdated
.instructions-editor__footer {
margin: 1rem;
padding-top: 1rem;
border-top: 1px solid var(--color-light-gray);
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.

I think this text could stand to be a bit smaller.

Comment thread src/components/InstructionsEditor.jsx Outdated
/>
</div>
<div className="instructions-editor__footer">
Styling with Markdown is supported
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.

Let’s make this a link to a suitable Markdown guide?

@ajgreenb ajgreenb force-pushed the editable-project-instructions branch from 936ef74 to 667fd47 Compare March 21, 2018 21:53
@ajgreenb
Copy link
Copy Markdown
Contributor Author

@outoftime I think I addressed all your feedback! Let me know what you think. I'm not in love with styling of the Save and Cancel buttons (lack thereof)—should I spend some time trying to make them look more like the buttons in the top bar?

Copy link
Copy Markdown
Contributor

@outoftime outoftime left a comment

Choose a reason for hiding this comment

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

@ajgreenb awesome!! gonna release this now. a couple of things i think would be good for a follow up:

  • It’d be nice if the edit textarea were focused when it’s first rendered (especially when there are no preexisting instructions, it’s not immediately visually obvious what’s going on)
  • Along the same lines, perhaps a placeholder in the textarea?
  • I meant to suggest we use Hack (the editor font) rather than Roboto (the UI font) in the textarea. My bad!!!
  • I think we should consider renaming the isEnabled prop that MenuItem takes—it’s confusing to have both isEnabled and isDisabled, talking about different things. Maybe isActive instead of isEnabled?

@outoftime outoftime merged commit 310dba8 into popcodeorg:master Mar 23, 2018
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.

5 participants