Implement collection attacher component.#3599
Conversation
|
Skipping CI for Draft Pull Request. |
|
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
68f4a49 to
e3de69a
Compare
| () => | ||
| debounce( | ||
| (value: string) => setSearchFilter({ Collection: value }), | ||
| (value: string) => setSearchFilter({ 'Collection Name': value }), |
There was a problem hiding this comment.
This is an unrelated change, but not worth a separate PR.
The BE team is using Collection Name instead of Collection for this search label.
| sortOption: ApiSortOption, | ||
| page: number, | ||
| pageSize: number | ||
| page?: number, |
There was a problem hiding this comment.
Most backend APIs can support un-paginated requests, so we don't need to enforce that these values are set.
In this specific use case, we need to request all attached collections by id without pagination.
e3de69a to
d6ee87a
Compare
|
Images are ready for the commit at 462c127. To use with deploy scripts, first |
c89253d to
9ea40fb
Compare
| className="pf-u-align-self-flex-start" | ||
| variant="secondary" | ||
| onClick={() => fetchMore(search)} | ||
| isLoading={fetchMoreLoading} |
There was a problem hiding this comment.
Most boolean state variables have is or occasionally has prefix:
isLoading={isFetchMoreLoading}A grammatical alternative in this case which I mention, not necessarily recommend: isFetchingMore
There was a problem hiding this comment.
I think the grammatical alternative reads better in this case, updated the prop name.
| } | ||
| > | ||
| {items.length > 0 ? ( | ||
| <TableComposable aria-label={label} variant={TableVariant.compact}> |
| <Badge className="pf-u-ml-sm" isRead> | ||
| {items.length} | ||
| </Badge> |
There was a problem hiding this comment.
Thoughts about badge, which I was happy to see after designs had moved away from it for a while:
- Attached collections: Does search filter apply to this table? Length seems meaningful only if not filtered.
- Detached collections: Length seems meaningful only if
!hasMoreand maybe only without search filter.
There was a problem hiding this comment.
Agreed that the badge has limited utility when the full dataset is not present, and the one case where it would be meaningful (unfiltered attached collections) is likely going to be a small enough number that the badge is fairly unimportant.
I left the ability to show the badge in the underlying component though, since if we get reuse out of it there is the possibility we use it against data that is complete and unfilterable.
| return isByLabelField(selector.field); | ||
| } | ||
|
|
||
| export type CollectionSlim = { id: string; name: string; description: string }; |
There was a problem hiding this comment.
Note to self - we can just use the full type since we are querying the server for the full Collection object here.
- Replace
CollectionSlimwithCollection
There was a problem hiding this comment.
Instead of Collection, I just passed CollectionResponse[] directly since the parsing of the response into a stricter data type is not needed for this piece of the UI.
9ea40fb to
2f9f80b
Compare
| <Button variant="link" className="pf-u-pl-0" isInline> | ||
| {name} | ||
| </Button> |
There was a problem hiding this comment.
Asking to confirm my understanding or misunderstanding: Button element
- in form: will have
onClickcallback to view collection in modal? - in modal: will have
component={LinkShim} href={href}props to view collection in page?
If yes, then aretarget="_blank" rel="noopener noreferrer"props also needed?
There was a problem hiding this comment.
Yes that is exactly correct. In a follow up I'll likely move the CollectionAttacher.tsx#selectorListCells up to CollectionFormPage and pass through as props CollectionFormPage -> CollectionForm -> CollectionAttacher to accommodate the two use cases for the main page table and the modal table.
| aria-label="Search by name" | ||
| placeholder="Search by name" |
There was a problem hiding this comment.
Although I see Search Google and Gmail, Filter seems more common for placeholder in UI.
There was a problem hiding this comment.
Fair, there are multiple occurrences of Filter in similar contexts but this looks to be the first case where we use Search. This is kind of a hybrid case, as we are both searching and filtering the two lists with a single input, but I'll change for the sake of consistency.
| selectedOptions={selectedOptions} | ||
| deselectedOptions={deselectedOptions} | ||
| onSelectItem={({ id }) => attach(id)} | ||
| onDeselectItem={({ id }) => detach(id)} |
There was a problem hiding this comment.
An observation, not a change request, that change in terminology from attach/detach to select/deselect is what I would expect for a reusable component, what do you think are pro and con:
- pro: how likely to reuse in a context where application level is other than attach/detach
- con: slight substitution by reader and possible effect on Find in Files
There was a problem hiding this comment.
Hmm this is a good question. My gut feeling is that the default terminology for using this in other contexts would be "select/deselect". This component is similar to the dual list selector PF component which uses terms that are fairly close. I think the attach/detach are specific, but not exclusive, to the semantics behind Collections.
That said it doesn't feel great having a disconnect between the props and the only use case. (The useSelectToggle() hook suffers from this mismatch as well.) I'm OK with changing the terminology or leaving as-is. Do you think people are more likely to Find in Files or Ctrl+Click to navigate around this code in the future?
There was a problem hiding this comment.
Your choice. You caught me: I often use Find in Files by mental muscle memory from less capable editors.
| selectButtonText="Attach" | ||
| deselectButtonText="Detach" | ||
| /> | ||
| {fetchMoreError && ( |
There was a problem hiding this comment.
First impression gave me a much needed smile: fetch more error, please ;)
There was a problem hiding this comment.
Hahah now I can't read it any other way! Seriously though, do you think there is enough chance for confusion that we should change this to fetchingError?
There was a problem hiding this comment.
It just hit me funny at that moment. In first reading a few days ago, it seemed nicely consistent.
pedrottimark
left a comment
There was a problem hiding this comment.
Approving and am available as needed if there is anything more to discuss.
|
@dvail: The following test failed, say
Full PR test history. Your PR dashboard. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |


Description
Adds a UI component that allows users to attach and detach "embedded" collections from a collection configuration.
When the initial collection data is loaded, a secondary request will fetch metadata for all of the embedded collections of the initial collection. These embedded collections will make up the attached list in the widget, and are not paginated.
Once this data is loaded and the form is rendered, the collection attacher component will attempt to fetch a page of detached collections (everything else in the system). Since this secondary request may include collections that are already part of the attached list, we need to filter the results client side. If this filtering results in less than half a page load, we fetch an additional page worth of data. The idea being we want to prevent situations where "View more" returns a full page sometimes, and then very few another time (possibly even zero), which could lead to looking like buggy behavior.
When the user enters a search term, the locally cached list of detached collections is cleared out and the page counter is reset. This will require refetching the detached collections, now filtered by search term. This could cause some wasted requests, but the alternative of keeping the cache and filtering client side had larger problems. If we don't clear cache and all data has not yet been loaded, there would be two ways to handle the follow up "view more" requests:
I've documented some potential workarounds and optimizations for this in the code that we can do as follow ups if needed.
Checklist
If any of these don't apply, please comment below.
Testing Performed
Visit the collections page, and select a collection that has embedded collection data:

Clicking the "Attach" button should remove items from the bottom list and place them in the top list:


Clicking the "Detach" button should move items from the top list to the bottom list:


Entering a search value should filter the top and bottom lists by collection name, case insensitive:


Clearing the filter should return the list to its previous state:
To demo the "View more" behavior, I manually changed the
pageSizeand minimum threshold to be1.If there are more results on the server, a "View more" button should be displayed.

Clicking this button should load another page of results:


Continuously clicking this button will load more and more results from the server.
Note that when we get to the fifth item, two network requests are sent instead of one. This is because the first request contains only "Notable deployments", which is already present in the attached list. Since this would result in no new items in the detached collections list, another request is sent.

When all results have been loaded by the server, the view more button disappears.

Test that layout is usable on small screens:
