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

Enable users to jump arbitrary page numbers from text field #739

Merged

Conversation

nabenabe0928
Copy link
Collaborator

@nabenabe0928 nabenabe0928 commented Dec 21, 2023

Contributor License Agreement

This repository (optuna-dashboard) and Goptuna share common code.
This pull request may therefore be ported to Goptuna.
Make sure that you understand the consequences concerning licenses and check the box below if you accept the term before creating this pull request.

  • I agree this patch may be ported to Goptuna by other Goptuna contributors.

Reference Issues/PRs

This PR solves issue#504.

What does this implement/fix? Explain your changes.

This PR adds the following features:

  1. a text field to specify which page number to jump in DataGrid
  2. the pagination for DataGrid will appear only if we have data,
  3. the pagination text field for DataGrid will appear only if we have more than 4 pages, and
  4. the pagination information is slightly modified to tell the page number.

After the Modification

  1. Too many rows to click next many times.
    image

  2. We can specify the page number to jump.
    image

  3. The page number was successfully jumped to the specified page after hitting the enter key.

image

Copy link

codecov bot commented Dec 21, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (616f08c) 68.20% compared to head (5f73021) 69.48%.
Report is 49 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #739      +/-   ##
==========================================
+ Coverage   68.20%   69.48%   +1.27%     
==========================================
  Files          35       35              
  Lines        2334     2353      +19     
==========================================
+ Hits         1592     1635      +43     
+ Misses        742      718      -24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@nabenabe0928 nabenabe0928 marked this pull request as ready for review December 22, 2023 04:15
@nabenabe0928
Copy link
Collaborator Author

Could you review this PR?
@eukaryo @keisuke-umezawa

@keisuke-umezawa
Copy link
Member

I will review it detail later, but can you add e2e test for loading journal storage file similar to sqlite here?

def test_load_storage(
page: Page,
server_url: str,
) -> None:
study_name = "single-objective"
url = f"{server_url}"
def create_storage_file(filename: str):
import optuna
storage = optuna.storages.RDBStorage(f"sqlite:///{filename}")
study = optuna.create_study(study_name=study_name, storage=storage)
def objective(trial: optuna.Trial) -> float:
x1 = trial.suggest_float("x1", 0, 10)
x2 = trial.suggest_float("x2", 0, 10)
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective, n_trials=100)
with tempfile.TemporaryDirectory() as dir:
with tempfile.NamedTemporaryFile() as fp:
filename = fp.name
path = os.path.join(dir, filename)
create_storage_file(filename)
page.goto(url)
with page.expect_file_chooser() as fc_info:
page.get_by_role(
"button",
name="Load an Optuna Storage Drag your SQLite3 file here or click to browse.",
).click()
file_chooser = fc_info.value
file_chooser.set_files(path)
page.get_by_role("link", name=study_name).click()
def count_components(page: Page, component_name: str):
component_count = page.evaluate(
f"""() => {{
const components = document.querySelectorAll('.{component_name}');
return components.length;
}}"""
)
return component_count
count = count_components(page, "MuiCardContent-root")
assert count == 6

Copy link
Member

@keisuke-umezawa keisuke-umezawa left a comment

Choose a reason for hiding this comment

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

I left some comments. Could you check them?

To add one more comment, can we make the box smaller especially for its hight because it is overlapped with the above line?
スクリーンショット 2024-01-04 0 59 15

page={page}
labelDisplayedRows={({ page }) =>
`${page + 1} of ${maxPageNumber}`
}
Copy link
Member

Choose a reason for hiding this comment

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

[nits] It seems that we should use default values here. I surveyed some templates for pagination and this one is similar to what you implemented. https://ui-patterns.com/patterns/Pagination/examples/691

Copy link
Member

Choose a reason for hiding this comment

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

How about adding max page number somewhere around PaginationTextFieldComponent?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

[Question] Does this mean I should simply remove labelDisplayedRows and add maxPageNumber to the text field?
I reflected what I assumed from your response, so could you confirm it from my modification?

Copy link
Member

Choose a reason for hiding this comment

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

Sorry for my poor explanation. You understood what I meant and fixed them. Thank you.

