-
Notifications
You must be signed in to change notification settings - Fork 1
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
main UI - directives and table views #168
base: main
Are you sure you want to change the base?
Conversation
src/liquid/app/nav.html
Outdated
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.
renamed to header.html to distinguish between header and nav bar
src/routes/app.ts
Outdated
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.
apply changes and filter modified to filter by contactType
src/scss/_header.scss
Outdated
$dropdown-width: 200px; | ||
|
||
.navbar { | ||
background-color: $_medic-grey; |
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 we should keep the navbar white and remove the text next to the logo. The previous look with the logo only was clean
src/liquid/app/header.html
Outdated
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 see we removed most of the actions from the nav but i don't see any alternatives introduced for clearing the place list, refreshing the place list, creating places etc
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.
was following this for design thats why options moved away from then header bar
must have missed the clear option though will add that nice catch
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 there's no alternative for the actions in the Users
drop down menu i think we should just maintain it for now or provide alternatives
src/liquid/place/list.html
Outdated
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.
Can we add an explicit color for the in_progress
state? It looks like it defaults to gray which i think is a bleak color for a progress state
src/liquid/place/directive.html
Outdated
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.
The places don't get filtered when i click on any of the filters
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.
interesting would like to know how this is tested
what browser are you using?
this works in my chrome and firefox
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 am on Firefox, eg if i successfully upload say 10 items from that list and click on the success
filter, the list doesn't get updated and i still see all places regardless of state
src/scss/_tables.scss
Outdated
margin: 0.5em 5px 1em 5px; | ||
width: auto; | ||
border-radius: $element-border-radius; | ||
@include card-shadow; |
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 don't think we should have a shadow on the table. In this case, the table and the pagination controls should be on the same level yet the table is "above" the pagination controls. I think we should use shadows sparingly
src/public/scripts/pagination.js
Outdated
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 feel like the UI would be much snappier if we paginated the Place list from the API. I've noticed this triggering the "page is slow or unresponsive" notification on Firefox on large lists. Currently (changes on the main branch) we're lazy loading the place list but i think a solution around pagination would be much better
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.
glad you brought this up
how big is the test dataset?
also curious on how you are testing this be cause it loads very fast even with large datasets on my end since data is loaded once and this pagination is just ui showing and hiding rows
but the reason i used the UI not the api to paginate was the api is slow
you can test this in prod
- load a large dataset
- filter the dataset, you'll realize the more data you have the slower the filter gets
this is actually what breaks my browser during testing but the pagination works fine
you can feel performance drop with as little as 30-40 rows
Which brings me to this; why are we using session storage to store data? i dont think its the right solution for scaling
we could try browser dbs like pouchDB, indexeddb etc they can offer better performance cc @kennsippell
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.
but also very curious how pagination slow on your end could you share video recording of this?
it not expected to be like this at all
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.
im exploring using the api atm i see your PR introduces table lazy loading it could help
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.
but the reason i used the UI not the api to paginate was the api is slow
Yes, for large lists (1000+) it takes 1-3 seconds to generate the HTML but if we add pagination, we'd only be generating HTML for a smaller dataset making it much faster
filter the dataset, you'll realize the more data you have the slower the filter gets
this is actually what breaks my browser during testing but the pagination works fine
Yes that is what is slowing down my browser as well. If you test with the latest changes It's much better but that doesn't fully fix the problem as we should be trying to keep response times in the 100-200ms range if possible
Which brings me to this; why are we using session storage to store data? i dont think its the right solution for scaling
we could try browser dbs like pouchDB, indexeddb etc they can offer better performance
Right now the server acts as the source of truth since this is a server rendered app, there's no to little state on the client side. It might be the wrong one but not for the reasons you stated, memory will always be faster than anything that does File I/O.
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.
memory is fast for small data but when it comes to large data i think youre better off with a db app becomes memory hog and browser hangs
Memory here is RAM on the server or whatever platform this is deployed on. No data is stored on your browser. For this app, if your browser hangs it's either trying to render a massive amount of HTML or some JS is misbehaving.
we could explore redis as well
I'd prefer if we used an embedded DB (like sqlite3) to reduce deployment complexity but we can discuss this later
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.
until we instruct it to store data locally its ram even in the browser thats why it struggles
anyway ill implement the api pagination and circle back here
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.
@freddieptf I have update pagination to api its works well until pagesize is about 50 rows
but still pretty much usable
this ready for review
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.
its works well until pagesize is about 50 rows
It should be fine for larger lists if you test with NODE_ENV=production
. Can we now remove the lazy loading and do pagination? I think the lists loads fast enough now.
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.
if by lazy loading you mean the spinner logic i beg to differ i think its very useful for bad internet/ heavy server loads that might delay response its good practice we should leave it
c67e457
to
c36c9c9
Compare
src/services/pagination.ts
Outdated
constructor(options: { page: number; pageSize?: number; cookie: {}; requestContactTypeName?: string }) { | ||
this.pageSize = options.pageSize ? options.pageSize : 10; | ||
this.page = options.page; | ||
this.cookiePageSize = this.getPaginationCookie(options.cookie, 'pageSize'); |
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.
This should belong on the request URL and not in the cookies. It's very transparent what data the app is loading when it's on the page URL. Also, It'd be weird if someone uploaded a list, viewed a random page, cleared the list, uploaded another list then got directed to the previously cached page we find in the cookies.
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 want to persist page number in cookie to handle all miscellaneous call to root "/" e.g when you move out to create more users/edit etc you should come back to your "current page"
i can create logic to handle the situation you are talking about
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 can create logic to handle the situation you are talking about
Yeah but that's just more code. Personally, I like less code. Having the state in the URL for both the current tab and page is much simpler and easier to understand at a glance both on the UI and in code
i want to persist page number in cookie to handle all miscellaneous call to root "/"
Then maybe we should fix that instead?
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.
whats is much code? :)
you want us to handle all calls to "/"? that sounds like more code than just handling this situation with a variable and an if
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.
cookies are good for storing and persisting user preferences besides there is nothing sensitive we are storing here that the user cant see on the ui
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 want to persist page number in cookie to handle all miscellaneous call to root "/"
you want us to handle all calls to "/"?
Find these calls and replace them with appropriate ones i.e redirecting to the correct page. Calling /
worked before because there was no pagination
cookies are good for storing and persisting user preferences besides there is nothing sensitive we are storing here that the user cant see on the ui
The current page and active tab are not user preferences, they are part of the navigation state that should be on the URL
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.
cookies have been removed
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 entirely sure if we need this, managing this state would be much easier if all you had to look at was a URL param and slice the list accordingly
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 dont understand is this comment intended for the entire pagination file?
you mean slice it in front end? that would be expensive for the PC/browser
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.
This class as used in the endpoint. You can parse the URL param and slice the place list before returning the response to the browser.
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 sure i understand this well
what you're explaining i believe is what i'm doing here
is only sliced/paginate and sent back to the user
this has no effect on the original places data in store and also only return sliced data
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 entirely sure if we need this, managing this state would be much easier if all you had to look at was a URL param
This is part of the cookie conversation. We don't need cookies for these
@@ -30,6 +30,28 @@ export default async function events(fastify: FastifyInstance) { | |||
}); | |||
}; | |||
|
|||
const updateNavBadge = async () => { |
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.
Isn't this already done by the "directive" update?
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.
directive updates the directive, this nav bar is outside the directive
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.
will try move this inside directive and see though it was a bit "shaky" loading the entire nav bar
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.
oh i see so this updates the count on the navbar. You can just remove the count from the navbar then, no need to duplicate what's already on the directive
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.
This might be trickier than i thought. While the filters work, i find them a bit confusing as they represent the state of both lists. This worked before because all the lists were on the same page. In the screenshot below, all the 4 invalid items are on 1 tab so if i apply the invalid filter when on the other tab I get an empty list and have to manually switch tabs to view the invalid items.
I think we should move the filters closer to the table, it would be great if they were directly on the status column. The app only needs to show the user some sort of hint when there are invalid/failed items and these hints can have links that just auto-apply a filter
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 see no problem showing 0 rows if the filter is applied as long as we clearly show that there is a filter applied
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.
OK, we can change this behavior later then.
src/liquid/components/summary.html
Outdated
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.
What should be on this page? I don't see it used anywhere
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.
this is the summary essentially place states for each contacttype
plan is to handle it later in another pr as this is very big already but shouldnt be a blocker
unless otherwise, i can remove it lmk what you think
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.
If it doesn't have anything on it then there's no need to keep it around
src/routes/authentication.ts
Outdated
@@ -23,6 +23,11 @@ export default async function authentication(fastify: FastifyInstance) { | |||
|
|||
fastify.get('/logout', unauthenticatedOptions, async (req, resp) => { | |||
resp.clearCookie(Auth.AUTH_COOKIE_NAME); | |||
for (const cookieName in req.cookies) { |
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.
Maybe you can remove the call to clearCookie
now?
<a hx-post="/app/remove-all/{{contactType.name}}" hx-swap="none" | ||
data-toggle="tooltip" data-placement="bottom" title="delete all" | ||
hx-confirm="Are you sure you want to DELETE ALL USERS?"> | ||
<img src="public/icons/delete-all.svg" alt="refresh"> |
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.
Can we use the same icon used on the list items?
src/liquid/place/directive.html
Outdated
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.
Fix indent please
src/liquid/place/place_navbar.html
Outdated
</div> | ||
|
||
<script> | ||
function highlight(element) { |
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.
Can we find a way to update this state from the server? Let's try and avoid JS like this as much as possible
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.
Anything ui related that can be done frontend shouldnt do around trip to the server, find it unnecessary
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.
While i agree with you, you still make the trip to the server to fetch the page after clicking the tab. Being a server rendered app, the server manages most of the state in the UI. In this case, you can return both the page and the updated navbar in the response from the server and achieve the same effect without JS
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.
but htmx, sse etc all run in the frontend and do manipulate ui before even hitting the server!
this is equivalent to asking the server to register/listen for button clicks
i dont think thats what SSR is
otherwise you end up with things ive seen here where server is storing and assigning classes
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.
but htmx, sse etc all run in the frontend and do manipulate ui before even hitting the server!
this is equivalent to asking the server to register/listen for button clicks
There's nothing fancy going on. We're just issuing AJAX calls to the server on certain events. htmx helps with this and content loading/swapping. We can ditch htmx and just use full page reloads for any state change and the app would work the same as the state is all on the server.
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.
ditching it would be pointless. you can never get rid of js completely in web development even if your back end is python
JS was built for web development
The point i was making wasnt about htmx only but all the js served in the public folder all of it runs in the browser
all the calendar js tooltip js etc
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 i understand some UI elements are complex and need JS to manage their state. To be clear, I'm not saying we should get rid of JS, I'm saying that the application state should be driven by the server as much as possible. Application state in this app should be the same with or without JS
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.
UI state and server state should be managed seperately, with only communication between the 2 on the state of one another
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.
All I'm saying is update the tab's state by the same way the contents of the page are updated. We don't need a script to do 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.
this has been changed
src/css/custom-bootstrap.css
Outdated
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.
Interesting that you still rely on bootstrap. Did bulma not provide this?
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 can customized bootstrap to get only the elements i want for this its tooltips, badges and breadcrumbs keeping the file very small
not sure you can do that with bulma
@freddieptf lmk when you have time we do a peer review online for this PR so i can better understand somethings |
@freddieptf requesting review here this is ready |
</nav> | ||
|
||
<script> | ||
document.addEventListener('click', function () { |
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 sure why this listener is added to the document and not the element being targeted
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.
aah i see, to hide the drop down menu when we click anywhere on the page, correct?
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.
Now I'm confused, since the drop down disappears when it's not hovered on, why is this needed?
</ul> | ||
</nav> | ||
|
||
<script> |
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.
It'd be great to keep scripts like this in an app.js
or something
Description
This PR is 2/3 of #172 and #157
Fixes #131