-
Notifications
You must be signed in to change notification settings - Fork 44
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
Circulars Archive Group View #2617
base: main
Are you sure you want to change the base?
Conversation
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.
Please rebase.
e64cd81
to
d91fa13
Compare
Added "Open/Close All" button on group overview page as requested by @jracusin |
That was the plan as I said in the original PR description:
I rebased and took the PR out of draft status. |
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.
There are more conflicts. Please rebase again.
f425a78
to
e53c732
Compare
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.
First, some high-level UX feedback:
- Please use numbered lists, not bulleted lists, for Circulars in the index view. The list number value should be the Circular number.
- For now, don't have disclosure arrows on the per-group page. Just display all of the Circulars belonging to the group. We can fine-tune the UI to quickly navigate within a group in a future PR.
@@ -29,6 +29,7 @@ export const AstroDataContext = createContext<AstroDataContextProps>({}) | |||
/** | |||
* An Astro Flavored Markdown enriched link. | |||
*/ | |||
// eslint-disable-next-line react/display-name |
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.
Why was this addition necessary?
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.
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.
I was trying to make the move have no changes to the code if possible
@@ -53,6 +64,7 @@ export default function PaginationSelectionFooter({ | |||
page={page} | |||
limit={limit} | |||
totalPages={totalPages} | |||
view={view} |
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.
Why does the Pagination component need to know about the view?
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.
because in getPageLink if the view is not set as a search param, then when it creates the link, it doesn't include view. If it doesn't include view, then the view defaults to index. If it's always index, then the pagination links will never work for groups. To show you what I mean, here is what happens when I remove the view from getPageLinks. When I hover over the 2 button, this is the link. You will see that it doesn't include the view so when that page is navigated to, it's the index view which is the default.
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.
Ah, I see.
The last time that I looked at this component, I noticed that a lot of apparently separate concerns were leaking into it from pages that use it. At some point, I'd like to come back to this and try to refactor 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.
I think that's a good idea. It did feel odd to have to add view specific code to 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.
- Please place the new event pages under /circulars/group/ rather than /group/.
- The synonym IDs make for URLs that are not very presentable. Instead, can we use a slugified form of the event name (any of the event names that belong to the group) as the path component?
I have a couple of concerns about this if I'm understanding correctly.
Can you explain what about uuids feels not presentable to you? |
adds validation and error handling fixes tests adds modal warning prior to delete changes removal button to words instead of only icons code review change requests removing unused className formatting autofill moderator synonym eventId selector adding create sad path test removing feature flag check adding a 3 second debounce Adds grouped view to circulars archive index adds missing route and flag checks
81d7ea6
to
772831d
Compare
I proposed using "any of the event names that belong to the group" as the path component. So /circulars/groups/GW170817, /circulars/groups/GRB170817A, /circulars/groups/GW170817+GRB170817A would all represent the same resource. (One would need to be reported as the canonical URL for SEO purposes; probably the version with the maximal set of terms.) Another option (but not my preference) would be to do what Stack Overflow does: have an opaque UUID followed by a slug that is ignored. So for example, all of the following refer to the same resource:
although the first is canonical.
It's a usability issue: https://en.wikipedia.org/wiki/Clean_URL |
That still does not solve for or answer the issues I brought up in the above comment. If we take your example of /circulars/groups/GW170817, /circulars/groups/GRB170817A, /circulars/groups/GW170817+GRB170817A. Jane Doe is interested in this grouping that she discovered when searching for GRB170817A. She bookmarks /circulars/groups/GRB170817A so she can go back and look at this group. A moderator looks at the grouping and decides that while the events were very close together, they are actually different events. So the moderator removes GRB170817A from the group with GRB170817. So now when Jane visits the website looking for the information from both GRB170817A and GRB170817, the link she bookmarked would take her to the group that only has GRB170817A in it. This request would be like removing the circularId from the circulars path and replacing it with the circular subject instead. But you shouldn't do that because the subject could be edited and if so, it would break links because it's fragile. The only difference in these patterns is UUID vs integer id. But the integer ID isn't giving any additional information in a human readable format. I have no insight into what circular 12345 is about. To make it restful, it should follow the pattern /{resource}/{id} |
I don't disagree that RESTfulness is a desirable property for URL routing, but an entity need not have a unique URL, does it? By analogy, files on a filesystem don't have unique paths. It's true that we are using Circular IDs as URL path components, but Circular IDs are part of the publicly-visible bibliographic record of Circulars. UUIDs are an internal detail. |
I disagree that what you are proposing is "clean".
your request violates:
because calling a resource by one of it's members is not restful. not restful != clean and
because of the situations outlined above when the members of the group change. If I have a group of GRB A, GRB B, GRB C, and GRB D. If I bookmark Additionally, is it really worth the complexity that it creates?
|
In a URL like /circulars/group/GW170817, the "group" component is a the resource and "GW170817" is the ID. I view the event names as permanent, stable IDs. The UUIDs are not. Although this approach appears RESTful to me, I don't want to get bogged down in that argument, because this path is not an API endpoint and it is not all that important whether it is RESTful or not. It's more important that they are human-readable and predictable. Here are some examples of style guidelines and advice related to human-readable URLs:
That looks like a reasonable implementation plan. Is there a good open-source slugging library we could use? |
So if the group consists of events GRB 123456A, GRB 123456B, and GRB 123456C, is GRB 123456A the group? or is GRB 123456A a member of the group? if we have a data structure that is like so:
Which is how we are representing the concept of a synonym group. I acknowledge that how it is stored in dynamo does not make it apparent, but that is because we had to do some unusual things to use a document store relationally. But the general concept of a group is the above structure. According to that record above, is the resource id of the group 1 or is it GRB 123456A? If I remove GRB 123456C from the synonym group, thus making it a group unto itself I would have these two records:
Is the group the same for GRB 123456C as it was before? it used to be in group 1, now it is in group 2. Are group 1 & 2 the same resource? |
I would consider the group to be a collection of circulars. I don't care that there is a DynamoDB table of synonyms. Synonyms are not a user-visible aspect of our application (except to moderators). In your example, I suggest that all of the following URLs resolve to the same resource:
The canonical URL should be /circulars/group/grb_123456a-grb_123456b-grb_123456c, which consists of all of the synonyms in lexical order. To resolve the group for a given URL, take the entity ID and split on the separator (in the example above, a dash). Take just the first name in the group, and look up its synonyms. Return all Circulars for all synonyms belonging to that group. |
Okay, so according to your example, I have bookmarked group: |
in the above case |
No, it would not. As I said:
|
so you are saying that if they looked up |
I'll refer you again to this algorithm:
The alternatives that I see are to raise a 404 error if the URL does not contain all of the event names, or to only return the circulars belonging to the event names in the URL. Both of those alternatives would be more surprising to the user. |
But what wouldn't be surprising to anyone in any case is if the user had a link to a group id instead of to the changing members of the group. if you had the uri as that way, when the editable field gets changed, the uri is not comprised of editable members, so it doesn't get confusing. You would always go to the group and who the members of that group are can change freely without impacting anything while also following REST. That's why it's the convention. if the user bookmarks |
The URL structure does not need to reflect the database structure. The UUIDs are a bit of dirty laundry that I don't want users to see, ever. |
We decided as a group that we would use the following style of URL: Consequently, an event consisting of GRB 123456A, GRB 123456B, GRB 123456C, would have the following URLs, which would all be equivalent:
@Courey, please note:
|
There are several characters we use in eventIds that are not alphanumeric. they are: Some of these are acceptable in URIs, others are reserved and can not be used. Here are examples of the different characters that are used in eventIds:
If we tried to use the slug to query the database, we would not be able to return them exactly to their original format, we would just know that reserved or unacceptable characters had been turned into dashes. This would have a similar impact to SEO as the other options where the keywords are not exact. (GRB-160225-81 would be GRB, 160225, and 81 instead of 160225.81)
here are the examples above url encoded:
Encoded with our custom encoder they would appear like so: it's unusual, but functional. It can be revesed exactly so the value can be used in a query and it would preserve keywords. None of the options are ideal and all will have some impact on SEO. Option 1 is not an option. |
An additional option would be to add a field to the synonyms table called
Then we would have to add an additional index to the slug field. That would change the lookup slightly from a pkey lookup to a GSI lookup. We would need an additional backfill for the existing synonyms to create the slug. |
@Courey, if we want the slugs to be case insensitive (and I think we do), then we'll need to add the slugs to the database anyway because DynamoDB keys are case sensitive. Given that, I think we can abandon the requirement that the slugs are reversible, and just replace anything that would require percent encoding with a dash. There are a number of slugging libraries on NPM. I believe that we already have a dependency on https://www.npmjs.com/package/github-slugger. |
Additional work for this feature:
|
This work is based off #2538 and will be turned into a non-draft PR once that work has been merged in and I rebase off main.
Description
This work includes:
Related Issue(s)
Resolves #2544
Testing
This has been thoroughly manually tested locally, but should be tested on dev WITHOUT the feature flag on to ensure that no existing functionality has broken.
Images