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

Restore one-click-review-submission feature #6964

Merged
merged 8 commits into from
Oct 5, 2023

Conversation

RobHannay
Copy link
Contributor

@RobHannay RobHannay commented Sep 27, 2023

Fixes #6963.

GitHub have changed their review submission modal so that it:

  • now has the radio buttons properly nested in a form
  • the radios' labels are not adjacent siblings anymore

Test URLs

This PR??

Screenshot

Capture d’écran 2023-09-27 à 10 21 11 PM
Enregistrement.de.l.ecran.2023-09-27.a.10.31.39.PM.mov

Description tooltips

image
image
image

source/features/one-click-review-submission.tsx Outdated Show resolved Hide resolved
@@ -43,18 +42,19 @@ function replaceCheckboxes(originalSubmitButton: HTMLButtonElement): void {
classes.push('tooltipped tooltipped-nw tooltipped-no-delay');
}

const label = document.querySelector(`label[for="${radio.id}"]`)?.textContent;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The labels are not adjacent siblings anymore, so I'm just grabbing the text from their actual <label>s.

Let me know if there's a way to do this that's more in keeping with the repo

for (const radio of radios) {
radio.closest('.form-checkbox')!.remove();
}
radios[0].closest('fieldset')!.remove();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The radios are now wrapped in a fieldset, which also has padding of its own, so it's cleaner just to remove.

Accessing the first radio and therefore its closest fieldset felt like the most straightforward way to achieve without having to find anything more specific about the fieldset (it only has an m-3 class)

@RobHannay RobHannay marked this pull request as ready for review September 27, 2023 21:32
@capfei
Copy link

capfei commented Sep 27, 2023

Not sure if it is considered better or not but I was able to get the button text by replacing {radio.nextSibling} with {radio.labels[0].innerHTML}.

@RobHannay
Copy link
Contributor Author

Not sure if it is considered better or not but I was able to get the button text by replacing {radio.nextSibling} with {radio.labels[0].innerHTML}.

Thanks @capfei, I like this suggestion

@fregante do you have a preference?

@fregante
Copy link
Member

fregante commented Sep 28, 2023

It's safer to deal with nodes, innerHTML triggers extra checks by Mozilla https://stackoverflow.com/q/45579400/288906

Something you could optimize for would be to maintain compatibility with the older version so that we don't break GitHub Enterprise users

@RobHannay
Copy link
Contributor Author

It's safer to deal with nodes, innerHTML triggers extra checks by Mozilla stackoverflow.com/q/45579400/288906

This is useful, thanks. I still kept textContent instead of innerHTML - does that mitigate the above?

Something you could optimize for would be to maintain compatibility with the older version so that we don't break GitHub Enterprise users

Ah yes, what's the usual process with this? When features get yolo-disabled I assume that also disables for GHE users?

@fregante fregante added the bug label Sep 28, 2023
@fregante
Copy link
Member

fregante commented Sep 28, 2023

This is useful, thanks. I still kept textContent instead of innerHTML - does that mitigate the above?

textContent is perfectly fine 👍

GitHub Enterprise users

Ah yes, what's the usual process with this?

It depends. For less visible features we just make the changes and wait for GHE users to open issues or submit patches, if they're necessary. See #6633

This feature is rather visible and quite important, so we can't risk breaking GHE users like #6963.

For GitHub changes that are introduced via Feature Preview, it's easy to toggle back and forth and see both DOM versions. In this case:

  • we write code that can work in both cases (e.g. keep the form attribute), OR
  • we use detection (e.g. if this element exist, OLD CODE, otherwise NEW CODE), keeping the changes to a minimum, OR
  • we keep a whole new copy of the code in cases where that detection makes the code too messy. See #6927

I suggest trying the first one, then we can tag a GHE user to test it out.

@fregante
Copy link
Member

When features get yolo-disabled I assume that also disables for GHE users?

Yes. That also means that if we ship a feature that breaks GHE, we have to yolo-disable it on GitHub.com too

@fregante
Copy link
Member

fregante commented Sep 28, 2023

@busches can you paste the popup’s prettified HTML here so that we can work on a compatible fix?

@RobHannay
Copy link
Contributor Author

Cool, thanks. I've merged the two version together to take a hybrid approach, where we always try the 'new' way but fallback to the old way if it's nullish.

Will await either the old DOM or someone to test it :)

@busches
Copy link
Member

busches commented Sep 28, 2023

Here's what this PR looks like on GHE 3.9.4:
image

Here's the HTML:
modal.txt

