-
Notifications
You must be signed in to change notification settings - Fork 14.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
feat(dashboard): direct link to single chart/tab/header in dashboard #6964
feat(dashboard): direct link to single chart/tab/header in dashboard #6964
Conversation
d27f199
to
568120a
Compare
Grace and I synced up offline about this today. Documenting the outcome here.
TBD: Size of the icon. Is it large enough? Most likely wait for user feedback on this. Right now it is the same size as the icon in the chart share action. |
design plan sounds great! |
568120a
to
7ca14b5
Compare
7ca14b5
to
b0c5d5c
Compare
Codecov Report
@@ Coverage Diff @@
## master #6964 +/- ##
==========================================
+ Coverage 64.57% 64.67% +0.09%
==========================================
Files 422 425 +3
Lines 20581 20660 +79
Branches 2251 2280 +29
==========================================
+ Hits 13290 13361 +71
- Misses 7169 7175 +6
- Partials 122 124 +2
Continue to review full report at Codecov.
|
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.
Looking great overall! I had a few suggestions.
I would vote to change the name directLinkPath
to something that more clearly indicates what it is if you don't have context of this mechanism, "directLinkPath" could be anything. I think something like nestedLinkPath
or parentIds
or something could be more readable which I think is important, wdyt?
anchorLinkId: 'CHART-123', | ||
}; | ||
|
||
it('ComponentDidMount', () => { |
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 clear from this test name what's supposed to happen in componentDidMount
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.
my intention is this:
if location hash matched with component id, when AnchorLink is mounted, it should call DOM function scrollIntoView (bring chart/tab/header into center of view).
here is a discuss about similar way to test: enzymejs/enzyme#676
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.
sorry I mean include a description of what you expect in the it(_test description_, () => ...)
, componentDidMount
is not a description of what is expected to happen in componentDidMount
, if I read "componentDidMount"
in the CLI or CI report, I would have not clue what went wrong or what was expected to happen that failed.
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.
e.g., something like it('scrolls the AnchorLink into view upon mount', ...)
is all I meant.
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.
😂 description is updated.
anchorLinkId: PropTypes.string.isRequired, | ||
filters: PropTypes.object, | ||
showShortLinkButton: PropTypes.bool, | ||
placement: PropTypes.string, |
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.
could you enumerate the allowed types instead of simply string
? more specific = 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.
fixed.
@@ -43,6 +43,11 @@ const propTypes = { | |||
updateComponents: PropTypes.func.isRequired, | |||
handleComponentDrop: PropTypes.func.isRequired, | |||
logEvent: PropTypes.func.isRequired, | |||
directLinkPath: PropTypes.array, |
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.
array of what?
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.
fixed.
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
export default function({ currentComponent, directLinkPath = [] }) { |
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.
you should always name functions, it enables a better debugging experience.
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.
fixed
@@ -29,6 +29,7 @@ const propTypes = { | |||
emailSubject: PropTypes.string, | |||
emailContent: PropTypes.string, | |||
addDangerToast: PropTypes.func.isRequired, | |||
placement: PropTypes.string, |
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 enumerate specific values 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.
fixed
return dispatch => | ||
SupersetClient.post({ | ||
return dispatch => { | ||
dispatch({ type: UPDATE_COMPONENTS_PARENTS_LIST }); |
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 this is a Promise
you should be able to chain it with the POST
request. Is there a reason not 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.
dispatch
is synchronous function, the dispatched action can be asynchronous, like returning a promise, so that we can chain actions after it.
https://stackoverflow.com/questions/43276291/is-store-dispatch-in-redux-synchronous-or-asynchronous
The action { type: UPDATE_COMPONENTS_PARENTS_LIST }
is synchronous. Browser will always run this action first, then do post. (so that no need to chain in Promise object)
.then(response => { | ||
dispatch(saveDashboardRequestSuccess()); | ||
dispatch(addSuccessToast(t('This dashboard was saved successfully.'))); | ||
return response; |
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.
typically the assumption with redux actions is that you can continue to chain promises onto them. are you certain that returning a response
doesn't break this promise chain? that's why it was written the way it was.
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, tested dashboard save flow. For the same reason (both these 2 actions are synchronous), i just feel no need to wrap them into Promise.
@@ -54,10 +55,12 @@ const propTypes = { | |||
showBuilderPane: PropTypes.bool, | |||
handleComponentDrop: PropTypes.func.isRequired, | |||
toggleBuilderPane: PropTypes.func.isRequired, | |||
directLinkPath: PropTypes.array, |
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.
array of what?
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.
fixed.
@@ -45,6 +46,7 @@ const propTypes = { | |||
editMode: PropTypes.bool.isRequired, | |||
renderHoverMenu: PropTypes.bool, | |||
logEvent: PropTypes.func.isRequired, | |||
directLinkPath: PropTypes.array, |
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.
array of what?
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.
fixed.
...state, | ||
}; | ||
|
||
const doUpdate = currentComponent => { |
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 you please aadd a component for what this is doing? since it's somewhat complex and very important!
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 separated this function out into a util function, so that easier to add test.
I am thinking to name prop as |
b0c5d5c
to
3267255
Compare
ping @williaster all comments are address. |
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
export default function findTabIndexByComponentId({ |
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 if we should have unit tests for this or not?
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.
added a couple tests.
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 couple small comments but looks good overall 👍 can you post a final screenshot of the updated UI/designs?
3267255
to
5698b58
Compare
the expected UI is updated in description |
@elibrumbaugh do you want to do any more design review? overall looks good to me except the link icons don't look vertically aligned with the tab/title text. I'd expect them to be vertically centered instead of the link top-aligned with the text. |
5698b58
to
10c97fa
Compare
We always render first tab when dashboard opens. When a dashboard has multiple root tabs and nested row-level tabs, it will takes a few clicks to navigate to the point of interest. This feature is to add direct link for a UI component (chart, tab, header) in dashboard.
directLinkPath
which is the list of component ids from root to element id.parents
attribute for each UI component.Result
Direct link to tab
Direct link to chart
Direct link to header
@williaster @kristw @michellethomas @elibrumbaugh @mistercrunch