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

Labels editing and validation #3426

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

YuliaKrimerman
Copy link
Contributor

@YuliaKrimerman YuliaKrimerman commented Nov 4, 2024

RHOAIENG-6994
RHOAIENG-6995

Description

[

Screen.Recording.2024-11-06.at.1.31.09.PM.mov

](url)

When going to model/version Detail, editing the labels are behaving as inline labels and also now have a validation for a case a new label already exists ( side not the background of the error message is red in paternfly )

How Has This Been Tested?

on the UI

Test Impact

Working on adding test while getting feedback on the implementation

Request review criteria:

Self checklist (all need to be checked):

  • The developer has manually tested the changes and verified that the changes work
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has added tests or explained why testing cannot be added (unit or cypress tests for related changes)

If you have UI changes:

  • Included any necessary screenshots or gifs if it was a UI change.
  • Included tags to the UX team if it was a UI/UX change.

After the PR is posted & before it merges:

  • The developer has tested their solution on a cluster by using the image produced by the PR to main

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress This PR is in WIP state label Nov 4, 2024
Copy link
Contributor

openshift-ci bot commented Nov 4, 2024

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign manosnoam for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@YuliaKrimerman
Copy link
Contributor Author

@yih-wang Haley please take a look as well, and let me know what you think

Copy link
Contributor

@mturley mturley left a comment

Choose a reason for hiding this comment

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

One quick comment from looking at the video - I will give a more thorough review when I get a chance

Comment on lines 84 to 88
editableProps={{
'aria-label': 'Add label',
defaultValue: '',
'data-testid': 'add-label-input',
}}
Copy link
Contributor

@mturley mturley Nov 4, 2024

Choose a reason for hiding this comment

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

The way I understand the mockup, I don't think we want the "Add label" button to be an editable label itself. It can just be a button like before, but instead of its onClick opening a modal, it should add a new label called "New label" via setUnsavedLabels(). Then the user can click that label to edit it.

Copy link

Choose a reason for hiding this comment

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

+1 to @mturley.
@YuliaKrimerman here's a PF demo of how should the Add label work: https://www.patternfly.org/components/label/#editable-label-group-with-add-button Hope it helps.

@YuliaKrimerman
Copy link
Contributor Author

@mturley @yih-wang I think I got it now. Updated the video.

@yih-wang
Copy link

yih-wang commented Nov 6, 2024

Thanks for the updates @YuliaKrimerman! My only comment is when handling duplicate label errors, the newly created label should be marked in red to indicate the error. From the video, it looks like the existing label is flagged instead.

@yih-wang
Copy link

yih-wang commented Nov 6, 2024

And one question to the loading time - from the video the newly added label takes a while to load after saving. Would this delay also occur in the production environment, or is it only in development environment? It’s a bit confusing to me before the label is loaded, so if this is expected in production, adding a loading state might help improve clarity.

Copy link

codecov bot commented Nov 6, 2024

Codecov Report

Attention: Patch coverage is 84.84848% with 10 lines in your changes missing coverage. Please review.

Project coverage is 85.75%. Comparing base (1636d39) to head (eed547a).
Report is 66 commits behind head on main.

Files with missing lines Patch % Lines
.../components/EditableLabelsDescriptionListGroup.tsx 85.48% 9 Missing ⚠️
...egistry/screens/ModelVersions/ModelDetailsView.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3426      +/-   ##
==========================================
+ Coverage   85.12%   85.75%   +0.62%     
==========================================
  Files        1338     1347       +9     
  Lines       30127    30681     +554     
  Branches     8274     8547     +273     
==========================================
+ Hits        25647    26310     +663     
+ Misses       4480     4371     -109     
Files with missing lines Coverage Δ
...d/src/components/DashboardDescriptionListGroup.tsx 100.00% <100.00%> (ø)
...ns/ModelVersionDetails/ModelVersionDetailsView.tsx 97.61% <100.00%> (+2.61%) ⬆️
...egistry/screens/ModelVersions/ModelDetailsView.tsx 80.00% <0.00%> (ø)
.../components/EditableLabelsDescriptionListGroup.tsx 83.11% <85.48%> (+32.46%) ⬆️

... and 133 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

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

@yih-wang
Copy link

yih-wang commented Nov 7, 2024

Thanks for the updates @YuliaKrimerman! All look good now!

