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

ENH Pre-render the LinkField in entwine #241

Conversation

maxime-rainville
Copy link
Contributor

@maxime-rainville maxime-rainville commented Mar 1, 2024

This PR is making the pre-rendered UI more pleasing by pre-rendering somethings.

Before

no-pre-load-linkfield-2024-03-01_21.55.02.webm

Before React boots

Screenshot from 2024-03-01 21-57-31

Before LinkField gets its data back

Screenshot from 2024-03-01 22-00-00

After

pre-load-linkfield-2024-03-01_21.53.59.webm

Before React boots

Screenshot from 2024-03-01 22-02-10

Before LinkField gets its data back

image

Parent issue

Depends on

if (!linkData) {
// Render dataless item to provide a good loading experience, except if we have single link field
const linkData = data[linkID] || {};
if (!linkData && !isMulti) {
continue;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

By not skipping the link entries for which we don't have data yet, we'll render a list of placeholder LinkPickerTitle. This will avoids having a big jump on the page once the data finally gets back to us.

@@ -446,7 +446,7 @@ const LinkField = ({

const saveRecordFirst = !loadingError && ownerID === 0;
const renderLoadingError = loadingError;
const renderPicker = !loadingError && !inHistoryViewer && !saveRecordFirst && (isMulti || Object.keys(data).length === 0);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was needed because a disabled LinkField with pe-existing data would briefly render a picker and a place holder link.

With this change, it only renders the picker.


public function LinkIDs(): ArrayList
{
return ArrayList::create($this->dataValue());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This wraps the IDs in an ArrayList so the SS template can loop over them.

Copy link
Member

@GuySartorelli GuySartorelli left a comment

Choose a reason for hiding this comment

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

Are the new templates always used for rendering those elements, or does react render them separately?
If the latter, this gives the false impression that you can change how the linkfield gets rendered by changing templates.

@maxime-rainville
Copy link
Contributor Author

Enwtine only.

Most of these templates were pre-existing, so you could easily have been confused into thinking that you could override them. If you did try to customise them, you would quickly notice that your changes a being nuked once React boots.

I can rename the templates and/or add extra comments to make it clear this is an Entwine only construct.

@GuySartorelli
Copy link
Member

Enwtine only.

Linkfield is a react component, so that doesn't really make any sense

Most of these templates were pre-existing, so you could easily have been confused into thinking that you could override them. If you did try to customise them, you would quickly notice that your changes a being nuked once React boots.

The existing ones CAN be overridden, but notably are used to bootstrap the react component.

The new templates mirror something that is rendered by react - so changing these templates will only change the display of a linkfield before any react is bootstrapped for the field if I'm not mistaken.

At the very very least these templates need comments at the top indicating that they are only for use in rendering the field before react has bootstrapped and will not affect the display of the rendered react component.

@maxime-rainville maxime-rainville self-assigned this Mar 3, 2024
@maxime-rainville
Copy link
Contributor Author

Behat build is broken. I thought it was intermittent, but it seems to be a legit failure.

I'll add comments to the template while I'm at it.

@maxime-rainville maxime-rainville force-pushed the pulls/4/improve-pre-loaded-state branch from 12ac60a to 61ee9fe Compare March 5, 2024 02:18
@maxime-rainville maxime-rainville changed the base branch from 4 to 4.0 March 5, 2024 02:26
@maxime-rainville maxime-rainville force-pushed the pulls/4/improve-pre-loaded-state branch from 61ee9fe to 8a891cd Compare March 5, 2024 09:28
Copy link
Member

@emteknetnz emteknetnz left a comment

Choose a reason for hiding this comment

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

We shouldn't be adding templates to a react component

Copy link
Contributor Author

@maxime-rainville maxime-rainville left a comment

Choose a reason for hiding this comment

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

I've addressed the feedback.

On the broader point of "adding templates to a react component", providing placeholder markup while waiting for some long running process to complete is a standard practice in most modern JS based application.

For example, here's what ZenHub does.
image

It provides a nicer UI for the user, avoid things jumping around on the page once the long process has completed and reassures the user that the site hasn't crash on them.

I appreciate we have not historically done this. Now is as good a time to start as any.

templates/SilverStripe/LinkField/Form/LinkField_Spinner.ss Outdated Show resolved Hide resolved
}) });
await screen.findByText('Page title');
const linkPicker = container.querySelectorAll('#link-picker__link-123');
expect(linkPicker[0]).toHaveAttribute('aria-disabled', 'false');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's an aria-disabled attribute on the Disabled linkfield ... but its value is false. I'm not sure if that's actually what we want to do here.

I've added like this for now. We can revisit in the accessibility card.

}) });
await screen.findByText('Page title');
const linkPicker = container.querySelectorAll('#link-picker__link-123');
expect(linkPicker[0]).toHaveAttribute('aria-disabled', 'false');
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
expect(linkPicker[0]).toHaveAttribute('aria-disabled', 'false');

Adding it here make it look like this is the correct behaviour, even though we know it's wrong. If we're explicitly adding aria-disabled on the other card then we'll naturally add a unit test for it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the test for false.

Copy link
Member

@emteknetnz emteknetnz left a comment

Choose a reason for hiding this comment

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

There's little orange 'modified' badges showing before it's loaded as part of the 'loading animation' which shouldn't be there

This video showing me refreshing the page on my local

linkfield-fout-after-2024-03-07_15.25.41.webm

I can't help thinking we need to look at the spinner styling, the dark background on it make for a pretty jarring experience on my local where there's lots of "flashing" because the background is rendered for so little time. There already was some before this PR, though it's quite a lot worse afterwards

Copy link
Contributor Author

@maxime-rainville maxime-rainville left a comment

Choose a reason for hiding this comment

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

Added the missing comment and cleaned the version state icon.

FYI this PR now depends on silverstripe/silverstripe-admin#1705

}) });
await screen.findByText('Page title');
const linkPicker = container.querySelectorAll('#link-picker__link-123');
expect(linkPicker[0]).toHaveAttribute('aria-disabled', 'false');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the test for false.

@@ -0,0 +1,9 @@
const versionStates = {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Repeating the same strings over and over again seemed wrong and likely to lead to confusion. So I moved them to a constant.

Copy link
Member

Choose a reason for hiding this comment

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

Could you please refrain from doing random refactoring half-way through a peer review. It adds unnecessary burden at the end of the person doing the peer review.

@@ -198,4 +201,8 @@ LinkPickerTitle.propTypes = {
buttonRef: PropTypes.object.isRequired,
};

LinkPickerTitle.defaultProps = {
versionState: versionStates.unversioned,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change addresses the problem where the place holder LinkPickerTitle would get a draft state icon.

@@ -17,7 +17,8 @@
"php": "^8.1",
"silverstripe/framework": "^5.2",
"silverstripe/cms": "^5",
"silverstripe/versioned": "^2"
"silverstripe/versioned": "^2",
"silverstripe/admin": "^2.2"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a dependency on admin 2.2 because of the new spinner template.

Copy link
Member

@emteknetnz emteknetnz left a comment

Choose a reason for hiding this comment

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

Tested locally

Copy link
Member

@emteknetnz emteknetnz left a comment

Choose a reason for hiding this comment

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

Behat failures in CI

@maxime-rainville
Copy link
Contributor Author

Merging the admin PR fixed the behat build.

@emteknetnz emteknetnz merged commit 967c457 into silverstripe:4.0 Mar 12, 2024
12 checks passed
@emteknetnz emteknetnz deleted the pulls/4/improve-pre-loaded-state branch March 12, 2024 20:46
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.

None yet

3 participants