@RobHannay
Copy link
Contributor Author

Here's what this PR looks like on GHE 3.9.4: image

Here's the HTML: modal.txt

Thanks @busches. On it

const tooltip = radio.parentElement!.getAttribute('aria-label');
const labelNode = radio.labels?.[0];

const tooltip = labelNode?.nextElementSibling?.textContent;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, weirdly it looks from the previous DOM structure like there wasn't an aria-label on its parent anyway. I suspect that could have broken a while ago. Not sure exactly what the intended behaviour was before, but I've actually re-removed the hybrid approach because I don't believe it was doing anything

Copy link
Member

Choose a reason for hiding this comment

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

There are many versions of GHE and the DOM changes quite a bit. I'm thankfully on a more recent version, but 3.7-3.10 are currently supported by GH themselves.

Copy link
Member

Choose a reason for hiding this comment

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

This label is grabbing too much on GHE:

<label class="d-block">
        <input
          type="radio"
          name="pull_request_review[event]"
          value="comment"
          checked=""
        />
        Comment
        <p class="text-normal color-fg-muted">
          Submit general feedback without explicit approval.
        </p>
      </label>

Can do something "fun" like:

const label = labelNode?.nextElementSibling;
const nestedDescription = label.getElementsByTaName('p'); // GHE has a nested P with description inside the label
if (nestedDescription.length) {
   label.removeChild(nestedDescription[0]);
}
const tooltip = label.textContent;

I'm sure there's a better way to achieve that, but that should get us there.

form={formAttribute}
value={radio.value}
className={classes.join(' ')}
aria-label={tooltip!}
disabled={radio.disabled}
>
{radio.nextSibling}
{/* Old || new. Backwards-compat label content queries. Issue #6963. */}
{radio.nextSibling?.textContent?.trim() || labelNode?.textContent}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So this label fix works by:

  • Trying to use the old approach first,
  • Failing properly if nextSibling doesn't contain any text (in the new structure, it was containing a line break hence the trim)
  • Falling back to the new way of doing labelling which only has the single-word labels, where the description is now somewhere else

@RobHannay
Copy link
Contributor Author

I've hit two conflicting lint rules.

I want to use a logic OR for the label fallback; I can't use nullish coalescing operator because the "old" label will be an empty string if it doesn't exist. So I changed to use a ternary op a ? a : b which tbf is called out, and is worse imo.

Should I lint-ignore the nullish operator one or what? Is that only because it doesn't have enough type information?

// Generate the new buttons
for (const radio of radios) {
const tooltip = radio.parentElement!.getAttribute('aria-label');
const labelNode = radio.labels?.[0];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const labelNode = radio.labels?.[0];
const [label] = radio.labels!;

The rule is to only use ?. if we expect the element to be missing in some cases. If we know it won't be missing, we use !

This applies to your other code too

@@ -30,9 +29,13 @@ function replaceCheckboxes(originalSubmitButton: HTMLButtonElement): void {
);
}

const formAttribute = originalSubmitButton.getAttribute('form')!;
Copy link
Member

@fregante fregante Sep 28, 2023

Choose a reason for hiding this comment

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

Let's move this back to line 12 to keep the blame history

@fregante
Copy link
Member

fregante commented Oct 2, 2023

I hope to see this completed soon so I can merge it ☺️ if you see any awkward lint errors you can leave them broken and I'll take care of them

@fregante
Copy link
Member

fregante commented Oct 4, 2023

@busches could you help bring this over to the finish line so I can publish it without having to disable the feature on GHE?

@busches
Copy link
Member

busches commented Oct 5, 2023

@fregante I probably won't have time till Friday to take a look. If you have something to test, I get to that tomorrow.

@fregante fregante self-assigned this Oct 5, 2023
@fregante
Copy link
Member

fregante commented Oct 5, 2023

All good now. Testing for the GHE version was as easy as pasting that HTML replacing the original <form>, and the selector-observer automatically reapplied the changes. Thanks @busches!

I also made a change that was long overdue: I dropped the green background from the "comment" button. It was technically correct (green = default action, on GitHub) but it was confusing (green = approval)

Screenshot 6

@fregante fregante changed the title fix: one-click-review-submission to reflect GitHub's restructure of that modal Restore one-click-review-submission feature Oct 5, 2023
@fregante fregante merged commit 5247e6e into refined-github:main Oct 5, 2023
10 checks passed
@RobHannay
Copy link
Contributor Author

Thanks for getting it over the line 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

one-click-review-submission seems broken
4 participants