Focal point crop 3.0: go React!
It took a little longer than planned, but I have finally released a completely new version of my Focal point cropping extension for Content Hub, version 3.0. This new version contains a React version of the external page components Focal point editor and Public link viewer (I have slightly changed the names of the components). Since version 4.2 of Content Hub, Sitecore replaced the front-end Knockout framework with React, rendering my original code unusable. Content Hub does come with a temporary compatibility mode where you can disable React, but due to the dependencies in my code on the entity context it was not possible to use my components regardless. So I had to rebuild my components from the ground up using React, which was new to me. That, and the fact that on the first releases of Content Hub 4.2 the documentation was not yet updated with the new requirements and possibilities, made it bit of a challenge. But here we are, and I must admit I like React a lot! The code certainly is more clean and stable now, also due to a number of other improvements.
In this blog post, I will explain the most important changes to my extension. But before I do, I want to give a big shout-out to fellow Sitecore MVP and Content Hub enthusiast Ronald van der Plas (https://www.contenthub.dev/) for helping me to get started. As I shared in one of my previous blog posts, the documentation was lacking behind (which is fixed now by the way), and I had no experience with React, so I did have some trouble getting started. But Ronald built an alpha version of my Public link viewer component and submitted a Pull Request on my Open Sourced GitHub repository. It needed a bit of work still, but was everything I needed to get going!
Change log
1. Front-end framework
Obviously, the front-end framework changed, from Knockout to React. This also meant that the initialization of all elements now needs to be asynchronous, and the abstraction between the actual DOM, events and window properties increased. It took a bit of fiddling, but the code is now easier to understand and read I think. And luckily for me, I could of course re-use all the logic.
2. Styling
Content Hub didn’t really have the option to build components in the same style as the native ones before (not sure that’s what External page components are for anyway), so I inspected the Content Hub UI and copied some class names and inline styling onto my own HTML for the first version. Felt sketchy but didn’t really have a lot of options either. Now, Content Hub is using Material UI and most of the styling automatically applies to any default component created. This way I could drop almost all hard-coded or inline styling and certainly all the not-so-reliable class names copied from Content Hub. There’s still a little bit of tweaking needed though, because the MUI overrides of the default styling by Content Hub aren’t automatically applied and I have some discrepancies in margin, but nothing major. I will tweak this furthermore in upcoming updates.
To demonstrate the difference and the huge improvement, let’s compare the old row element of the Public link viewer with the new MUI component definition. Going from:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<li class="file-history-viewer__item flex-grid grid--align-center"> <a href="{{href}}" target="_blank"> <div class="file-history-viewer__thumb-wrapper" style="width:100px;-webkit-flex-basis:99px;flex-basis:100px;"> {{#if preview}}<img src="{{preview}}" class="file-history-viewer__asset-thumb" style="max-width:100px;max-height:100px;" alt="Image preview" />{{/if}} </div> <div class="file-history-viewer__meta flex-grid grid--direction-column" style="max-width:calc(100% - 122px);"> <strong class="file-history-viewer__file-name" title="{{title}}">{{title}}</strong> <div class="file-history-viewer__file-meta-data flex-grid grid--align-center"> <span class="file-history-viewer__item-size"><strong>{{rendition}}</strong> · {{croppingType}}{{#if width}} · {{width}} x {{height}} px{{/if}}</span> </div> </div> </a> </li> |
To:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<TableRow key={"row_" + index} hover={true}> <TableCell size="small" align="center"> <a href={entityUrl} target="_blank"> <img src={entityUrl + "&t=thumbnail"} alt="Image preview" /> </a> </TableCell> <TableCell valign="top"> <ThemeProvider theme={context.theme}> <Typography variant="body1"> {title} </Typography> </ThemeProvider> <Box> <ThemeProvider theme={context.theme}> <Typography variant="body2" color={"rgba(0, 0, 0, 0.54)"}> {rendition.label} · {croppingType} · {width} x {height} px </Typography> </ThemeProvider> </Box> </TableCell> </TableRow> |
I only need to drop that custom color and want to get rid of the multiple ThemeProvider wrappers, but I have a pending support ticket to find out what the intended implementation should look like.
3. Interaction with Content Hub entities
Previously, you received an entity object in JavaScript within your context, which you could use to read properties from or even stringify it into raw JSON to be able to use a JSON parser and access all the properties and relations like browsing through the output of the Content Hub API. It works, but it is less reliable and wasn’t really well documented. For this version I switched to the JavaScript SDK for reading properties and relations from the Content Hub asset for my components, as well as for saving the updated focal point coordinates to that same asset. This solution is way more robust, and also very well documented. Check it out at https://doc.sitecore.com/ch/en/developers/34/cloud-dev/javascript-sdk.html.
Exceptions were made…
Though, I needed to make an exception to this rule. I couldn’t find any more data about the available renditions then available in the asset properties. And that is not enough for my use case: for example, in the renditions property the downloadPreview rendition isn’t included, as well as the URLs of the renditions, which I both need for displaying the asset in my Focal point editor, and also, the reference names aren’t included, which I need for displaying the originating renditions of the public links in the Public link viewer. Maybe it’s there, but I couldn’t find the data through the JavaScript SDK. The properties do not provide enough data and there’s no such thing as an ‘AssetToRendition’ relation. Hence, I resorted to my trusted API approach and used the corresponding /renditions
resource to fetch the detailed rendition data.
4. Configuration
Very small, but an improvement nonetheless. I used to have a hard-coded reference to your Content Hub instance in the ‘Public links preview.js’ script assigned to the variable this.contentHubBaseUrl
, used to call the Content Hub API. Since this code is always running on the instance itself though, I could easily replace this with a call to window.location.hostname
, avoiding the need to configure anything instance specific.
And of course, the configuration of the new external components in Content Hub is easier too, only requiring you to link to a JavaScript bundle, instead of pasting code in multiple text areas and separately configuring any required dependencies as well.
The result
I still consider this version to be a beta version, as I only tested it myself on version 4.2.21, and my code is pending a review by an experienced React developer. Also I have requested a few people to test it out in their instance. I am confident though that you can start using it and everything should work just fine, also being compatible with data stored by the old Knockout version. If you have any remarks or findings, please let me know, via an issue on my repository or by submitting a Pull Request if you fancy chiming in.
This is how the new version looks and it immediately proves its value as you can see the different cropping ratios all are spot on. You can find the full source code and installation manual on:
https://github.com/robhabraken/content-hub-focal-point-cropping
For the sake of backwards compatibility, I kept the original HTML / JS components in my repository, so you can now choose to install the version that matches your Content Hub instance version.
Comments
Comments are disabled for this post