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

Dynamically fetch control epic copy #9

Merged
merged 1 commit into from Jan 22, 2020
Merged

Conversation

tjmw
Copy link
Member

@tjmw tjmw commented Jan 21, 2020

This PR introduces a change to dynamically fetch the control epic copy from a remote endpoint. This happens once when the app is started. There isn't an elegant failure handling mechanism at this point. We'll figure that out in a future PR. Currently we'll catch and log any errors which occur during this process.

Not implemented here

  • Elegant handling/retrying if we fail to fetch the content
  • We don't have full support for all possible placeholders yet (I think the full list is %%CURRENCY_SYMBOL%%, %%COUNTRY_NAME%% and %%ARTICLE_COUNT%%)
  • We do support interpolating the currency symbol, but we just use a hardcoded value. In future we'll want to bring across the logic from frontend where we resolve this based on the geolocation.

{paragraphs.length > 0 &&
paragraphs.map((paragraph, idx) => (
<p key={idx} className={bodyStyles}>
<span dangerouslySetInnerHTML={{ __html: replacePlaceholders(paragraph) }} />
Copy link
Member Author

Choose a reason for hiding this comment

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

I've introduced an additional span here around the paragraph content to allow me to use dangerouslySetInnerHtml, since I also want to include children below (the Highlighted component appears within the same <p> tag). I'm interested to hear thoughts on alternative approaches here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is annoying and I don't have any better solution I'm afraid :(.

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 have a better solution either. But for the sake of argument, if we absolutely had to stop that extra span from being added, I suppose we could move the dangerouslySetInnerHTML call back to the paragraph level and ensure the HTML we pass into it includes the paragraph text, as well as the result of passing the Highlighted component through ReactDOM's renderToStaticMarkup function, which we do use further upstream. But again, I personally wouldn't do that in this case as we can live with that span.

@tjmw tjmw requested review from andre1050 and nicl January 21, 2020 15:19
Copy link
Contributor

@nicl nicl left a comment

Choose a reason for hiding this comment

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

This is fetch!

src/components/DefaultEpic.tsx Outdated Show resolved Hide resolved
{paragraphs.length > 0 &&
paragraphs.map((paragraph, idx) => (
<p key={idx} className={bodyStyles}>
<span dangerouslySetInnerHTML={{ __html: replacePlaceholders(paragraph) }} />
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this is annoying and I don't have any better solution I'm afraid :(.

src/components/DefaultEpic.tsx Outdated Show resolved Hide resolved
import { DefaultEpic } from './components/DefaultEpic';
import cors from 'cors';

const app = express();
app.use(express.json({ limit: '50mb' }));
const bootApp = (content: DefaultEpicContent): void => {
Copy link
Contributor

Choose a reason for hiding this comment

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

What was the thinking behind not using top-level await in the end:? (Just curious really.) I've seen suggestions that it makes modules a bit harder to reason about/can be surprising, but on the flip-side for the key start file this might not matter and it might help remove the bootApp wrapping and indentation?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good question! It was a combination of things. When I looked it up I was reminded that, as you mentioned here, there is some push-back on whether or not top level await makes sense. I don't think any of the arguments against it affect us right now, but felt like maybe it was setting a precedent and it could be easy to avoid us having the conversation in future.

The other (somewhat major 😸) reason is that it's not supported in TypeScript yet.

Copy link
Contributor

@nicl nicl Jan 21, 2020

Choose a reason for hiding this comment

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

Ha okay, that last argument is pretty slam-dunk :).

It looks like they're adding it in the next version - https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#top-level-await

@tjmw
Copy link
Member Author

tjmw commented Jan 21, 2020

Thanks for the review & feedback @nicl! I'm either proud or ashamed to say that I didn't need to follow the link to get the Mean Girls reference 😝

Copy link
Contributor

@andre1050 andre1050 left a comment

Choose a reason for hiding this comment

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

Great work @tjmw! 🆒💥


const Body: React.FC<BodyProps> = ({ highlighted, paragraphs }: BodyProps) => (
<>
{paragraphs.length > 0 &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't think we need to check for the length of the array before we map through it, do we? With a length of 0 the map callback would be called 0 times, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah thanks, good spot! I think at some point I had a version where I did want this, but definitely not needed now.

{paragraphs.length > 0 &&
paragraphs.map((paragraph, idx) => (
<p key={idx} className={bodyStyles}>
<span dangerouslySetInnerHTML={{ __html: replacePlaceholders(paragraph) }} />
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 have a better solution either. But for the sake of argument, if we absolutely had to stop that extra span from being added, I suppose we could move the dangerouslySetInnerHTML call back to the paragraph level and ensure the HTML we pass into it includes the paragraph text, as well as the result of passing the Highlighted component through ReactDOM's renderToStaticMarkup function, which we do use further upstream. But again, I personally wouldn't do that in this case as we can live with that span.

@tjmw
Copy link
Member Author

tjmw commented Jan 21, 2020

Thanks for the feedback @andre1050! I couldn't respond directly to your comment about dangerouslySetInnerHTML for some reason, but yeah I agree with your thinking there. I'm happy to stick with it as-is and we can revisit if there's a strong reason we need to get rid of the additional <span>.

@tjmw tjmw force-pushed the feature/dynamic-epic-content branch from 661f514 to 0f2197e Compare January 21, 2020 17:00
@@ -0,0 +1,39 @@
import { fetchDefaultEpicContent } from './fetchDefaultEpicContent';
Copy link
Contributor

Choose a reason for hiding this comment

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

cc @andre1050 and @tjmw - what are people's preferences on:

a) naming these files? (with Andre earlier I'd assumed we'd go for nouns as good names here - the reason being that it makes it easier to add additional functions later, i.e. they are more like mini-modules or objects, which typically have noun naming

b) utils folder? - I don't have strong views on this, generally I prefer a name other than utils though (or things like common - as common in Frontend still makes me sad).

Copy link
Member Author

Choose a reason for hiding this comment

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

Hey @nicl both good questions!

For a) yep I can see the point here. I agree that's the direction I'd expect the naming to go eventually. The name as it is now definitely doesn't invite adding additional functions. I guess the danger is going with something too generic before figuring out what we want this module to be which can end up being misleading. So we could rename now or put that decision off until we have a concrete use case. I don't feel too strongly either way.

b) yeah I think we should look to split utils up into several more specifically named folders. I've definitely seen utils become a bit of a dumping ground in projects in the past. Perhaps the file added here belongs in src/api or similar.

Copy link
Member Author

Choose a reason for hiding this comment

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

I ended up reorganizing and renaming things here a little bit. We've now got src/api/contributionsApi where we can perhaps group all API requests we need to make to fetch contributions data. Maybe not perfect, but we can always change in future.

Fetch the copy for the default epic from an API endpoint once when we
boot the app. At this point we're still missing the following, which
we'll follow up on in future PRs:

* Elegant handling/retrying if we fail to fetch the content

* We don't have full support for all possible placeholders yet (I think
the full list is %%CURRENCY_SYMBOL%%, %%COUNTRY_NAME%% and
%%ARTICLE_COUNT%%)

* We do support interpolating the currency symbol, but we just use a
hardcoded value. In future we'll want to bring across the logic from
frontend where we resolve this based on the geolocation.
@tjmw tjmw force-pushed the feature/dynamic-epic-content branch from 89566b9 to 0c34a4b Compare January 22, 2020 09:39
@tjmw tjmw merged commit f312756 into master Jan 22, 2020
@tjmw tjmw deleted the feature/dynamic-epic-content branch January 22, 2020 09: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