-
Notifications
You must be signed in to change notification settings - Fork 6
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
Add dotcom-ui-data-embed
#808
Conversation
@@ -1,4 +1,5 @@ | |||
import React from 'react' | |||
// TODO: Figure out why importing the package name does not work. | |||
import { ClientEmbed } from '../../../dotcom-ui-client-embed/src' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to have another go at this but I could not figure out why referencing the package name does not work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was because when I added these as a dependency I just had not ran npm install
on the directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will pull your branch and have a play.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, that tripped me up too. If there are packages with dependencies on other packages then you need to install each of them (in order, I would imagine).
@@ -3,14 +3,8 @@ import subject from '../../server/formatFlagsJSON' | |||
const fixture = Object.freeze({ foo: 1, bar: false, baz: 'qux' }) | |||
|
|||
describe('dotcom-ui-flags/src/server/formatFlagsJSON', () => { | |||
it('returns a stringified object', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed this since it seemed unnecessary to check the type when we do a strict assertion on an object below. Let me know what you'd prefer to do.
@@ -11,5 +11,5 @@ export default function formatFlagsJSON(flags: TFlagsData = {}): string { | |||
} | |||
}) | |||
|
|||
return JSON.stringify(output) | |||
return output |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like it is on the right track.
I guess one of the obvious things to add to the example app would be some custom data that gets passed from server to client.
The use case for this requirement is next-video-page
: https://www.ft.com/video. You can see that it is using an attribute that is denied by the appContext schema: permutiveContext
(hence with it is on v0.6 and not v0.7, the latter of which validates the appContext schema and fails if there are any disallowed attributes present).
@@ -11,5 +11,5 @@ export default function formatFlagsJSON(flags: TFlagsData = {}): string { | |||
} | |||
}) | |||
|
|||
return JSON.stringify(output) | |||
return output |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
@@ -1,4 +1,5 @@ | |||
import React from 'react' | |||
// TODO: Figure out why importing the package name does not work. | |||
import { ClientEmbed } from '../../../dotcom-ui-client-embed/src' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will pull your branch and have a play.
Could you explain how you're testing this with the front page?
|
Just checking the Dev Tools Elements tab on production ft.com, which is why it was surprising that the appContext and flags data is not stringified (as code suggests we are currently stringifying it). |
examples/kitchen-sink/client/main.js
Outdated
|
||
readyState.domready.then(() => { | ||
const flagsClient = flags.init() | ||
const appContextClient = appContext.init() | ||
|
||
const customContext = loadClientEmbed('custom-context') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you can see it's simple at the moment but does not follow the init
convention elsewhere + the getAll
pattern.
Should we require the user to pass their ID to init
or automagically find clientEmbeds when init()
is called and then allow them to use the client to specify an embed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice if we can keep it matching the pattern.
I think including the ID as an argument for init
will make it clear which embed is being retrieved, but means it will require an individual DOM query for each embed being retrieved (although that is what the code is currently doing, and there is only one extra embed being added to one app at the moment, so this is minimal).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One other alternative would be this sort of pattern:
const clientEmbed = new clientEmbed('IDHERE')
clientEmbed.init()
@pixelandpage would appreciate your thoughts on what the interface could look like here as well if you have time :)
@@ -64,6 +65,7 @@ module.exports = (_, response, next) => { | |||
</section> | |||
</div> | |||
</Layout> | |||
<ClientEmbed id="custom-context" data={{ foo: true, bar: 'qux' }} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In documentation should make it clear to put the embed at the bottom of the page to remove risk of it blocking page render.
examples/kitchen-sink/client/main.js
Outdated
|
||
readyState.domready.then(() => { | ||
const flagsClient = flags.init() | ||
const appContextClient = appContext.init() | ||
|
||
const clientEmbedClient = clientEmbed.init('custom-context') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should move this 'custom-context' constant into a 'constants.js' file as per convention in this repo...
|
||
getAll(): TAppContext { | ||
return this.appContext | ||
super(options.appContext) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to figure out how to extend a class and apply the types, as this currently has removed the type information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like what I wanted to do is not possible(?) so will need to figure out another way to achieve this: microsoft/TypeScript#3402
@@ -0,0 +1,15 @@ | |||
export default class ClientEmbedData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any way to add types here and then make them more specific when the class gets extended?
private data | ||
|
||
constructor(data) { | ||
this.data = Object.freeze(data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the data in this is likely to be nested, should we consider doing a deeper freeze? may not be worth the extra code required in the bundle...
@@ -0,0 +1,2 @@ | |||
export * from './components/ClientEmbed' | |||
export * from './client' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've had to add the client entrypoints to the main entrypoints which I assume is not ideal since we have a separate browser entrypoint for a reason. This was necessary to allow the client code to be shared in other packages with the TypeScript types working...
Something I noticed: |
a764a46
to
e891ef7
Compare
I have ruled out having a default 'id' prop as I'm not sure there's an easy way to communicate you need unique IDs if you use more than one embed. |
Spoke to Maggie, we're gonna go with |
76dc970
to
1a5275c
Compare
Since `dotcom-ui-app-context` and `dotcom-ui-flags` share functionality this commit moves JSON output into the embed component which is the same as how it works in app-context. This'll hopefully make it easier to use the new package in the future. May be a breaking change if formatFlagsJSON is part of the public API.
Also rename the file since there's no JSX syntax used in this file anymore.
Also rename the file since there's no JSX syntax used in this file anymore.
This allows users to parse the data embedded in the page.
1a5275c
to
8d904d8
Compare
Mirrors the classes found in flags and app-context.
Allow users to create an instance of the client and initialise it later. Don't expose internal methods and have a consistent 'init' method to use.
8d904d8
to
6f9fe16
Compare
8c51043
to
aa8683c
Compare
I suggested refactoring away from |
I've spiked putting this into next-video-page: https://github.com/Financial-Times/next-video-page/compare/spike-data-embed-2?expand=1 I'm curious if we're really solving the underlying problem. If our main worries were that app context was being passed into nTracking etc should we not have validation or an allowlist there? And allow for app context to be used for all data, which is as we've seen, what people tend to do? If when we passed the app context into things like nTracking, nTracking allowlisting only the properties it expects, would this allow us to use AppContext in a broader way? |
This PR description goes some way to answering that question: #782. I think it's preferable to enforce the schema as far upstream as possible so that Page Kit - being the originator of the It's fair to say that (in the case of The The concern would be that If it transpires that a property should be added to |
@andygout thanks for the clarity, let's continue. I'm still getting my head around this space. :) |
Worked on a different branch to clean up renaming files: #812 |
Continued in this pull request: #812