Skip to content
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(logs): pagination and infinite scroll #2213

Merged
merged 7 commits into from
May 29, 2024
Merged

Conversation

bodinsamuel
Copy link
Collaborator

@bodinsamuel bodinsamuel commented May 27, 2024

Context

Fixes NAN-1004
Fixes NAN-997
Contributes to NAN-908

Took me a day just to handle this :|
It was much more painful than anticipated for many reasons:

  • plenty of filters to combine
  • live refresh that prepend and also updates the current rows
  • infinite scroll that append but only if nothing else is changing in the UI

When filtering the cursor changes, but when something change too fast: race condition can happen, so I had to use ref and tricks. I also had to aggregate rows into an array from which I could: update, append and prepend; I had to handle writing in this array from multiples places which in React is not easy.
The result is honestly quite flaky and very hard to grasp, I don't give it 2 weeks until something is broken.
Ideally we should remove at least the "update", only query before or after the cursor, and update the states of the rows with websockets.

Changes

  • Add cursor to searchOperations

  • Handle infinite scroll and live refresh for operations

  • Fix layout scroll box
    The DashboardLayout component was a mix of fixed and flex box which made the scroll area not consistent. For example a page without content would still have a scrollbar. I also added an option to allow a content to stretch the full width.

Test

(I added some fake lag to help me spot loading)

Screen.Recording.2024-05-27.at.20.50.33.mp4

@bodinsamuel bodinsamuel self-assigned this May 27, 2024
@@ -0,0 +1,36 @@
import * as React from 'react';
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't used it right now but I know the scroll is messed up on windows, it will be used when polishing

@khaliqgant
Copy link
Member

FYI i took a look at this last night but would like to due a more thorough review and pull it locally to see it in action. Let me know if this is blocking and I can expedite the review @bodinsamuel

@@ -128,20 +132,24 @@ export async function listOperations(opts: {
});
}

const cursor = opts.cursor ? parseCursor(opts.cursor) : undefined;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can parseCursor throw an exception?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, fine to me it will bubble up

query
});
const hits = res.hits;

const total = typeof hits.total === 'object' ? hits.total.value : hits.hits.length;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use the null coalescing operator here? hits.total?.value ?? hits.hits.length;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't because this object has multiple shapes unfortunately : number | estypes.SearchTotalHits | undefined

connections: z.array(z.string()).optional().default(['all']),
syncs: z.array(z.string()).optional().default(['all']),
period: z.object({ from: z.string().datetime(), to: z.string().datetime() }).optional()
integrations: z.array(z.string()).max(10).optional().default(['all']),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious about the max 10. How did you choose the value?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a conservative value right now, totally arbitrary to avoid slow search

@khaliqgant
Copy link
Member

Some unrelated feedback for logs:

  • when creating an unauthenticated connection the connection name doesn't show in the logs
    image
    image
    Happens for other connection creation as well it seems:
    image

  • Why is this a cursor pointer?
    image

  • If there is no payload should this box show at all?
    image

  • The back arrow seems to not be centered / mis aligned
    image

  • This is off center
    image

The live refresh jumps to a new pane if a new log comes in while you have another pane open which is a bit jarring

@bodinsamuel
Copy link
Collaborator Author

bodinsamuel commented May 29, 2024

Why is this a cursor pointer?

It's a placeholder for the moment, they insist on going with icons but it's hard to understand the meaning behind each icons.

If there is no payload should this box show at all?

For UI consistency, we decided to always show it. We might revisit that later.

The back arrow seems to not be centered / mis aligned

✅ Fixing, thanks

This is off center

✅ Actually it's not needed, thanks

the live refresh jumps to a new pane

✅ Ah yes I have fixed that in a subsequent PR, but let me backport it here.

when creating an unauthenticated connection the connection name doesn't show in the logs

Yes I have noted that in my todo, I need to fetch the connection when receiving the callback (for all type of integration)

@bodinsamuel bodinsamuel enabled auto-merge (squash) May 29, 2024 11:47
@bodinsamuel bodinsamuel disabled auto-merge May 29, 2024 11:51
@bodinsamuel bodinsamuel merged commit 9854182 into master May 29, 2024
21 checks passed
@bodinsamuel bodinsamuel deleted the feat/logs-pagination branch May 29, 2024 12:00
bodinsamuel added a commit that referenced this pull request May 29, 2024
## Context

Fixes NAN-998
Contributes to NAN-908

More or less the same than #2213
The main diff here is that we don't need to update the current page
state, so we use two cursor `cursorBefore` and `cursorAfter` the former
to live refresh (prepend) and the later to do infinite scroll (append).

## Changes

- **Add `cursorBefore` and `cursorAfter`** to searchMessages
Note: there is no concept of search_before in Elasticsearch, you just
reverse the sorting order and re-reverse the results to achieve it.

- Implement live refresh and infinite scroll in the UI


## Test

**(note the scrollbar changing position because we prepend, it's very
hard to manage unless we use our own scroll bar


https://github.com/NangoHQ/nango/assets/1637651/4c802379-7eb7-4234-b5c8-b2ca6dff8526
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants