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

Fixes #21312 - components for formatting dates #5184

Merged
merged 23 commits into from
Dec 25, 2018
Merged

Fixes #21312 - components for formatting dates #5184

merged 23 commits into from
Dec 25, 2018

Conversation

tstrachota
Copy link
Member

Contains following changes:

  • adds React components for rendering dates
  • locales for react-intl as well as the fallback intl package are loaded lazily
  • enables multiple webpack entry points per plugin (necessary to get this change into katello)
  • adds HOC for i18n that waits until locales are loaded

Depending on your setup, you might need to set ASSET_PATH env variable to get the dynamic imports (lazy loading) working in development. It's required when running over https. Eg:

ASSET_PATH='https://myforeman.org:3808/webpack/'

@theforeman-bot
Copy link
Member

Issues: #21312

index_prefix = File.basename(entry_path).gsub(/[_]?index[.]js$/, '')
bundle = plugin_name.to_s.gsub(/core$/, '').gsub(/-|_|#{remove_bundle_name_plugins}/,'')

if index_prefix == ''
Copy link
Member

Choose a reason for hiding this comment

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

nitpick: .blank?

Copy link
Member Author

Choose a reason for hiding this comment

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

We're using this helper also in plugin_webpack_directories.rb where we don't have active support included.

if (production) {
publicPath = process.env.ASSET_PATH || '/webpack/';
} else {
publicPath = process.env.ASSET_PATH || `http://${process.env.HOSTNAME}:${devServerPort}/webpack/`;
Copy link
Member

Choose a reason for hiding this comment

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

do you really need the entire url? I would prefer to avoid hardcoding the path if we URL scheme

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately we really need the entire url. We have to pass the dev server port. Without that webpack fetches dynamic imports from wrong url.

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems my process.env.HOSTNAME is undefined.

Copy link
Contributor

Choose a reason for hiding this comment

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

How should it work in production? Do we need the ASSET_PATH in production?

Copy link
Contributor

Choose a reason for hiding this comment

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

Should consider adding this variable to Procfile and script/foreman-start-dev?

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'll try to tune the Procfile. Production will be served from /webpack/ as before. That branch is unchanged.


filename: production ? '[name]-[chunkhash].js' : '[name].js'
filename: production ? '[name]-[chunkhash].js' : '[name].js',
chunkFilename: production ? '[name]-[chunkhash].js' : '[name].js'
Copy link
Member

Choose a reason for hiding this comment

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

what does this do?

Copy link
Member Author

Choose a reason for hiding this comment

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

https://webpack.js.org/configuration/output/#output-chunkfilename
Name format for non-entry chunks created by webpack.

Copy link
Contributor

Choose a reason for hiding this comment

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

I am getting all of those files into my public/webpack when building production:

0-03661867bb957b74fba9.js
1-1d5ccaf80730fcbd15a5.js
2-531ce93840f13a2bb530.js
3-0fe5d3ece4ad57ea7eb8.js
n-.....................js
28-.....................js

shouldn't it be en-[hash].js / pt_BR-[hash].js?

Copy link
Contributor

Choose a reason for hiding this comment

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

Does it mean plugins are also going to build those files?

Copy link
Member Author

Choose a reason for hiding this comment

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

The dynamic chunks didn't have webpackChunkName configured. I'll fix it.

@@ -28,7 +28,7 @@ export function templateSelected(item) {
$('#storage_volumes .children_fields >.fields').remove();
$.each(result.volumes, function () {
// Change variable name because 'interface' is a reserved keyword.
this.disk_interface = this['interface'];
this.disk_interface = this.interface;
Copy link
Member

Choose a reason for hiding this comment

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

not related?

@@ -6,4 +6,7 @@ export default {
});
},
noop: Function.prototype, // empty function
getDisplayName(Component) {
return Component.displayName || Component.name || 'Component';
Copy link
Member

Choose a reason for hiding this comment

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

isnt this the default (just with an Unknown string instead of Component?

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'm not sure what are the defaults. I saw displayName being undefined at some places. This approach is a React.js convention for HOCs: https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging

@ohadlevy
Copy link
Member

@sharvit @amirfefer @waldenraines @danseethaler can you guys review please?

Copy link
Member

@danseethaler danseethaler left a comment

Choose a reason for hiding this comment

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

Looks good overall - just one question with the babel setup.

.babelrc Outdated
"presets": ["env", "react"],
"presets": [
"env",
["es2015", {"modules": false}],
Copy link
Member

Choose a reason for hiding this comment

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

I'm pretty sure you can pass the {"modules": false} into the env preset. Is there a reason we're targeting 2015 only here?

package.json Outdated
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-assign": "^6.8.0",
"babel-plugin-transform-object-rest-spread": "^6.8.0",
"babel-preset-env": "^1.6.1",
"babel-preset-es2015": "^6.24.1",
Copy link
Member

Choose a reason for hiding this comment

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

Same question as above about needing this.

Copy link
Contributor

@sharvit sharvit left a comment

Choose a reason for hiding this comment

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

Nice work @tstrachota 👍
Good job implementing the async importers!

It's a significant and blessed change, so I hope it will merge soon even though I have many comments.

if (production) {
publicPath = process.env.ASSET_PATH || '/webpack/';
} else {
publicPath = process.env.ASSET_PATH || `http://${process.env.HOSTNAME}:${devServerPort}/webpack/`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems my process.env.HOSTNAME is undefined.

// Detect supported locales from folders in ./locale/
const localeDir = path.join(__dirname, '..', 'locale')
const localeSubdirs = [ ...new Set(fs.readdirSync(localeDir).filter(f => fs.statSync(path.join(localeDir, f)).isDirectory())) ];
const supportedLocales = localeSubdirs.map(d => d.split('_')[0]).join('|')
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you refactor those lines so it will be easy to understand?

if (production) {
publicPath = process.env.ASSET_PATH || '/webpack/';
} else {
publicPath = process.env.ASSET_PATH || `http://${process.env.HOSTNAME}:${devServerPort}/webpack/`;
Copy link
Contributor

Choose a reason for hiding this comment

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

How should it work in production? Do we need the ASSET_PATH in production?


filename: production ? '[name]-[chunkhash].js' : '[name].js'
filename: production ? '[name]-[chunkhash].js' : '[name].js',
chunkFilename: production ? '[name]-[chunkhash].js' : '[name].js'
Copy link
Contributor

Choose a reason for hiding this comment

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

I am getting all of those files into my public/webpack when building production:

0-03661867bb957b74fba9.js
1-1d5ccaf80730fcbd15a5.js
2-531ce93840f13a2bb530.js
3-0fe5d3ece4ad57ea7eb8.js
n-.....................js
28-.....................js

shouldn't it be en-[hash].js / pt_BR-[hash].js?

if (production) {
publicPath = process.env.ASSET_PATH || '/webpack/';
} else {
publicPath = process.env.ASSET_PATH || `http://${process.env.HOSTNAME}:${devServerPort}/webpack/`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should consider adding this variable to Procfile and script/foreman-start-dev?

import { locale, ready as i18nReady, loaded as i18nLoaded } from './i18n';
import helpers from './helpers';

export function i18nProviderWrapper(initialNow = undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

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

can use es6 syntax for the function?
Shouldn't the default value of initialNow should be undefined anyway?

super(props);
if (!i18nLoaded) {
i18nReady.then(() => {
this.forceUpdate();
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make more sense to use an inner store instead forceUpdate?

import { FormattedDate, intlShape } from 'react-intl';
import { timezone } from '../../../common/i18n';

class Date extends React.Component {
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't it interfere with the native Date?

Copy link

Choose a reason for hiding this comment

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

+1

Copy link

Choose a reason for hiding this comment

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

What do you think of the name IsoDate instead?

https://www.w3.org/QA/Tips/iso-date

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 like IsoDate, I'll change the names.


class Date extends React.Component {
render() {
if (this.props.data.date) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can do:

const { date, default } = this.props.data;

if (date) {
  return ...;
}

return <span>{default}</span>;

import RelativeDateTime from './common/dates/RelativeDateTime';
import LongDateTime from './common/dates/LongDateTime';
import ShortDateTime from './common/dates/ShortDateTime';
import Date from './common/dates/Date';
Copy link
Contributor

Choose a reason for hiding this comment

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

Afraid Date interfere with the native Date

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true. One has to import it under a different name if you plan to use them together. I couldn't find any better name. Suggestions?

@sharvit
Copy link
Contributor

sharvit commented Jan 28, 2018

Can you add the intl and react-intl to config/webpack.vendor.js?

$.cookie('timezone', tz.name(), { path: '/', secure: location.protocol === 'https:' });
tfm.i18n.ready.then(() => {
var tz = jstz.determine();
$.cookie('timezone', tz.name(), { path: '/', secure: location.protocol === 'https:' });
Copy link

@priley86 priley86 Feb 2, 2018

Choose a reason for hiding this comment

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

hey @tstrachota ... maybe you can have some Cookies with this PR? 🍪

https://github.com/js-cookie/js-cookie

wdyt?

Copy link

Choose a reason for hiding this comment

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

maybe in the future but not now... i dunno...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes @priley86 we should actually do that, thanks for the advice 👍

I was also looking into that repository:
https://github.com/reactivestack/cookies

I think the js-cookie is better for us, for now, i still don't see us using CookieProvider or withCookie wrapper.

We actually trying to get ride of jquery which is a long process and migrating the cookies is a good step.

I open an issue and i hope to do it soon:
http://projects.theforeman.org/issues/22506

Copy link

Choose a reason for hiding this comment

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

I am fine w/ react-cookie too... and yes, very much prefer that API down the road if it becomes an option. Universal cookies are even more tasty! They could stream via react-dom/server within apollo-server in an isomorphic way, you know? Some kind of strange renderToNodeStream voodoo...haha

overall, i like the approach here w/ react-intl and utilizing the componentRegistry. I noticed Twitter doing something very similar yesterday. I'm happy to move off of jquery as you have time...

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'm ok with migrating from jquery cookies to some other solution in future, but it's out of the scope of this PR.

return <span />;
}
return (
<IntlProvider locale={i18n.locale} initialNow={initialNow}>
Copy link

Choose a reason for hiding this comment

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

I think you can render messages on the IntlProvider as well...

https://egghead.io/lessons/react-convert-a-hard-coded-string-using-react-intl-formattedmessage

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I know about it. But we don't use react-intl for messages. It's one of the options for future, but we haven't decided what will be our approach yet. We can easily add it later.

import { FormattedDate, intlShape } from 'react-intl';
import { timezone } from '../../../common/i18n';

class LongDateTime extends React.Component {
Copy link

@priley86 priley86 Feb 6, 2018

Choose a reason for hiding this comment

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

I think all of these can be converted to stateless functional components.... at least my linter tells me that ;)

example: priley86/manageiq-v2v@9db79b6

ShortDateTime.propTypes = {
data: PropTypes.shape({
date: PropTypes.any,
defaultValue: PropTypes.string,
Copy link

Choose a reason for hiding this comment

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

you are missing seconds in propTypes here

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated

@tstrachota
Copy link
Member Author

[test]

@waldenraines
Copy link

Where are we with this? This is blocking Katello/katello#7001 which is in turn blocking some katello work which relies on the infrastructure in that PR.

@waldenraines
Copy link

@tstrachota do you mind rebasing this please?

@tstrachota
Copy link
Member Author

@waldenraines rebased

@waldenraines
Copy link

@ohadlevy what else is needed here?

@tstrachota
Copy link
Member Author

[test foreman]

@ohadlevy
Copy link
Member

@waldenraines I didnt test it yet (lack of time) and the fact that @sharvit still didn't approve it?

Copy link
Contributor

@sharvit sharvit left a comment

Choose a reason for hiding this comment

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

@tstrachota I couldn't run it locally, can you check it please?

.babelrc Outdated
"presets": ["env", "react"],
"presets": [
"env",
"es2015",
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it really necessary? Shouldn't the env provide the es-latest-stable?

Copy link
Contributor

Choose a reason for hiding this comment

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

When running tests, I am getting a bunch of those errors:

ERROR: Error: Couldn't find preset "es2015" relative to directory

Copy link
Contributor

Choose a reason for hiding this comment

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

Same when running dev-server:

Module build failed: Error: Couldn't find preset "es2015"

@tstrachota
Copy link
Member Author

@ohadlevy nice catch with the chunk naming. My last commit fixes that.

@tstrachota
Copy link
Member Author

Added one more fix in webpack.config.js for names of chunks from plugins.

import { deprecateObjectProperty } from '../../foreman_tools';

const runningInPhantomJS = () => window._phantom !== undefined;
Copy link
Member

Choose a reason for hiding this comment

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

note we might be running also in chrome as introduced in 6044a04, perhaps you can also detect based if ENV["JS_TEST_DRIVER"] is defined.

Copy link
Member Author

Choose a reason for hiding this comment

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

Chrom is not a problem as it implements Intl API correctly. We had issues with phantom that provides Intl object but its functionality is quite limited.

@@ -0,0 +1,42 @@
import React from 'react';
import { IntlProvider } from 'react-intl';
Copy link
Member

Choose a reason for hiding this comment

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

does this include the functionality of Provider from 'react-redux' ? AFAIU we need it when store is not passed explicitly ?

Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIU the components/wrapperFactory.js will wrap it with the react-redux Provider so we should be safe.

This might make it simpler: https://github.com/ratson/react-intl-redux
We can migrate later if we decide to.


/* eslint-disable react/style-prop-object */
return (
<span title={title}>
Copy link
Member

Choose a reason for hiding this comment

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

this means it uses the jquery popover right? perhaps we should be explicit and use the pf one?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, this means it uses standard html attribute: https://www.w3schools.com/tags/att_title.asp
I don't think jQuery is involved here.

Copy link
Member

Choose a reason for hiding this comment

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

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 see. I didn't see it would apply anywhere on the dates. It's probably because the components mounted after the tooltip initialization.

Copy link
Member

Choose a reason for hiding this comment

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

right, but if you want to show the correct date (e.g. a minute after the page has been loaded) you would need a different way. I"m OK to leave this outside of this pr.

'UTC',
'Europe/Prague',
'Europe/Kiev',
'Asia/Tel_Aviv',
Copy link
Member

Choose a reason for hiding this comment

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

its Asia/Jerusalem AFAIR :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I can change that

Copy link
Member

Choose a reason for hiding this comment

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

no need, I wasn't sure if it has a meaning in terms of real timezone names or not...

Copy link
Member Author

Choose a reason for hiding this comment

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

It worked for me. I didn't notice Asia/Tel_Aviv tz is deemed to be deprecated, but obviously it's still available for backwards compatibility. Anyway a changed it to Jerusalem.

@@ -0,0 +1,23 @@
import React from 'react';
Copy link
Member

Choose a reason for hiding this comment

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

hmm.. should these be part of the pr?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not?
Notice it's living under webpack/stories/component/ and it helps to show code in the storybook.

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 needed it for the storybook. It's first time where we're using it so I think it's valid to add that. I can make it a separate commit if you want.

sharvit
sharvit previously approved these changes Dec 20, 2018
Copy link
Contributor

@sharvit sharvit left a comment

Choose a reason for hiding this comment

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

Thanks @tstrachota, I think we can merge it 👍

- it uses Asia/Jerusalem timezone
- fix initial date to make it compatible with Firefox
@tstrachota
Copy link
Member Author

@ohadlevy updated, stories now use Asia/Jerusalem.
The PR contains 22 commits. They should be squashed prior to merge.

return this.registry[name];
},

wrapperFactory() {
return new WrapperFactory();
Copy link
Member

Choose a reason for hiding this comment

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

does this happen once per document load? multiple times? I'm guess I don't understand the background for all of this change...

Copy link
Member Author

Choose a reason for hiding this comment

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

It's called once per component mount when it's mounted into erb or angular. I added that to enable plugins using wrappers easily. An example in Katello is here:
https://github.com/Katello/katello/pull/7001/files#diff-5bcfdae0ace18ad3702fbb46115e768dR19

@ares
Copy link
Member

ares commented Dec 21, 2018

@ohadlevy any more comments from your side? thanks

@ohadlevy
Copy link
Member

@ohadlevy any more comments from your side? thanks

the last question i had is regarding the generated assets file, I currently see:

           react-intl/locale/zh-662ccab329e3af4fcb9c.js    4.79 kB       0  [emitted]         react-intl/locale/zh
           react-intl/locale/ru-2d0f6f61adb59bf9c46f.js    2.36 kB       2  [emitted]         react-intl/locale/ru
           react-intl/locale/pt-bd268a4462ae1be8bb04.js    3.02 kB       3  [emitted]         react-intl/locale/pt
           react-intl/locale/pl-96ff3027a599698c16f0.js    2.14 kB       4  [emitted]         react-intl/locale/pl
           react-intl/locale/nl-3869fec41a97afb827b0.js    1.73 kB       5  [emitted]         react-intl/locale/nl
           react-intl/locale/ko-21e911695f048417239a.js  993 bytes       6  [emitted]         react-intl/locale/ko
           react-intl/locale/ja-77956907904bc88ced79.js  955 bytes       7  [emitted]         react-intl/locale/ja
           react-intl/locale/it-1f21a13e7e2dd99d9114.js    1.58 kB       8  [emitted]         react-intl/locale/it
           react-intl/locale/gl-ab4daec4a55995bbd086.js    1.42 kB       9  [emitted]         react-intl/locale/gl
           react-intl/locale/fr-312eabafdbcc2d88382b.js    4.33 kB      10  [emitted]         react-intl/locale/fr
           react-intl/locale/es-951784f084c629d5f087.js    13.5 kB      11  [emitted]         react-intl/locale/es
           react-intl/locale/en-7d31511c86c2212a45fd.js    7.23 kB      12  [emitted]         react-intl/locale/en
           react-intl/locale/de-7a6876e26f41edb260e5.js    1.69 kB      13  [emitted]         react-intl/locale/de
           react-intl/locale/ca-3c83f454af41f9327d18.js    2.87 kB      14  [emitted]         react-intl/locale/ca
                 intl/locale/zh-18b8279c56af2f01b537.js    20.9 kB      15  [emitted]         intl/locale/zh
                 intl/locale/sv-2c2314fc5a83c5a1fccf.js    24.2 kB      16  [emitted]         intl/locale/sv
                 intl/locale/ru-a7760efcc9511150bee4.js    27.1 kB      17  [emitted]         intl/locale/ru
                 intl/locale/pt-32f23f08c488321f4f5d.js    24.8 kB      18  [emitted]         intl/locale/pt
                 intl/locale/pl-2ade033777ee01b48d72.js    24.2 kB      19  [emitted]         intl/locale/pl
                 intl/locale/nl-2e2a6d97829d34c2ff87.js    24.5 kB      20  [emitted]         intl/locale/nl
                 intl/locale/ko-64888f94049ba7de36a6.js    22.5 kB      21  [emitted]         intl/locale/ko
                 intl/locale/ja-bab9d2a50afef2a669ec.js    12.5 kB      22  [emitted]         intl/locale/ja
                 intl/locale/it-718667f30c1f0c80a017.js      24 kB      23  [emitted]         intl/locale/it
                 intl/locale/gl-0890d08d92044a767e33.js    24.1 kB      24  [emitted]         intl/locale/gl
                 intl/locale/fr-b1601eccc932cad2fa64.js    24.6 kB      25  [emitted]         intl/locale/fr
                 intl/locale/es-502102792c7b4e2bd935.js    24.5 kB      26  [emitted]         intl/locale/es
                 intl/locale/en-e6d85a7f0b5e27bc92fc.js    24.2 kB      27  [emitted]         intl/locale/en
                 intl/locale/de-3ed06f626e2e243e1900.js    24.4 kB      28  [emitted]         intl/locale/de
                 intl/locale/ca-1e8ad8aa3868728b0a0e.js    24.6 kB      29  [emitted]         intl/locale/ca

is that expected? (note the react-intl and intl - with the same language) @sharvit any idea?

@sharvit
Copy link
Contributor

sharvit commented Dec 25, 2018

@ohadlevy - I made some research about the issue and the conclusion is the assets are fine.

In details:

  • Most of the modern browsers today comes natively with global.Intl API.
  • react-intl rely on the global.Intl API
  • In case of a browser without a global.Intl we need to load polyfills to the global.Intl (https://github.com/andyearnshaw/Intl.js)
  • It is not enough to just require('intl') and we need to load the specific locale data require('intl/locale-data/jsonp/en.js')
  • The react-intl locale data does not provide the full locale data, only the gap between what it needs to what the global.Intl provides. (see the size differences)

The implementation looks good to me, see the IntlLoader class and how it conditionally loads the polyfills into the global.Intl.

@ohadlevy ohadlevy merged commit 96cf840 into theforeman:develop Dec 25, 2018
@ohadlevy
Copy link
Member

thanks for the explanation @sharvit.

many thanks for your contribution @tstrachota :-)

@tbrisker
Copy link
Member

Looks like develop is now broken due to this. @ohadlevy @sharvit please take a look.

@ohadlevy
Copy link
Member

@tbrisker thanks! this seems to be effecting only development and related to how the hostname is being defined, looking at the console I can see:

bootstrap 51ccf83…:766 Refused to load the script 'http://ohad:3808/webpack/react-intl/locale/en.js' because it violates the following Content Security Policy directive: "script-src 'unsafe-eval' 'unsafe-inline' 'self' localhost:3808". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

I'm not sure where the hostname 'ohad' is used vs 'localhost' in this case, but i assume that's the reason for the failure.

@sharvit
Copy link
Contributor

sharvit commented Dec 26, 2018

@tbrisker seems like some cases it can't figure out the publicHost.
Can you try $WEBPACK_OPTS='--publicHost your-hostname'?

@@ -9,13 +9,16 @@
"@storybook/addon-knobs": "^3.4.3",
"@storybook/react": "^3.2.12",
"@storybook/storybook-deployer": "^2.0.0",
"argv-parse": "^1.0.1",
Copy link
Member

Choose a reason for hiding this comment

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

I missed this in the final review, but needed a packaging PR as well.

@ohadlevy
Copy link
Member

ohadlevy commented Jan 9, 2019 via email

@tbrisker
Copy link
Member

tbrisker commented Jan 9, 2019

I'm now also noticing multiple errors with this on the dashboard - https://projects.theforeman.org/issues/25812

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet