-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Refactor useQueryExecution & add inline query execution status #4584
Conversation
…k instead of polling on the query result status. This is a step towards bigger refacotr. We should completly rewrite this class and split it into two: 1. QueryExecution -- executes a query and tracks status. 2. QueryResult -- represents the actual QueryResult and has the different utilities to use the results (although those might be moved into helpers).
@@ -154,20 +159,14 @@ function QuerySource(props) { | |||
return; | |||
} | |||
if (isDirty || !isEmpty(selectedText)) { | |||
executeAdhocQuery(selectedText); | |||
executeQuery(null, () => { |
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.
Need to improve the API here so we don't have to pass null
as first argument if we're passing in custom executor.
const [fullscreen, setFullscreen] = useState(false); | ||
const toggleFullscreen = useCallback(() => setFullscreen(!fullscreen), [fullscreen]); | ||
|
||
useEffect(() => { | ||
updateUrlSearch("fullscreen", fullscreen ? true : null); | ||
}, [fullscreen]); |
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 removed the sync w/ URL on purpose. I'm not sure we need it 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.
Yeah, I actually kept it thinking about sharing the URL and to have the same behavior the Dashboard page have. But both cases are not that important anyway.
{queryResult && queryResultData.status !== "done" && ( | ||
<div className="query-alerts m-t-15 m-b-15"> | ||
{(executionError || isExecuting) && ( | ||
<div style={{ position: "absolute", bottom: "75px", right: "20px", zIndex: 1000 }}> |
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.
Need to move this into the stylesheet.
/> | ||
</div> | ||
)} | ||
{(!queryResult || queryResultData.status === "done") && ( | ||
{true && ( |
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 we indeed keep viz always visible, need to remove this line.
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 this is probably the best option, the query view page just look so empty when loading and it makes the whole process of updating results look smoothier :)
shortcut="alt+f" | ||
onClick={toggleFullscreen}> | ||
<i className="zmdi zmdi-fullscreen" /> | ||
<Icon type={fullscreen ? "fullscreen-exit" : "fullscreen"} /> |
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.
Switched to Ant's icons. If we like it, we should use it in other places where we have "fullscreen" toggle.
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'm leaned towards the zmdi one, but I think I'm biased anyway.
newQueryResult | ||
.toPromise(onStatusChange) | ||
.then(queryResult => { | ||
// TODO: this should probably belong in the QueryEditor page. |
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.
A quick note: here (and in other similar places) we need to handle a case when component was destroyed during async operation (ignore all .then
/.catch
and callback calls otherwise all sort of setState
s will trigger error).
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 definitely in the direction I was thinking about (always having a result showing up). From the gif, imo the alert will need a different styling, I considered either having a notification (any from the Antd options) or just having the text saying the status of the execution in that footer. At most a colored Icon to emphasize the status. |
query.latest_query_data_id = queryResult.getId(); | ||
query.queryResult = queryResult; | ||
} | ||
// TODO: this belongs on the query page? |
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 tend to prefer this logic in here mainly for 2 reasons: 1 - Reduce complexity from Pages; 2 - It's a shared piece of code between View and Source.
In terms of where this code "belongs", it feels to me it could be in both the query page or in 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.
It's not for this PR, but eventually it makes sense to use useQueryExecute
in Widgets, where this logic isn't needed.
useEffect(() => { | ||
queryRef.current = query; | ||
executeQueryRef.current = executeQuery; | ||
}, [executeQuery, query]); |
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 safest way I could think to remove the dependencies from the useEffect
hook and make it execute only once.
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.
Is useEffect
really needed here? Seems you can leave only assignment - assigning value to ref.current
does not re-render component.
For "Empty state ("no results, try refresh") flashes on first load." I added a state to control whether the first results were loaded or not. So far I just keep it hidden until first results are loaded and it looks ok, apart from 2 cases:
For 2, it's not in the scope in here, but explore WebWorkers for heavy calculations is passing through my mind (I think this could help with Dashboard performance issues as well). |
} | ||
|
||
setExecutionState({ | ||
queryResult, |
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's also the option of keeping old queryResults when a query has an error, but you were thinking about an Error State?
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 what I had in mind here. Will experiment with both options and decide.
@arikfr, I think most of the functionality side of this feature is done (I checked from the checkboxes in the description). Now it's mostly a matter of iterating design for both desktop and mobile. For those I didn't understand very well what you mean:
|
15d0e36
to
d1ef80a
Compare
3db2377
to
f0338ce
Compare
👍 I think I got it now, I updated the QueryExecutionMetadata to be a separate component. Now it's the same for both view and edit.
|
It makes sense for the visualization to decide how it handles 0 rows. Why not render the viz in such case? |
When clicking on "Add Description" it should auto focus the input field. |
🤔, the simplest should be to just pass an Edit: What I had in mind not to be changing all visualizations was to do sth similar to cff0163 (have a property that would define when a vis is going to use the provided emptyState) |
- remove inputRef and use autoFocus attr
🪲 Just noticed there's some change specifically in this PR that breaks Filters (only multi-filters perhaps), seems to happening due to multiple React updates. E.g.: https://deploy-preview-4584--redash-preview.netlify.com/queries/334 Will investigate -> It seems sth to do with this (2f45fc5) Merge commit, I'll continue to see what may have gone wrong with it. Fixed in cf56791. Looks like it was a missing |
What will pass the empty state node? The viz implementation?
…On Fri, Feb 14, 2020, 00:04 Gabriel Dutra ***@***.***> wrote:
It makes sense for the visualization to decide how it handles 0 rows. Why
not render the viz in such case?
🤔, the simplest should be to just pass an EmptyState node to the
VisualizationRenderer. I'll see how easy it is to make the default
behavior for visualizations, but also not be hard to replace it,
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#4584?email_source=notifications&email_token=AAAROLASDAXG5UGBTGWBYGDRCW7VBA5CNFSM4KKULSI2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOELWZBGI#issuecomment-585994393>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAROLECNG2QJZTP5L5K57LRCW7VBANCNFSM4KKULSIQ>
.
|
QueryPage pass emptyState -> General Vis Render checks if visualization |
Let's minimize changes to the code or behavior and delegate to the visualization to handle this (which at the moment means do nothing -- like we had before). I'll try to think about this by considering the various visualizations & states (query page vs. widget) and come up with a definition for future improvement. |
@gabrieldutra I did two small changes here:
There are still few small design fixes to do, but I will merge this (and the parent PR) now and open a separate issue detailing them. |
What type of PR is this?
Description
While trying to add an inline Query Execution status that won't remove the current results in display, I realized that we need to refactor
useQueryExecution
to allow the view to retain current results.While the
QueryResult
class needs significant refactoring (probably split into two: one for execution and one for data), I did one change: add a callback to receive current execution status. This calllback allows us to remove the polling logic fromuseQueryResult
and actually removeuseQueryResult
entirely. I did keep thegetQueryResultData
helper, but we should probably remove it when we get to do said refactoring.I will add some more implementation notes in comments.
It's still not complete:
Related Tickets & Documents
Mobile & Desktop Screenshots/Recordings (if there are UI changes)