@edx/frontend-platform 1.14.1 → 1.14.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
# Overview
|
|
9
9
|
|
|
10
|
-
See the [GitHub Pages site for the complete documentation](https://
|
|
10
|
+
See the [GitHub Pages site for the complete documentation](https://openedx.github.io/frontend-platform/).
|
|
11
11
|
|
|
12
12
|
frontend-platform is a modest application framework for Open edX micro-frontend applications and their supporting libraries. It provides a number of foundational services that all Open edX micro-frontends should have:
|
|
13
13
|
|
|
@@ -25,6 +25,27 @@ In addition, frontend-platform provides an extensible application initialization
|
|
|
25
25
|
|
|
26
26
|
## Getting started
|
|
27
27
|
|
|
28
|
+
### One-time setup if you have not ugpraded node/npm
|
|
29
|
+
IMPORTANT: There is now a new node/npm version being used by frontend-platform as of
|
|
30
|
+
https://github.com/edx/frontend-platform/pull/259
|
|
31
|
+
|
|
32
|
+
#### Install nvm
|
|
33
|
+
This is highly recommended in order to be able to leverage different node/npm versions.
|
|
34
|
+
For a period of time, different repositories may be using different versions of node/npm.
|
|
35
|
+
|
|
36
|
+
Alternatively, please install node16 and npm8 for use with this repository.
|
|
37
|
+
|
|
38
|
+
#### Switch to node/npm version for this repo
|
|
39
|
+
```nvm use```
|
|
40
|
+
if you don't have the right node/npm versions, nvm will instruct you to install those
|
|
41
|
+
|
|
42
|
+
#### Clean out old node modules and reinstall
|
|
43
|
+
This step is needed because node now uses a different package lock format, and it's important to reinstall
|
|
44
|
+
dependencies based on this new package file. Delete node_modules, and issue a `npm ci`
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Standard getting started steps
|
|
48
|
+
|
|
28
49
|
1. `npm install`
|
|
29
50
|
2. `npm start`
|
|
30
51
|
3. Open http://localhost:8080 to view the example app.
|
|
@@ -116,4 +137,3 @@ NOTE: As of this writing, i18n is _not_ configurable. The `initialize()` functi
|
|
|
116
137
|
When making changes to frontend-platform, be sure to manually run the included example app located in `./example`. The example app includes 2 routes to test for both unauthenticated and authenticated users. To start the example app, run `npm start` from the root directory.
|
|
117
138
|
|
|
118
139
|
If you want to test changes to frontend-platform against a micro-frontend locally, follow the directions here: https://github.com/edx/frontend-build#local-module-configuration-for-webpack
|
|
119
|
-
|
|
@@ -214,7 +214,7 @@ var SegmentAnalyticsService = /*#__PURE__*/function () {
|
|
|
214
214
|
// the DOM by segment.min.js.
|
|
215
215
|
|
|
216
216
|
setTimeout(function () {
|
|
217
|
-
if (!global.ga || !global.ga.create) {
|
|
217
|
+
if (!global.ga || !global.ga.create || !global.google_tag_manager) {
|
|
218
218
|
_this3.segmentInitialized = false;
|
|
219
219
|
resolve();
|
|
220
220
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/analytics/SegmentAnalyticsService.js"],"names":["formurlencoded","snakeCaseObject","SegmentAnalyticsService","httpClient","loggingService","config","trackingLogApiUrl","LMS_BASE_URL","segmentKey","SEGMENT_KEY","hasIdentifyBeenCalled","segmentInitialized","initializeSegment","global","analytics","initialize","invoked","methods","factory","method","args","unshift","push","forEach","key","load","options","script","document","createElement","type","onerror","event","Event","dispatchEvent","async","src","first","getElementsByTagName","parentNode","insertBefore","_loadOptions","SNIPPET_VERSION","logError","eventName","properties","snakeEventData","deep","serverData","event_type","JSON","stringify","page","location","href","post","headers","error","userId","traits","Error","identify","Promise","resolve","reject","ready","user","id","reset","addEventListener","setTimeout","ga","create","checkIdentifyCalled","track","category","name"],"mappings":"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","sourcesContent":["import formurlencoded from 'form-urlencoded';\nimport { snakeCaseObject } from '../utils';\n\n/**\n * @implements {AnalyticsService}\n * @memberof module:Analytics\n */\nclass SegmentAnalyticsService {\n constructor({ httpClient, loggingService, config }) {\n this.loggingService = loggingService;\n this.httpClient = httpClient;\n this.trackingLogApiUrl = `${config.LMS_BASE_URL}/event`;\n this.segmentKey = config.SEGMENT_KEY;\n this.hasIdentifyBeenCalled = false;\n this.segmentInitialized = false;\n\n if (this.segmentKey) {\n this.initializeSegment();\n }\n }\n\n // The code in this function is from Segment's website, with a few updates:\n // - It uses the segmentKey from the SegmentAnalyticsService instance.\n // - It also saves a \"segmentInitialized\" variable on the SegmentAnalyticsService instance so\n // that the service can keep track of its own initialization state.\n // Reference:\n // https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/quickstart/\n initializeSegment() {\n // Create a queue, but don't obliterate an existing one!\n global.analytics = global.analytics || [];\n const { analytics } = global;\n\n // If the real analytics.js is already on the page return.\n if (analytics.initialize) {\n this.segmentInitialized = true;\n return;\n }\n\n // If the snippet was invoked do nothing.\n if (analytics.invoked) {\n this.segmentInitialized = true;\n return;\n }\n\n // Invoked flag, to make sure the snippet\n // is never invoked twice.\n analytics.invoked = true;\n\n // A list of the methods in Analytics.js to stub.\n analytics.methods = [\n 'trackSubmit',\n 'trackClick',\n 'trackLink',\n 'trackForm',\n 'pageview',\n 'identify',\n 'reset',\n 'group',\n 'track',\n 'ready',\n 'alias',\n 'debug',\n 'page',\n 'once',\n 'off',\n 'on',\n ];\n\n // Define a factory to create stubs. These are placeholders\n // for methods in Analytics.js so that you never have to wait\n // for it to load to actually record data. The `method` is\n // stored as the first argument, so we can replay the data.\n analytics.factory = method => ((...args) => {\n args.unshift(method);\n analytics.push(args);\n return analytics;\n });\n\n // For each of our methods, generate a queueing stub.\n analytics.methods.forEach((key) => {\n analytics[key] = analytics.factory(key);\n });\n\n // Define a method to load Analytics.js from our CDN,\n // and that will be sure to only ever load it once.\n analytics.load = (key, options) => {\n // Create an async script element based on your key.\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.onerror = () => {\n this.segmentInitialized = false;\n const event = new Event('segmentFailed');\n document.dispatchEvent(event);\n };\n script.async = true;\n script.src = `https://cdn.segment.com/analytics.js/v1/${key}/analytics.min.js`;\n\n // Insert our script next to the first script element.\n const first = document.getElementsByTagName('script')[0];\n first.parentNode.insertBefore(script, first);\n analytics._loadOptions = options; // eslint-disable-line no-underscore-dangle\n\n this.segmentInitialized = true;\n };\n\n // Add a version to keep track of what's in the wild.\n analytics.SNIPPET_VERSION = '4.1.0';\n\n // Load Analytics.js with your key, which will automatically\n // load the tools you've enabled for your account. Boosh!\n analytics.load(this.segmentKey);\n }\n\n /**\n * Checks that identify was first called. Otherwise, logs error.\n *\n */\n checkIdentifyCalled() {\n if (!this.hasIdentifyBeenCalled) {\n this.loggingService.logError('Identify must be called before other tracking events.');\n }\n }\n\n /**\n * Logs events to tracking log and downstream.\n * For tracking log event documentation, see\n * https://openedx.atlassian.net/wiki/spaces/AN/pages/13205895/Event+Design+and+Review+Process\n *\n * @param {string} eventName (event_type on backend, but named to match Segment api)\n * @param {Object} properties (event on backend, but named properties to match Segment api)\n * @returns {Promise} The promise returned by HttpClient.post.\n */\n sendTrackingLogEvent(eventName, properties) {\n const snakeEventData = snakeCaseObject(properties, { deep: true });\n const serverData = {\n event_type: eventName,\n event: JSON.stringify(snakeEventData),\n page: global.location.href,\n };\n return this.httpClient.post(\n this.trackingLogApiUrl,\n formurlencoded(serverData),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n ).catch((error) => {\n this.loggingService.logError(error);\n });\n }\n\n /**\n * * Send identify call to Segment.\n *\n * @param {string} userId\n * @param {*} [traits]\n */\n identifyAuthenticatedUser(userId, traits) {\n if (!userId) {\n throw new Error('UserId is required for identifyAuthenticatedUser.');\n }\n\n if (!this.segmentInitialized) {\n return;\n }\n global.analytics.identify(userId, traits);\n this.hasIdentifyBeenCalled = true;\n }\n\n /**\n * Send anonymous identify call to Segment's identify.\n *\n * @param {*} [traits]\n * @returns {Promise} Promise that will resolve once the document readyState is complete\n */\n identifyAnonymousUser(traits) {\n if (!this.segmentInitialized) {\n return Promise.resolve();\n }\n // if we do not have an authenticated user (indicated by being in this method),\n // but we still have a user id associated in segment, reset the local segment state\n // This has to be wrapped in the analytics.ready() callback because the analytics.user()\n // function isn't available until the analytics.js package has finished initializing.\n return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars\n global.analytics.ready(() => {\n if (global.analytics.user().id()) {\n global.analytics.reset();\n }\n global.analytics.identify(traits);\n this.hasIdentifyBeenCalled = true;\n resolve();\n });\n\n // this is added to handle a specific use-case where if a user has blocked the analytics\n // tools in their browser, this promise does not get resolved and user sees a blank\n // page. Dispatching this event in script.onerror callback in analytics.load.\n document.addEventListener('segmentFailed', resolve);\n // This is added to handle the google analytics blocked case which is injected into\n // the DOM by segment.min.js.\n setTimeout(() => {\n if (!global.ga || !global.ga.create) {\n this.segmentInitialized = false;\n resolve();\n }\n }, 2000);\n });\n }\n\n /**\n * Sends a track event to Segment and downstream.\n * Note: For links and forms, you should use trackLink and trackForm instead.\n *\n * @param {*} eventName\n * @param {*} [properties]\n */\n sendTrackEvent(eventName, properties) {\n if (!this.segmentInitialized) {\n return;\n }\n this.checkIdentifyCalled();\n global.analytics.track(eventName, properties);\n }\n\n /**\n * Sends a page event to Segment and downstream.\n *\n * @param {*} [name] If only one string arg provided, assumed to be name.\n * @param {*} [category] Name is required to pass a category.\n * @param {*} [properties]\n */\n sendPageEvent(category, name, properties) {\n if (!this.segmentInitialized) {\n return;\n }\n this.checkIdentifyCalled();\n global.analytics.page(category, name, properties);\n }\n}\n\nexport default SegmentAnalyticsService;\n"],"file":"SegmentAnalyticsService.js"}
|
|
1
|
+
{"version":3,"sources":["../../src/analytics/SegmentAnalyticsService.js"],"names":["formurlencoded","snakeCaseObject","SegmentAnalyticsService","httpClient","loggingService","config","trackingLogApiUrl","LMS_BASE_URL","segmentKey","SEGMENT_KEY","hasIdentifyBeenCalled","segmentInitialized","initializeSegment","global","analytics","initialize","invoked","methods","factory","method","args","unshift","push","forEach","key","load","options","script","document","createElement","type","onerror","event","Event","dispatchEvent","async","src","first","getElementsByTagName","parentNode","insertBefore","_loadOptions","SNIPPET_VERSION","logError","eventName","properties","snakeEventData","deep","serverData","event_type","JSON","stringify","page","location","href","post","headers","error","userId","traits","Error","identify","Promise","resolve","reject","ready","user","id","reset","addEventListener","setTimeout","ga","create","google_tag_manager","checkIdentifyCalled","track","category","name"],"mappings":"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","sourcesContent":["import formurlencoded from 'form-urlencoded';\nimport { snakeCaseObject } from '../utils';\n\n/**\n * @implements {AnalyticsService}\n * @memberof module:Analytics\n */\nclass SegmentAnalyticsService {\n constructor({ httpClient, loggingService, config }) {\n this.loggingService = loggingService;\n this.httpClient = httpClient;\n this.trackingLogApiUrl = `${config.LMS_BASE_URL}/event`;\n this.segmentKey = config.SEGMENT_KEY;\n this.hasIdentifyBeenCalled = false;\n this.segmentInitialized = false;\n\n if (this.segmentKey) {\n this.initializeSegment();\n }\n }\n\n // The code in this function is from Segment's website, with a few updates:\n // - It uses the segmentKey from the SegmentAnalyticsService instance.\n // - It also saves a \"segmentInitialized\" variable on the SegmentAnalyticsService instance so\n // that the service can keep track of its own initialization state.\n // Reference:\n // https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/quickstart/\n initializeSegment() {\n // Create a queue, but don't obliterate an existing one!\n global.analytics = global.analytics || [];\n const { analytics } = global;\n\n // If the real analytics.js is already on the page return.\n if (analytics.initialize) {\n this.segmentInitialized = true;\n return;\n }\n\n // If the snippet was invoked do nothing.\n if (analytics.invoked) {\n this.segmentInitialized = true;\n return;\n }\n\n // Invoked flag, to make sure the snippet\n // is never invoked twice.\n analytics.invoked = true;\n\n // A list of the methods in Analytics.js to stub.\n analytics.methods = [\n 'trackSubmit',\n 'trackClick',\n 'trackLink',\n 'trackForm',\n 'pageview',\n 'identify',\n 'reset',\n 'group',\n 'track',\n 'ready',\n 'alias',\n 'debug',\n 'page',\n 'once',\n 'off',\n 'on',\n ];\n\n // Define a factory to create stubs. These are placeholders\n // for methods in Analytics.js so that you never have to wait\n // for it to load to actually record data. The `method` is\n // stored as the first argument, so we can replay the data.\n analytics.factory = method => ((...args) => {\n args.unshift(method);\n analytics.push(args);\n return analytics;\n });\n\n // For each of our methods, generate a queueing stub.\n analytics.methods.forEach((key) => {\n analytics[key] = analytics.factory(key);\n });\n\n // Define a method to load Analytics.js from our CDN,\n // and that will be sure to only ever load it once.\n analytics.load = (key, options) => {\n // Create an async script element based on your key.\n const script = document.createElement('script');\n script.type = 'text/javascript';\n script.onerror = () => {\n this.segmentInitialized = false;\n const event = new Event('segmentFailed');\n document.dispatchEvent(event);\n };\n script.async = true;\n script.src = `https://cdn.segment.com/analytics.js/v1/${key}/analytics.min.js`;\n\n // Insert our script next to the first script element.\n const first = document.getElementsByTagName('script')[0];\n first.parentNode.insertBefore(script, first);\n analytics._loadOptions = options; // eslint-disable-line no-underscore-dangle\n\n this.segmentInitialized = true;\n };\n\n // Add a version to keep track of what's in the wild.\n analytics.SNIPPET_VERSION = '4.1.0';\n\n // Load Analytics.js with your key, which will automatically\n // load the tools you've enabled for your account. Boosh!\n analytics.load(this.segmentKey);\n }\n\n /**\n * Checks that identify was first called. Otherwise, logs error.\n *\n */\n checkIdentifyCalled() {\n if (!this.hasIdentifyBeenCalled) {\n this.loggingService.logError('Identify must be called before other tracking events.');\n }\n }\n\n /**\n * Logs events to tracking log and downstream.\n * For tracking log event documentation, see\n * https://openedx.atlassian.net/wiki/spaces/AN/pages/13205895/Event+Design+and+Review+Process\n *\n * @param {string} eventName (event_type on backend, but named to match Segment api)\n * @param {Object} properties (event on backend, but named properties to match Segment api)\n * @returns {Promise} The promise returned by HttpClient.post.\n */\n sendTrackingLogEvent(eventName, properties) {\n const snakeEventData = snakeCaseObject(properties, { deep: true });\n const serverData = {\n event_type: eventName,\n event: JSON.stringify(snakeEventData),\n page: global.location.href,\n };\n return this.httpClient.post(\n this.trackingLogApiUrl,\n formurlencoded(serverData),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n },\n ).catch((error) => {\n this.loggingService.logError(error);\n });\n }\n\n /**\n * * Send identify call to Segment.\n *\n * @param {string} userId\n * @param {*} [traits]\n */\n identifyAuthenticatedUser(userId, traits) {\n if (!userId) {\n throw new Error('UserId is required for identifyAuthenticatedUser.');\n }\n\n if (!this.segmentInitialized) {\n return;\n }\n global.analytics.identify(userId, traits);\n this.hasIdentifyBeenCalled = true;\n }\n\n /**\n * Send anonymous identify call to Segment's identify.\n *\n * @param {*} [traits]\n * @returns {Promise} Promise that will resolve once the document readyState is complete\n */\n identifyAnonymousUser(traits) {\n if (!this.segmentInitialized) {\n return Promise.resolve();\n }\n // if we do not have an authenticated user (indicated by being in this method),\n // but we still have a user id associated in segment, reset the local segment state\n // This has to be wrapped in the analytics.ready() callback because the analytics.user()\n // function isn't available until the analytics.js package has finished initializing.\n return new Promise((resolve, reject) => { // eslint-disable-line no-unused-vars\n global.analytics.ready(() => {\n if (global.analytics.user().id()) {\n global.analytics.reset();\n }\n global.analytics.identify(traits);\n this.hasIdentifyBeenCalled = true;\n resolve();\n });\n\n // this is added to handle a specific use-case where if a user has blocked the analytics\n // tools in their browser, this promise does not get resolved and user sees a blank\n // page. Dispatching this event in script.onerror callback in analytics.load.\n document.addEventListener('segmentFailed', resolve);\n // This is added to handle the google analytics blocked case which is injected into\n // the DOM by segment.min.js.\n setTimeout(() => {\n if (!global.ga || !global.ga.create || !global.google_tag_manager) {\n this.segmentInitialized = false;\n resolve();\n }\n }, 2000);\n });\n }\n\n /**\n * Sends a track event to Segment and downstream.\n * Note: For links and forms, you should use trackLink and trackForm instead.\n *\n * @param {*} eventName\n * @param {*} [properties]\n */\n sendTrackEvent(eventName, properties) {\n if (!this.segmentInitialized) {\n return;\n }\n this.checkIdentifyCalled();\n global.analytics.track(eventName, properties);\n }\n\n /**\n * Sends a page event to Segment and downstream.\n *\n * @param {*} [name] If only one string arg provided, assumed to be name.\n * @param {*} [category] Name is required to pass a category.\n * @param {*} [properties]\n */\n sendPageEvent(category, name, properties) {\n if (!this.segmentInitialized) {\n return;\n }\n this.checkIdentifyCalled();\n global.analytics.page(category, name, properties);\n }\n}\n\nexport default SegmentAnalyticsService;\n"],"file":"SegmentAnalyticsService.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edx/frontend-platform",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.5",
|
|
4
4
|
"description": "Foundational application framework for Open edX micro-frontend applications.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -32,11 +32,11 @@
|
|
|
32
32
|
"homepage": "https://github.com/edx/frontend-platform#readme",
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
|
|
35
|
-
"@edx/frontend-build": "
|
|
36
|
-
"@edx/paragon": "16.
|
|
35
|
+
"@edx/frontend-build": "9.0.5",
|
|
36
|
+
"@edx/paragon": "16.22.0",
|
|
37
37
|
"axios-mock-adapter": "1.20.0",
|
|
38
38
|
"codecov": "3.8.3",
|
|
39
|
-
"core-js": "3.
|
|
39
|
+
"core-js": "3.19.3",
|
|
40
40
|
"enzyme": "3.11.0",
|
|
41
41
|
"enzyme-adapter-react-16": "1.15.6",
|
|
42
42
|
"husky": "7.0.4",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"universal-cookie": "4.0.4"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"@edx/paragon": ">= 10.0.0
|
|
73
|
+
"@edx/paragon": ">= 10.0.0 < 17.0.0",
|
|
74
74
|
"prop-types": "^15.7.2",
|
|
75
75
|
"react": "^16.9.0",
|
|
76
76
|
"react-dom": "^16.9.0",
|