code.pyret.org
code.pyret.org copied to clipboard
improve publish button
Right now the publish interface looks like this:

- I feel like in 2021, we've gotten accustomed to the default action being "Copy" (as in, copy the link to clipboard).
- The "Update" button leaves me unsure: if I don't click it, is my current program published or not? I have to think because it's the default action.
- To really understand what's going on, I have to read text. OMG.
- It's really quite unclear what "Cancel" here means. It's easy to think it means "cancel publishing", but it doesn't, right?
I wonder if a better interface isn't to have three buttons:
- Copy Link [default]
- Update [reddish button?]
- Cancel
I think it's also important to put the conventional "copy" icon right next to the URL. For people who know about Ctrl-C/Cmd-C, the current interface (w/ text selected) works fine. But for people who don't do that, they're going to drag the mouse, maybe select only part of the text, etc. I think there's a reason why apps have all moved to having a "copy to clipboard" button.
Curious what Adam Solove would say. This already looks improved by him, and I think it's visually better than before, but could probably be improved further.
@asolove ^
I have a proposed design for this that I can find when I get back home.
The real issue is not UI though but concept. There are several completely separate things that can happen in the publish dialog that are currently conflated.
IIUC, the way it works is:
- Every CPO session has a “file”
- The first time you click publish for a publishable file, you see a warning about what this means and are asked if you’re ok with the implications. If you agree, a second copy of the file, the “published file” is created and is available to other users.
- Later on, if changes are made to the original file, you can “update” to push those changes to the published file. This actually creates a new “version” of the published file without forgetting about previous versions.
- Each published file has two identifiers with different semantics. One is a file id which allowed interior mutation (so that it always points to the latest version). The other is a file hash that will always point to a single version of the published file.
A couple issues then:
- while seeing this UI instead of the permissions screen does mean that the file has previously been published, that isn’t actually explicitly communicated anywhere and novice users may not know. It also doesn’t make it obvious when you published it, what the content was, or what other previous versions may still be importable.
- the current UI combines “get the reference to the current file” and “get the hash to the current version” but hidden as a syntax difference between URL’s and imports. That seems wrong: you might want the immutable one as a url or the mutable one as an import (for a class assignment template, where the teacher might need to fix a base file).
- it also combines “get the reference/hash” with “push changes to the published file”, when those two things are separate.
- it does not communicate the mental model of file -> mutable published reference (wrapping immutable versions)
What could we do with this? If I had an unlimited time budget, I would probably:
- Make this into a UI with a couple sections rather than a modal that looks like it has a single action. Rename it to “Share” since you can use it to share the file without actually changing the publish state at all.
- one section shows the published copy’s state. It should clearly show: this was published, here’s how to share the current version. (URL should be default option, with import syntax available but clearly secondary for people who know what it is.) This is purely informational and at max you can copy something and then close the UI with no fear that you took or cancelled any other action.
- a second section on version history, possibly with a list of past versions, date times for versions, maybe a way to see a diff of the current file v publishable file state. Then a button that clearly takes the action of publishing the current files state into a published version
- If there is a diff between current file state and published file state, a small warning should appear near the copy url section and indicate to use the publish button first.
I also am still partial to the idea that “Share” would be a natural way to add in explicit assignment tracking, on which case “share with a single class section” might be equivalent to a published version, and have an option to expand the student files created from the shared assignment file. But yeah.
@asolove 's proposed design is good.
One clarification about how this works – there is only one ID for (and indeed only one copy of) the published file. The import and the #share version should have the same ID, and refer to the same place.
The file is always mutable by re-publishing. Since it's owned by the owner of the original file, this doesn't give others a way to change it or anything, but others could always see the code change when re-visiting the share link or re-running a program with an import of that file.
Oh, interesting! What is the deal with the two arguments to the import? I thought I had saw some code where that was versions.
Let me think on that, it simplifies the design problem a lot!
The second argument to import is just a friendly human name for the file to ease reading import lines (the publish UI just copies the name over).
Oh and the &v=NNNN bit is the commit hash of the Pyret version in use. It doesn't have any effect. A long time ago we used to keep old Pyret versions around and load the one that corresponded to the version the file was shared with. This was for really thorough backwards-compatibility. That got way too complicated with language updates that affected the runtime so we left it as a bit of useful debugging information. You could drop the &v=... with no effect.
https://groups.google.com/g/pyret-discuss/c/Y1uIuWrUEI4/m/JVYjDieeCgAJ
@shriram @jpolitz Curious for feedback before I go further with this.
The idea here is to have three separate states:
- You have not shared yet, but can if you want to. (The warning about permissions now moves to after you see the Share modal for the first time.)
- You have shared and the file content matches what is public. (You can see that fact and grab the link or import syntax, but there's no need to worry about update.)
- You have shared before but have updated the file so it doesn't match what's public. You can grab the link or import for the published version, and see at a glance that it's different from the current file content, plus get a diff or publish updates.
The share widget has a dropdown similar to the Run/Run with Types dropdown, which defaults to "Link" but can be switched to "Import". And the dropdown picker will have descriptions of when you want to use each, but this way Link is very prominent and only people explicitly looking for something else have to think about the import syntax.

This is all powered by a fun discovery that the Google API response we already fetch has lots of useful timestamps and an md5 of the file content. I hope that separating out these states means we no longer need long text explaining the save v publish issue, and people will be less confused.
Visually, I think it's pretty solid. Focusing on the few things I don't like:
- The
Link vbutton I think overly hides the Import functionality, at least not without some explanation at the top to clue people in of what that button could do. It's odd to me that stylistically that button and the copy button are themed identically but have very different functionality... - I'm not sure if this is the intended size of the dialog, but as shown, the URL portion of the share link is precisely the uninformative part of the link! Everything on CPO starts off with
cpo/editor#.... - The yellow "cautionary" circle is a bit hard to see -- I'd prefer an update icon instead (e.g. something like https://thenounproject.com/icon/refresh-document-403307/, just as a brainstorm idea), and then the green circle could become a green check or something.
This is all powered by a fun discovery that the Google API response we already fetch has lots of useful timestamps and an md5 of the file content.
Nice! Thanks for spelunking through those responses. That's super helpful.
My feedback is basically the same as @blerner 's. I don't mind the undiscoverable dropdown next to Link since import syntax is so seldom used. The simple colored circles seem lousy for accessibility, not sure I have a concrete alternative in mind.
Thanks for feedback, all!
- Yes, UI needs more work and this is more a mockup of the structure of things. The "Link" dropdown should look more like a dropdown (up/down arrow, more obviously clickable). I'll work on that styling and we can also bikeshed the exact text that shows up in the dropdown to explain the two options.
- I'm not sure I want to show more of the url though, as the only purpose of showing it at all is so you can verify it is the right "shape" of thing ("this looks like a URL hosted by Pyret!") and anyone reading the full content is probably making a mistake
- Agree on updating the icon to be clearer. I like something that's scannable at small size so we can also use it in the Share button outside of the modal. (I like the subtle hint that after you first share, it's green, and when you next make changes it turns yellow, and you maybe start building your mental model of how our sharing model works without having to read a lot of text.)
- I'm not worried on accessibility of the icon, though, as it duplicates information already semantically available in the text, and is just an additional helper.
Sounds like folks are ok with this direction, though, so I'll get the main flows working and then report back with a closer-to-real UI.
We often get teachers (and likely students) who don't see/notice the difference between #share and #program links. I think I'd prefer to see at least ...#share=XXXX... in the link text, so that (a) students and teachers habituate to looking for that #share part, and (b) so that experts can quickly skim the beginning of the uuid and correlate that with where it's used in other files. (This had been useful, eg, in fixing up a bunch of BS:P teachpacks, when we weren't quite sure we had the right original files.) It doesn't need to be much, but I'm uneasy with it being this shortened.
Oh interesting! I don't even know the difference between #share and #program: what are they? Happy to make sure we share more if that distinction is important to experts.
On Mon, May 2, 2022 at 1:14 PM Ben Lerner @.***> wrote:
We often get teachers (and likely students) who don't see/notice the difference between #share and #program links. I think I'd prefer to see at least ...#share=XXXX... in the link text, so that (a) students and teachers habituate to looking for that #share part, and (b) so that experts can quickly skim the beginning of the uuid and correlate that with where it's used in other files. (This had been useful, eg, in fixing up a bunch of BS:P teachpacks, when we weren't quite sure we had the right original files.) It doesn't need to be much, but I'm uneasy with it being this shortened.
— Reply to this email directly, view it on GitHub https://github.com/brownplt/code.pyret.org/issues/414#issuecomment-1115138031, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAACCL4C6RDC7LEOIEPCHWTVIAEQFANCNFSM5LC4TBVQ . You are receiving this because you were mentioned.Message ID: @.***>
When you're working on your own programs, you're working on a #program=XXXX link. When you share it, you get a #share=YYYY link (with a different id than the program itself, since it's a copy of the original file). Too often teachers (and likely students, but I haven't interacted directly with them in classrooms) just copy the URL of the browser window they're in, and send that URL to the workshop leaders -- and that'll be a #program=XXXX link.
And what happens then? I assume they get a 404 because of lack of access? Could we make that page a little clearer and add a "if someone sent you this, they might need to share it with you!"?
On Mon, May 2, 2022 at 2:06 PM Ben Lerner @.***> wrote:
When you're working on your own programs, you're working on a #program=XXXX link. When you share it, you get a #share=YYYY link (with a different id than the program itself, since it's a copy of the original file). Too often teachers (and likely students, but I haven't interacted directly with them in classrooms) just copy the URL of the browser window they're in, and send that URL to the workshop leaders -- and that'll be a #program=XXXX link.
— Reply to this email directly, view it on GitHub https://github.com/brownplt/code.pyret.org/issues/414#issuecomment-1115199804, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAACCL67CGPKJILXW6Q4Z6DVIAKTTANCNFSM5LC4TBVQ . You are receiving this because you were mentioned.Message ID: @.***>
The person who sends out the wrong URL won't notice anything -- how could they? they aren't doing anything directly with CPO at that point! The recipient of the link merely sees a red "The program failed to load" message in the status bar at the bottom-right. We have no way of detecting whether the program id was bogus, mistyped, or forgotten-to-be-shared, since the GDrive API just returns a 404 to us.
Sure but our UI after the 404 could guess and explain that either the link was bad, you are signed in with the wrong account, or if someone gave you this link they should use share instead.
On Mon, May 2, 2022 at 2:28 PM Ben Lerner @.***> wrote:
The person who sends out the wrong URL won't notice anything -- how could they? they aren't doing anything directly with CPO at that point! The recipient of the link merely sees a red "The program failed to load" message in the status bar at the bottom-right. We have no way of detecting whether the program id was bogus, mistyped, or forgotten-to-be-shared, since the GDrive API just returns a 404 to us.
— Reply to this email directly, view it on GitHub https://github.com/brownplt/code.pyret.org/issues/414#issuecomment-1115222760, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAACCLYXC3Y2G76J4ZTX32LVIANFDANCNFSM5LC4TBVQ . You are receiving this because you were mentioned.Message ID: @.***>