One thing that wasn’t part of the original design proposal but stood out to me as potentially confusing from the video - currently, after saving an edit, the label list keeps its original expanded/collapsed state. This means if the list was collapsed before editing, and the user enters the edit mode then saves any changes, the newly added label isn’t visible because the list stays collapsed. To avoid this potential confusion, it might be clearer to have the label list automatically expand after any edit is saved, regardless of its original collapsed/expanded state.

Anyway it doesn't belong to the original scope of the issue, and I don't know how much work it needs, so not sure whether we should create a new story to improve this experience separately in a future sprint @mturley

@YuliaKrimerman YuliaKrimerman changed the title WIP - Labels editing and validation Labels editing and validation Nov 7, 2024
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress This PR is in WIP state label Nov 7, 2024
Copy link
Contributor

@manaswinidas manaswinidas left a comment

Choose a reason for hiding this comment

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

@YuliaKrimerman can you add testing instructions in the "How has this been tested?" section of PR description?

modelVersionDetails.findAddLabelButton().click();

// Check label exists and is visible
cy.findByTestId('editable-label-New Label').should('exist');
Copy link
Contributor

Choose a reason for hiding this comment

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

can findLabel('New label') be used instead ofeditable-label-New label? I believe findLabel was added for this?

cy.findByTestId('editable-label-New Label').click();

// Type the new label
cy.get('input[data-testid="edit-label-input-New Label"]').should('exist');
Copy link
Contributor

Choose a reason for hiding this comment

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

same applies here: modelVersionDetails.findLabelInput('New Label') instead of 'input[data-testid="edit-label-input-New Label"]' and the following 2-3 lines...


cy.findByTestId('editable-label-Testing label').click();

cy.get('input[data-testid="edit-label-input-Testing label"]')
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

it('should handle label validation', () => {
modelVersionDetails.findEditLabelsButton().click();

cy.findByTestId('editable-label-Testing label').click();
Copy link
Contributor

Choose a reason for hiding this comment

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

use findLabelInput('Testing label') instead

isSavingEdits={isSavingEdits}
contentWhenEditing={
<DashboardDescriptionListGroup
data-testid="editable-labels-group"
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this test-id necessary? I don't see this test-id used anywhere.

<LabelGroup
data-testid="label-group"
data-testid="editable-label-group"
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see this testid used anywhere.

@@ -62,6 +64,7 @@ const ModelDetailsView: React.FC<ModelDetailsViewProps> = ({
)
.then(refresh)
}
data-testid="model-labels"
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see this testid anywhere

Copy link
Contributor

@mturley mturley left a comment

Choose a reason for hiding this comment

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

Hey @YuliaKrimerman, progress is looking great here but we need a bit of refactoring.

newText: string,
currentLabel?: string,
) => {
const error = validateLabel(newText, currentLabel);
Copy link
Contributor

@mturley mturley Nov 8, 2024

Choose a reason for hiding this comment

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

If I cause an error (e.g. add a duplicate label) and don't fix it, then add another label, the error disappears and submission is allowed even though there is still a problem. This is because we store errors in state and we can only have one at a time.

Errors don't need to be state here, they can be derived from the existing unsavedLabels state on each render. I think instead of having the labelErrors come from React.useState, we can just have a const labelErrors object that we compute as part of the rendering logic of the component. That way, simply the call to setUnsavedLabels that puts us in an error state will cause errors to appear. That does mean a bit of refactoring, since you won't be validating a specific label anymore but validating the list of labels. This also means we may have multiple errors to display - if you have two sets of duplicate labels, you'll want to call them both out.

Comment on lines +51 to +67
if (error) {
setLabelErrors({ [newText]: error });
setUnsavedLabels((prev) => {
const filtered = prev.filter((label) => label !== currentLabel);
return [...filtered, newText];
});
} else if (newText) {
setUnsavedLabels((prev) => {
if (currentLabel) {
return [...prev, newText];
}
const filtered = prev.filter((label) => label !== currentLabel);
return [...filtered, newText];
});
setLabelErrors({});
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure why the setUnsavedLabels behavior is different if there's an error vs if there isn't. This may resolve itself if you move the validation from here to render time, but I'm pretty sure handleEditComplete should update the unsaved labels state the same way no matter whether there is an error to show. I think this first call in your if (error) case is correct:

      setUnsavedLabels((prev) => {
        const filtered = prev.filter((label) => label !== currentLabel);
        return [...filtered, newText];
      });

Your other case is making it so any time edit focus is lost, if the user didn't enter duplicate label text, the old label is not filtered out on update and we end up with another duplicate:

Screen.Recording.2024-11-08.at.12.56.50.PM.mov

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.

5 participants