optuna_dashboard/ts/components/DataGrid.tsx Outdated Show resolved Hide resolved
) => {
event.preventDefault()
const newPage = parseInt(specifiedPageText, 10)
setSpecifiedPageText("") // reset the input field
Copy link
Member

Choose a reason for hiding this comment

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

[nits] This line should be the last line of handleSubmitPageNumber.

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 fixed it, but could you tell me why it would be better for my knowledge?
Is it just because of code preference or because of its code behavior?

Copy link
Member

Choose a reason for hiding this comment

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

Sorry for my poor explanation. The setSpecifiedPageText("") should be the procedure if the process is correctly handled. In that sense, this line should be put on the last line. More detail, the reason is that if we use early return e.g. if (Number.isNaN(newPage)) {, we should keep text in the field because the user can fix it later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you for the clarification! Your explanation actually makes sense")

optuna_dashboard/ts/components/DataGrid.tsx Outdated Show resolved Hide resolved
optuna_dashboard/ts/components/DataGrid.tsx Show resolved Hide resolved
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
{maxPageNumber > 4 ? (
Copy link
Member

Choose a reason for hiding this comment

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

[question] Why did you choose 4 here?

Copy link
Collaborator Author

@nabenabe0928 nabenabe0928 Jan 5, 2024

Choose a reason for hiding this comment

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

I will quickly leave a comment before I forget.
For the other comments, I will address then when I'm back to the work!
The reason is very simple: When we move from page X to Y by the text field, we need three actions. (1) Click the text field, (2) Type a number, (3) Hit the enter key.
Meanwhile when we would like to move any pages for 4-page data grid, we need to make less than or equal to three actions from A to B. Namely, we need to click the prev/next key less than or equal to three times.
That's why it's unnecessary (or at least, not more efficient ) to use the text field in this case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is it better to let it stay always?
Plus, is there any other stuff to address?

Copy link
Member

Choose a reason for hiding this comment

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

I understand it. But the reason is not so obvious if we do not put code comment there. We can choose the following options:

  1. Add comments for 4,
  2. Change the number from 4 to 2 (because 2 is much easier to understand the reason), or
  3. Always show it.

@nabenabe0928 nabenabe0928 force-pushed the feat/add-more-flexible-pagination branch 2 times, most recently from 501dd2f to 37fbdd6 Compare January 15, 2024 11:44
@nabenabe0928
Copy link
Collaborator Author

nabenabe0928 commented Jan 15, 2024

I will review it detail later, but can you add e2e test for loading journal storage file similar to sqlite here?

def test_load_storage(
page: Page,
server_url: str,
) -> None:
study_name = "single-objective"
url = f"{server_url}"
def create_storage_file(filename: str):
import optuna
storage = optuna.storages.RDBStorage(f"sqlite:///{filename}")
study = optuna.create_study(study_name=study_name, storage=storage)
def objective(trial: optuna.Trial) -> float:
x1 = trial.suggest_float("x1", 0, 10)
x2 = trial.suggest_float("x2", 0, 10)
return (x1 - 2) ** 2 + (x2 - 5) ** 2
study.optimize(objective, n_trials=100)
with tempfile.TemporaryDirectory() as dir:
with tempfile.NamedTemporaryFile() as fp:
filename = fp.name
path = os.path.join(dir, filename)
create_storage_file(filename)
page.goto(url)
with page.expect_file_chooser() as fc_info:
page.get_by_role(
"button",
name="Load an Optuna Storage Drag your SQLite3 file here or click to browse.",
).click()
file_chooser = fc_info.value
file_chooser.set_files(path)
page.get_by_role("link", name=study_name).click()
def count_components(page: Page, component_name: str):
component_count = page.evaluate(
f"""() => {{
const components = document.querySelectorAll('.{component_name}');
return components.length;
}}"""
)
return component_count
count = count_components(page, "MuiCardContent-root")
assert count == 6

@keisuke-umezawa
It does not seem to me that this modification relates to my PR, but should I also include it in this PR?

@keisuke-umezawa
Copy link
Member

@keisuke-umezawa
It does not seem to me that this modification relates to my PR, but should I also include it in this PR?

So sorry, it is a wrong message. you can ignore it.

Copy link
Member

@keisuke-umezawa keisuke-umezawa left a comment

Choose a reason for hiding this comment

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

It looks good to me other than a nit. I will merge it after your change.

onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
{maxPageNumber > 4 ? (
Copy link
Member

Choose a reason for hiding this comment

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

I understand it. But the reason is not so obvious if we do not put code comment there. We can choose the following options:

  1. Add comments for 4,
  2. Change the number from 4 to 2 (because 2 is much easier to understand the reason), or
  3. Always show it.

@nabenabe0928 nabenabe0928 force-pushed the feat/add-more-flexible-pagination branch from 37fbdd6 to 5f73021 Compare January 22, 2024 04:29
@nabenabe0928
Copy link
Collaborator Author

@keisuke-umezawa I reflected your suggestion

Copy link
Member

@keisuke-umezawa keisuke-umezawa left a comment

Choose a reason for hiding this comment

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

LGTM! Thank you for working on it.

@keisuke-umezawa keisuke-umezawa merged commit 6c7dc62 into optuna:main Jan 23, 2024
10 checks passed
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