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

fix: Owners selection in dataset edit UX #17063

Merged
merged 14 commits into from
Oct 13, 2021
Merged

fix: Owners selection in dataset edit UX #17063

merged 14 commits into from
Oct 13, 2021

Conversation

hughhhh
Copy link
Member

@hughhhh hughhhh commented Oct 11, 2021

SUMMARY

The original dataset edit screen didn't populate owners and wasn't allowing users to properly query the db for potentially new owners.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

edit-owners.mov

TESTING INSTRUCTIONS

  1. Goto datasets
  2. Click on edit dataset in one of list items
  3. Goto settings
  4. Change owners
  5. Save
  6. Make sure owners in list reflect owners you chose

ADDITIONAL INFORMATION

@hughhhh hughhhh force-pushed the hugh/edit-owners branch 4 times, most recently from d24364f to 9c92b7e Compare October 11, 2021 20:24
@codecov
Copy link

codecov bot commented Oct 11, 2021

Codecov Report

Merging #17063 (7c679b9) into master (11d52cb) will decrease coverage by 0.21%.
The diff coverage is 90.47%.

❗ Current head 7c679b9 differs from pull request most recent head a45e94c. Consider uploading reports for the commit a45e94c to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master   #17063      +/-   ##
==========================================
- Coverage   76.89%   76.67%   -0.22%     
==========================================
  Files        1031     1031              
  Lines       55183    55188       +5     
  Branches     7505     7505              
==========================================
- Hits        42432    42316     -116     
- Misses      12499    12620     +121     
  Partials      252      252              
Flag Coverage Δ
hive ?
mysql 81.92% <100.00%> (+<0.01%) ⬆️
postgres 81.93% <100.00%> (+<0.01%) ⬆️
presto ?
python 82.02% <100.00%> (-0.42%) ⬇️
sqlite 81.61% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...ontend/src/views/CRUD/data/dataset/DatasetList.tsx 65.92% <0.00%> (ø)
...erset-frontend/src/datasource/DatasourceEditor.jsx 73.85% <92.85%> (ø)
...perset-frontend/src/datasource/DatasourceModal.tsx 75.00% <100.00%> (ø)
superset/connectors/base/models.py 88.25% <100.00%> (+0.11%) ⬆️
superset/views/core.py 76.94% <100.00%> (+0.03%) ⬆️
superset/db_engines/hive.py 0.00% <0.00%> (-85.19%) ⬇️
superset/db_engine_specs/hive.py 69.76% <0.00%> (-17.06%) ⬇️
superset/db_engine_specs/presto.py 83.47% <0.00%> (-6.91%) ⬇️
superset/views/database/mixins.py 81.03% <0.00%> (-1.73%) ⬇️
superset/connectors/sqla/models.py 85.59% <0.00%> (-1.66%) ⬇️
... and 6 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 11d52cb...a45e94c. Read the comment docs.

@@ -374,6 +374,40 @@ const defaultProps = {
onChange: () => {},
};

function OwnersSelector({ datasource, onChange }) {
const selectedOwners = datasource.owners.map(owner => ({
Copy link
Member

Choose a reason for hiding this comment

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

will datasource and owners always have a value?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

@eschutho eschutho Oct 11, 2021

Choose a reason for hiding this comment

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

ok, great. then per the below comment, it looks like selectedOwners will never be null or undefined, so you don't need the || []

ariaLabel={t('Select owners')}
mode="multiple"
name="owners"
value={selectedOwners || []}
Copy link
Member

Choose a reason for hiding this comment

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

will selectedOwners ever be null? Unless there's an error above in the map, this value will already default to []

value={selectedOwners || []}
options={loadOptions}
onChange={newOwners => {
onChange(newOwners);
Copy link
Member

Choose a reason for hiding this comment

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

you should be able to just pass onChange as the function instead of writing a new one

})),
totalCount: response.json.count,
}));
});
Copy link
Member

@eschutho eschutho Oct 11, 2021

Choose a reason for hiding this comment

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

I believe if you don't pass any dependencies to useMemo, it will still recalculate on every rerender. Do you need the useMemo here? It looks like all it will do on rerender is create the query variable.

Copy link
Member Author

Choose a reason for hiding this comment

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

for some reason the select component fails with out the useMemo we should look into that more but lets leave it for now

Copy link
Member

Choose a reason for hiding this comment

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

I'm going to push back here... let's try to understand why useMemo is needed? My understanding is the same as Elizabeth's, without the dependency array it's a no-op.

We've had a lot of quality issues lately, let's not commit code that we don't understand what's doing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Talking to @michael-s-molina about useMemo vs. useCallback, if you fire the function with the same parameters (search, page, pageSize in this case) this code won't re run. So it is better for us to use useMemo since we'll be having the parameters for populating the select with owners options.

Copy link
Member

Choose a reason for hiding this comment

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

I believe if you don't pass any dependencies to useMemo, it will still recalculate on every rerender.

You're correct. If no array is provided, a new value will be computed on every render. In this case, we are passing a function to the options prop of the Select and this prop is used by useEffect hooks which means we don't want to recompute it unless the dependencies change. We could use a useCallback here but we also don't want to execute the function if it receives the same parameters. That's why we generally use useMemo with a dependency array (sometimes empty, sometimes not).

Copy link
Member

Choose a reason for hiding this comment

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

Just to let you know, we are already working on the documentation for each prop of the component and the different modes of operation. We're also going to update the Storybook with these docs.

Copy link
Member

@betodealmeida betodealmeida left a comment

Choose a reason for hiding this comment

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

Looks good, I just left 2 small nits.

Comment on lines 402 to 404
onChange={newOwners => {
onChange(newOwners);
}}
Copy link
Member

Choose a reason for hiding this comment

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

Nit:

Suggested change
onChange={newOwners => {
onChange(newOwners);
}}
onChange={onChange}

const loadOptions = useMemo(() => (search = '', page, pageSize) => {
const query = rison.encode({ filter: search, page, page_size: pageSize });
return SupersetClient.get({
endpoint: `/api/v1/chart/related/owners?q=${query}`,
Copy link
Member

Choose a reason for hiding this comment

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

The result is the same, but let's use dataset here instead of chart:

Suggested change
endpoint: `/api/v1/chart/related/owners?q=${query}`,
endpoint: `/api/v1/dataset/related/owners?q=${query}`,

@yousoph
Copy link
Member

yousoph commented Oct 11, 2021

/testenv up

@github-actions
Copy link
Contributor

@yousoph Ephemeral environment spinning up at http://35.86.147.0:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

@rosemarie-chiu
Copy link
Contributor

I'm not able to select user from the dropdown.
CleanShot 2021-10-11 at 15 17 27

@hughhhh
Copy link
Member Author

hughhhh commented Oct 12, 2021

/testenv up

@github-actions
Copy link
Contributor

@hughhhh Ephemeral environment spinning up at http://34.209.136.120:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

@hughhhh
Copy link
Member Author

hughhhh commented Oct 12, 2021

/testenv up

@github-actions
Copy link
Contributor

@hughhhh Ephemeral environment spinning up at http://34.217.1.111:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

@hughhhh
Copy link
Member Author

hughhhh commented Oct 12, 2021

/testenv up

@github-actions
Copy link
Contributor

@hughhhh Ephemeral environment spinning up at http://54.201.92.110:8080. Credentials are admin/admin. Please allow several minutes for bootstrapping and startup.

Comment on lines 269 to 272
"owners": [
{"label": f"{owner.first_name} {owner.last_name}", "value": owner.id}
for owner in self.owners
],
Copy link
Member

Choose a reason for hiding this comment

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

label and value are concerns tied to the component you're using in the frontend. Let's discuss this a bit more.

Copy link
Member

Choose a reason for hiding this comment

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

I assume we have endpoints where we can get full user information, including first name and last name. The component should fetch from there and build label and value however it needs.

})),
totalCount: response.json.count,
}));
}, []);
Copy link
Member

Choose a reason for hiding this comment

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

Curious to what the error is when you just use the function directly?

Using useCallback is basically the same as useMemo, though now you have an empty array of dependencies so it will memoize forever, which is what we want.

Copy link
Member Author

Choose a reason for hiding this comment

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

i had the wrong function schema 😓 rookie move

Copy link
Member

Choose a reason for hiding this comment

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

Let's clarify the concepts a little bit (https://reactjs.org/docs/hooks-reference.html)

  • useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed. This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.
  • useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.

Curious to what the error is when you just use the function directly?

If we pass the function directly, this means that every time the component renders, it will create a new instance of the function, which will trigger the useEffects inside the Select component, which will call the function and execute it unnecessarily.

If we use useCallback it means that the function instance will be the same between renders, avoiding unnecessary executions. But if while interacting with the component, this function is called two or more times with the same search, page, and pageSize, useCallback won't prevent unnecessary executions. That's why we use useMemo. One example of this scenario is if we change a property like useFetchOnlyOnSearch which will trigger a new call to the function with the same parameters.

@junlincc
Copy link
Member

does this PR fix #15530 and #16883?

@sadpandajoe
Copy link
Contributor

🏷️ 2021.40

@hughhhh
Copy link
Member Author

hughhhh commented Oct 12, 2021

does this PR fix #15530 and #16883?

Yup :)

@junlincc
Copy link
Member

Yup :)

Thanks! I will update the the pr description accordingly. 🙏

@hughhhh hughhhh merged commit 959fd76 into master Oct 13, 2021
@github-actions
Copy link
Contributor

Ephemeral environment shutdown and build artifacts deleted.

sadpandajoe pushed a commit to preset-io/superset that referenced this pull request Oct 13, 2021
* boilerplate

* update owner select component

* this is working

* update onchange

* refactorig

* you need to useMemo or things break

* update test

* prettier

* move logic into bootstrap data endpoint

* address concerns

* oops

* oops

* fix test

(cherry picked from commit 959fd76)
@geido geido mentioned this pull request Oct 20, 2021
9 tasks
@eschutho eschutho added the v1.4 label Oct 26, 2021
eschutho pushed a commit to preset-io/superset that referenced this pull request Oct 27, 2021
* boilerplate

* update owner select component

* this is working

* update onchange

* refactorig

* you need to useMemo or things break

* update test

* prettier

* move logic into bootstrap data endpoint

* address concerns

* oops

* oops

* fix test

(cherry picked from commit 959fd76)
opus-42 pushed a commit to opus-42/incubator-superset that referenced this pull request Nov 14, 2021
* boilerplate

* update owner select component

* this is working

* update onchange

* refactorig

* you need to useMemo or things break

* update test

* prettier

* move logic into bootstrap data endpoint

* address concerns

* oops

* oops

* fix test
@mistercrunch mistercrunch added 🍒 1.4.0 🍒 1.4.1 🍒 1.4.2 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.5.0 labels Mar 13, 2024
@mistercrunch mistercrunch deleted the hugh/edit-owners branch March 26, 2024 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels preset:2021.40 size/M v1.4 🍒 1.4.0 🍒 1.4.1 🍒 1.4.2 🚢 1.5.0
Projects
None yet
9 participants