-
Notifications
You must be signed in to change notification settings - Fork 270
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
feat(portal): Filtering, Fulltext Search, Pagination, Preloads #3751
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Ignored Deployment
|
Terraform Cloud Plan Output
|
4915e56
to
3af1033
Compare
a53ebfa
to
a121c62
Compare
gateway_groups = Enum.map(gateways, & &1.group), | ||
{relay_hosting_type, relay_connection_type} = Gateways.relay_strategy(gateway_groups), | ||
{:ok, [_ | _] = relays} <- | ||
Relays.list_connected_relays_for_resource(resource, relay_hosting_type) do | ||
Relays.all_connected_relays_for_resource(resource, relay_hosting_type) do |
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.
Since we have various kinds of returns I've decided to come up with a convention just for us:
list_*
returns{:ok, results, metadata}
- basically a paginated query used everywhere in the UIall_*
returns{:ok, results}
- used in places where we need to really fetch all the results without pagination (eg. list of enabled providers when we build the sign in form)all_*!
returnsresults
or raises an error. This is when we just do the query and there is no need to wrap it in the tuple, mostly used for internal stuff like background jobs
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.
👍
) | ||
end | ||
|
||
def by_slug(queryable \\ not_deleted(), slug) do |
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've removed \\ queryable()
everywhere so that our domain modules are more explicit, before you had to go to query and see if it will return all, or deleted, or active, or whatever records. Now you have to explicitly set that as a first stage when a query is built.
6df1ec9
to
ebf1f1e
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.
Not going to do an in-depth review of the code (will leave that to @bmanifold after he's back).
Some usability fixes / requests:
- I don't think the
Showing 25 of 304
is updated when flipping through pages (e.g. on the Groups page). Is that intended? - Clients page: Could we add sorting to the User column too? I think that will be used quite a bit. And maybe add the "All / Online / Offline" button group (or allow sorting by status).
- Policies -- add sort for Group and Resource
- Can you space the sort form elements horizontally to make better use of the space? e.g. this is fine on small screens (grid-cols-2 that collapses to grid-cols-1)
![Screenshot 2024-03-15 at 11 10 44 AM](https://private-user-images.githubusercontent.com/167144/313293089-efcae46a-8277-4d67-98f1-3d91f9d231e7.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTk4MzE5NDksIm5iZiI6MTcxOTgzMTY0OSwicGF0aCI6Ii8xNjcxNDQvMzEzMjkzMDg5LWVmY2FlNDZhLTgyNzctNGQ2Ny05OGYxLTNkOTFmOWQyMzFlNy5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzAxJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcwMVQxMTAwNDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1lOWIyODBjYWMyODViYjI0ODM1ZjFiNzdkODI2MWVkMzZhMDZjYWQ3MGIxZmQxNDU4YjAyN2NlZDU2MGY5NGZlJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.ji3HD62Kh8q27hDoIHPZV83OScTBvLeneLYngm1s3ZM)
But on larger screens I would expect the filter elements to be side-by-side:
![Screenshot 2024-03-15 at 11 11 59 AM](https://private-user-images.githubusercontent.com/167144/313293433-256a03c9-9d6f-45dd-bf6d-38e2026d1419.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTk4MzE5NDksIm5iZiI6MTcxOTgzMTY0OSwicGF0aCI6Ii8xNjcxNDQvMzEzMjkzNDMzLTI1NmEwM2M5LTlkNmYtNDVkZC1iZjZkLTM4ZTIwMjZkMTQxOS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwNzAxJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDcwMVQxMTAwNDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04MTZkZjQ0NzcyYzIyNDcxMGE0MGNlNjQ3ZGY1MTJlZWE1Mjk1NjM3NWEwZWZkMDk5NThjYzYxNGVjZTdhYzM3JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.Hpm69TkUq9LXUerPD1RZYyg1cbBe_xOkjAdrWnlE13I)
On the Actors page it's a little more problematic:
Maybe all of these can be contained inside a dropdown menu that's activated by a filter button?
gateway_groups = Enum.map(gateways, & &1.group), | ||
{relay_hosting_type, relay_connection_type} = Gateways.relay_strategy(gateway_groups), | ||
{:ok, [_ | _] = relays} <- | ||
Relays.list_connected_relays_for_resource(resource, relay_hosting_type) do | ||
Relays.all_connected_relays_for_resource(resource, relay_hosting_type) do |
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.
👍
Yes, 25 is the page size, and 304 is the total count. We can't and don't say on which page you are currently since it's cursor-based.
We can but:
Same reason here, it's not the best idea to paginate using the result of a join, you can always use a filter to find the ones you need or use a different view to see group policies (group show view) or resource policies (resource show view).
This is hard to do because presence is not stored in the database and we need to come up with a smart way for those filters to work without hitting our database with a gigantic
I'd suggest improving UX in a separate PR, this will spawn all sorts of look&feel discussions that will take time, while I think it's better if we get this merged (it's already functional and not so horrible) to unblock the clients that have thousands of groups first. There are lots of ways how filters can be improved: we hide them below the collapse button, use grids, add/remove some of the filters, etc.
I think we need a better breakpoint so it extends on smaller screens, I'll take care of that. |
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.
Approving to fix the timeouts currently impacting customers. Fixes can be addressed in followup PRs.
2de6200
to
06f5181
Compare
Performance Test ResultsTCP
UDP
|
5ce3b7a
to
47820b9
Compare
…om name generator
all_*! now returns list all_* returns {:ok, results} | {:error, reason} list_* returns {:ok, results, paging_metadata} | {:error, reason}
a5286f6
to
2247704
Compare
@bmanifold This was merged to fix production for a customer with lots of accounts and groups, but could still use your review (and a little bit of UI/UX CSS cleanup noted in my review). @AndrewDryga I think in the future what might be good for large PRs like this is to maybe split the PR into a UI PR and backend PR? That way we can discuss UI/UX (maybe sooner) without it impeding the backend fixes needed. Or use something quicker like wireframes to figure out how it will work/look before implementing. |
I'm not a big fan of having dead code in the main that we can deploy at any time (like the back-end that can not be used anywhere). We can split work into smaller PRs and then merge them into a temporary branch, but this will just add more work and still require one final "big" review.
It's easier for anyone on our team to go and update the HTML than sit and discuss prototypes without being able to use the portal. I think with designs the best approach is to do "good enough and polish after" that rather than trying to wireframe everything and kill our productivity. For example, I would be always faster writing HTML and LiveView code than using wireframing tools, and by doing so I can also understand the limitations better, what is easy to do and what is not, which components are available in FlowByte, while dragging square boxes around we will make decisions that then can be really hard to implement, which will require another set of discussions, etc. |
On the domain side this PR extends
Domain.Repo
with filtering, pagination, and ordering, along with some convention changes are removing the code that is not needed since we have the filtering now. This required to touch pretty much all contexts and code, but I went through all public functions and added missing tests to make sure nothing will be broken.On the web side I've introduced a
<.live_table />
which is as close as possible to being a drop-in replacement for the regular<.table />
(but requires to structure the LiveView module differently due to assigns anyways). I've updated all the listing tables to use it.