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

Apply actions #617

Merged
merged 8 commits into from
Nov 14, 2022
Merged

Apply actions #617

merged 8 commits into from
Nov 14, 2022

Conversation

georgefst
Copy link
Contributor

@georgefst georgefst commented Nov 10, 2022

We can now finally build programs again!

There is one bug I've noticed here: the actions list doesn't go back to empty when the selected node is deleted. The problem is that we never get the new selection from the backend. So the frontend still thinks it has a selection, but it doesn't correspond to any node in the tree. This leads to errors in the console if we then try to apply an action, due to a bad request. So the backend API.Prog needs to be modified to contain the Selection. Note that once this is fixed, initial selection here should be set from the backend initial prog, instead of being undefined.

Out of scope for this PR: rendering prompts, showing explanation when options list is empty, setting level (currently hardcoded to expert), logging (we silently show an empty list when available actions call fails, mutateAsync can also error).

};

export const ActionInput = (p: ActionInputProps): JSX.Element => {
const [input, setInput] = useState<string>("");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems a bit boilerplate-y, but AFAICT this is the recommended approach. Eventually we may want to send "is this acceptable input" requests on every keystroke anyway.

onSubmit: (option: string) => void;
};

export const ActionInput = (p: ActionInputProps): JSX.Element => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

A lot of this code is taken from #307. We can probably DRY some of it when we rebase that PR.


type State =
| { state: "ActionList" }
| { state: "Input"; action: InputAction; opts: Options };
Copy link
Contributor Author

@georgefst georgefst Nov 10, 2022

Choose a reason for hiding this comment

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

We'll probably add something like a "PrimitiveInput" state when we hook up #307. Or indeed separate states for each primitive.

type="button"
onClick={(_) => p.onSubmit(input)}
>
<ArrowUturnLeftIcon className="scale-y-[-1] w-6"></ArrowUturnLeftIcon>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This isn't a perfect match for the arrow in the Figma designs. But I couldn't find one at https://heroicons.com/.

Copy link
Contributor

Choose a reason for hiding this comment

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

It is a bit hidden in figma, but it is a (rotated) hero icon
2022-11-10-172706_278x108_scrot

Although this seems to have been removed in v2. See https://v1.heroicons.com/ and search for "reply" (I can't see how to put a direct link)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aha, thanks - I just searched for "arrow"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

...and clearly didn't scour the document thoroughly enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although this seems to have been removed in v2.

Ah, I missed that bit. I'll keep this as is then, until anyone has a better idea.

Copy link
Contributor

Choose a reason for hiding this comment

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

Although this seems to have been removed in v2.

Ah, I missed that bit. I'll keep this as is then, until anyone has a better idea.

Is there any reason not to use the v1 version?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't see anything for "reply" in the react library we're using, so I assume we're already on v2. Though we could easily manually render the old SVG, if we want.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so I assume we're already on v2

Yes: there's "@heroicons/react": "^2.0.13" in package.json.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, "reply" became "arrow-uturn-left" in the 2.0 release:

tailwindlabs/heroicons#750

Unfortunately, "arrow-uturn-left" is rendered substantially differently and looks more appropriate for undo than submit.

We might want to simply drop the icon. I don't think anyone will wonder what to do with an input field. I think the reason we added it in the first place was to distinguish between a placeholder value and a value that the student has typed, but I can't recall for certain. (There are other ways to distinguish between the placeholder and actual input: a greyed out and italicized placeholder font, for example.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, "reply" became "arrow-uturn-left" in the 2.0 release:

tailwindlabs/heroicons#750

Thanks. It is also mentioned in the release notes, located at https://github.com/tailwindlabs/heroicons/releases/tag/v2.0.0

)}
onClick={(_) => onOption(option)}
>
{option.option}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We render global names as unqualified here. See #603.

) : (
<ActionButtonList actions={[]} />
<div className="p-10">
Click something on the canvas to see available actions!
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This text is really a placeholder for something that we've never really discussed. What should we show in the actions panel when there's no selection?

Perhaps we shouldn't show the panel at all, and allow the canvas to naturally extend further right? Though this may be a bit weird since we'd expect that there will "almost always" be a selection during normal use.

Another option is to modify the backend so that selection can never be undefined. We could set initial selection to the first definition (though "first" is pretty arbitrary), and ensure that when the selected node is deleted, the selection always moves somewhere (maybe this part is actually already the case - we don't yet get selection from the backend - see OP).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before this PR, we showed the list with no actions. I changed that here, because a lot more plumbing is now needed to create an actions list. In particular, passing around click handlers for buttons which, in this case, don't even exist.

Copy link
Member

Choose a reason for hiding this comment

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

Our programs will always have at least one hole, so maybe just ensure that something is always selected.

(We couldn't strictly enforce this: the server might be down and not reply with the program, or there could be a bug, etc. But Maybe we just don't worry about those cases and show an empty panel (or an error message).)

Copy link
Member

Choose a reason for hiding this comment

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

We also have plans, if we haven't already implemented it, to record the cursor location in the backend state, so ensuring that something is always selected should be easy enough to do.

Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice to keep the same background even if there are no actions.

Copy link
Member

@dhess dhess Nov 14, 2022

Choose a reason for hiding this comment

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

The implementation in this commit is fine for this PR, but let's definitely fix this up later. At the very least, we can show the action list background and display a "No actions available" message, or something like that. It should be extremely rare for the reasons mentioned above.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Nov 10, 2022

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: b32fa79
Status: ✅  Deploy successful!
Preview URL: https://a581b1db.primer-app.pages.dev
Branch Preview URL: https://georgefst-actions.primer-app.pages.dev

View logs

@georgefst georgefst requested a review from a team November 14, 2022 12:58
action: NoInputAction | InputAction
): { font?: string; text: string } => {
const code = (text: string) => {
return { font: "font-code", text };
Copy link
Member

Choose a reason for hiding this comment

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

I've started using this technique for choosing Tailwind classes, as well, but one drawback is that we lose some static linting checks. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's worth it. Though it is pretty maddening that we lose those checks any time we want to extract some class names in to a variable. We already have this problem all over the place, particularly in ActionButton.

Ideally, TS would be smart enough to treat class names as a separate type to string, and thus ESLint would be able to work out where to apply its checks based on type information. Not that I see that happening.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe the Tailwind people will come up with a solution for this. It has to be a very common issue.

@dhess
Copy link
Member

dhess commented Nov 14, 2022

I think our Chromatic plan has restarted, so I'm going to re-enable the checks, and force-rebuild this PR in Buildkite.

Now that we no longer get this data from the backend, we have the freedom to make this code simpler and more idiomatic.
We also remove some comments about `ActionPanel` in `src/components/ActionButton/ActionButton.stories.tsx`. We've had the button list for a while, including its own stories, so there's nothing remaining to do. We now elide a background in the `ActionButton` stories so that we don't have to worry about it falling out of sync and being misleading as to the appearance of `ActionPanel`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ready to merge Ready to merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants