@financial-times/n-myft-ui 30.4.4 → 31.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -44,7 +44,22 @@ const instantAlertsIconUpdate = ({ event, followPlusInstantAlerts }) => {
44
44
  toggleInstantAlertsClass({instantAlertsOn, followPlusInstantAlerts });
45
45
  };
46
46
 
47
+ const instantAlertsIconOff = ({ event, followPlusInstantAlerts }) => {
48
+ const modalConceptId = followPlusInstantAlerts.dataset.conceptId;
49
+ if (!event || !modalConceptId) {
50
+ return;
51
+ }
47
52
 
53
+ const currentConcept = event.detail.subject === modalConceptId;
54
+ if (!currentConcept) {
55
+ return;
56
+ }
57
+
58
+ toggleInstantAlertsClass({
59
+ instantAlertsOn: false,
60
+ followPlusInstantAlerts,
61
+ });
62
+ };
48
63
 
49
64
 
50
65
  const sendModalToggleEvent = ({ followPlusInstantAlerts }) => {
@@ -73,4 +88,5 @@ export default () => {
73
88
  document.body.addEventListener('myft.user.followed.concept.load', (event) => instantAlertsIconLoad({event, followPlusInstantAlerts}));
74
89
 
75
90
  document.body.addEventListener('myft.user.followed.concept.update', (event) => instantAlertsIconUpdate({event, followPlusInstantAlerts}));
91
+ document.body.addEventListener('myft.user.followed.concept.remove', (event) => instantAlertsIconOff({ event, followPlusInstantAlerts }));
76
92
  };
@@ -1,6 +1,5 @@
1
1
  import myFtClient from 'next-myft-client';
2
2
  import getToken from '../../../myft/ui/lib/get-csrf-token';
3
- import oTracking from '@financial-times/o-tracking';
4
3
 
5
4
  const csrfToken = getToken();
6
5
 
@@ -46,25 +45,44 @@ const positionModal = ({ event, preferencesModal } = {}) => {
46
45
  }
47
46
  };
48
47
 
49
- const preferenceModalShowAndHide = ({ event, preferencesModal }) => {
48
+ const toggleCheckboxStatus = ({ instantAlertsCheckbox, isChecked }) => {
49
+ if (isChecked) {
50
+ instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-off';
51
+ instantAlertsCheckbox.checked = true;
52
+ } else {
53
+ instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-on';
54
+ instantAlertsCheckbox.checked = false;
55
+ }
56
+ }
57
+
58
+ const tracking = (conceptId) => {
59
+ const trackingData = {
60
+ category: 'component',
61
+ action: 'view',
62
+ concept_id: conceptId,
63
+ component: {
64
+ type: 'component',
65
+ name: 'pop-up-box',
66
+ id: '72de123e-5082-11ee-be56-0242ac120002',
67
+ }
68
+ }
69
+
70
+ const trackingEvent = new CustomEvent('oTracking.event', {
71
+ detail: trackingData,
72
+ bubbles: true
73
+ });
74
+
75
+ document.body.dispatchEvent(trackingEvent);
76
+ };
77
+
78
+ const preferenceModalShowAndHide = ({ event, preferencesModal, conceptId }) => {
50
79
  preferencesModal.classList.toggle('n-myft-ui__preferences-modal--show');
51
80
 
52
81
  if (preferencesModal.classList.contains('n-myft-ui__preferences-modal--show')) {
53
82
  positionModal({ event, preferencesModal });
54
- const opts = {
55
- category: 'component',
56
- selector: '[data-component-id="myft-preferences-modal"]',
57
- getContextData: () => {
58
- return {
59
- component: {
60
- type: 'component',
61
- name: 'pop-up-box',
62
- id: '72de123e-5082-11ee-be56-0242ac120002',
63
- },
64
- };
65
- },
66
- };
67
- oTracking.view.init(opts);
83
+
84
+ tracking(conceptId);
85
+
68
86
  } else {
69
87
  // Remove existing errors when hiding the modal
70
88
  renderError({
@@ -79,9 +97,7 @@ const removeTopic = async ({ event, conceptId, preferencesModal }) => {
79
97
 
80
98
  try {
81
99
  await myFtClient.remove('user', null, 'followed', 'concept', conceptId, { token: csrfToken });
82
-
83
100
  preferenceModalShowAndHide({ preferencesModal });
84
-
85
101
  } catch (error) {
86
102
  renderError({ message: 'Sorry, we are unable to remove this topic. Please try again later or try from <a href="/myft">myFT</a>', preferencesModal });
87
103
  }
@@ -91,8 +107,7 @@ const removeTopic = async ({ event, conceptId, preferencesModal }) => {
91
107
 
92
108
  const getAlertsPreferenceText = (addedTextBuffer) => {
93
109
  const alertsEnabledText = `Your delivery channels: ${addedTextBuffer.join(', ')}.`;
94
- const alertsDisabledText = 'You have previously disabled all delivery channels';
95
- return Array.isArray(addedTextBuffer) && addedTextBuffer.length > 0 ? alertsEnabledText : alertsDisabledText;
110
+ return Array.isArray(addedTextBuffer) && addedTextBuffer.length > 0 ? alertsEnabledText : '';
96
111
  };
97
112
 
98
113
  const getAlertsPreferences = async ({ event, preferencesModal }) => {
@@ -138,13 +153,11 @@ const setCheckboxForAlertConcept = ({ event, preferencesModal }) => {
138
153
  // 2. the said concept has instant alert enabled
139
154
  // if so, check the checkbox within the modal
140
155
  const currentConcept = event.detail.items.find(item => item && item.uuid === conceptId);
141
- if (currentConcept && currentConcept._rel && currentConcept._rel.instant) {
142
- instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-off';
143
- instantAlertsCheckbox.checked = true;
144
- } else {
145
- instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-on';
146
- instantAlertsCheckbox.checked = false;
147
- }
156
+ const isChecked = currentConcept && currentConcept._rel && currentConcept._rel.instant;
157
+ toggleCheckboxStatus({
158
+ instantAlertsCheckbox,
159
+ isChecked,
160
+ });
148
161
  };
149
162
 
150
163
  const toggleInstantAlertsPreference = async ({ event, conceptId, preferencesModal }) => {
@@ -160,11 +173,13 @@ const toggleInstantAlertsPreference = async ({ event, conceptId, preferencesModa
160
173
  token: csrfToken
161
174
  };
162
175
 
176
+ toggleCheckboxStatus({
177
+ instantAlertsCheckbox,
178
+ isChecked: instantAlertsCheckbox.checked,
179
+ });
163
180
  if (instantAlertsCheckbox.checked) {
164
- instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-off';
165
181
  data._rel = {instant: 'true'};
166
182
  } else {
167
- instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-on';
168
183
  data._rel = {instant: 'false'};
169
184
  }
170
185
 
@@ -184,6 +199,21 @@ const toggleInstantAlertsPreference = async ({ event, conceptId, preferencesModa
184
199
  instantAlertsCheckbox.removeAttribute('disabled');
185
200
  };
186
201
 
202
+ const setCheckboxForAlertConceptToOff = ({ event, preferencesModal }) => {
203
+ const conceptId = preferencesModal.dataset.conceptId;
204
+ const instantAlertsCheckbox = preferencesModal.querySelector('[data-component-id="myft-preferences-modal-checkbox"]');
205
+
206
+ const currentConcept = event.detail.subject === conceptId;
207
+ if (!currentConcept) {
208
+ return;
209
+ }
210
+
211
+ toggleCheckboxStatus({
212
+ instantAlertsCheckbox,
213
+ isChecked: false,
214
+ });
215
+ }
216
+
187
217
  export default () => {
188
218
  /**
189
219
  * This feature is part of a test
@@ -213,9 +243,10 @@ export default () => {
213
243
 
214
244
  instantAlertsCheckbox.addEventListener('change', event => toggleInstantAlertsPreference({ event, conceptId, preferencesModal }));
215
245
 
216
- document.addEventListener('myft.preference-modal.show-hide.toggle', event => preferenceModalShowAndHide({ event, preferencesModal }));
246
+ document.addEventListener('myft.preference-modal.show-hide.toggle', event => preferenceModalShowAndHide({ event, preferencesModal, conceptId }));
217
247
 
218
248
  document.addEventListener('myft.user.preferred.preference.load', (event) => getAlertsPreferences({ event, preferencesModal }));
219
249
 
220
250
  document.body.addEventListener('myft.user.followed.concept.load', (event) => setCheckboxForAlertConcept({ event, preferencesModal }));
251
+ document.body.addEventListener('myft.user.followed.concept.remove', (event) => setCheckboxForAlertConceptToOff({ event, preferencesModal }));
221
252
  };
@@ -26,7 +26,6 @@ export default function InstantAlertsPreferencesModal({ flags, conceptId, visibl
26
26
  className={`n-myft-ui__preferences-modal ${visible ? 'n-myft-ui__preferences-modal--show' : ''}`}
27
27
  data-component-id="myft-preferences-modal"
28
28
  data-concept-id={conceptId}
29
- data-o-tracking-view="true"
30
29
  >
31
30
  <div className="n-myft-ui__preferences-modal__content">
32
31
  <span className="o-forms-input o-forms-input--checkbox">
@@ -37,6 +36,7 @@ export default function InstantAlertsPreferencesModal({ flags, conceptId, visibl
37
36
  name="receive-instant-alerts"
38
37
  value="receive-instant-alerts"
39
38
  data-component-id="myft-preferences-modal-checkbox"
39
+ data-trackable-context-concept_id={conceptId}
40
40
  />
41
41
  <span className="o-forms-input__label n-myft-ui__preferences-modal__checkbox__message">
42
42
  Get instant alerts for this topic
@@ -45,9 +45,9 @@ export default function InstantAlertsPreferencesModal({ flags, conceptId, visibl
45
45
  </span>
46
46
 
47
47
  <p data-component-id="myft-preferences-modal-list" className="n-myft-ui__preferences-modal__text"></p>
48
- <a className="n-myft-ui__preferences-modal__text" href="/myft/alerts" data-trackable="pop-up-box|contact-preference">Manage your preferences here</a>
48
+ <a className="n-myft-ui__preferences-modal__text" href="/myft/alerts" data-trackable="pop-up-box|contact-preference" data-trackable-context-concept_id={conceptId}>Manage your delivery channels here</a>
49
49
  <span className="n-myft-ui__preferences-modal-error" data-component-id="myft-preference-modal-error"></span>
50
- <button className="n-myft-ui__preferences-modal__remove-button" data-component-id="myft-preference-modal-remove" data-trackable="pop-up-box|remove-from-myFT">Remove from myFT</button>
50
+ <button className="n-myft-ui__preferences-modal__remove-button" data-component-id="myft-preference-modal-remove" data-trackable="pop-up-box|remove-from-myFT" data-trackable-context-concept_id={conceptId}>Remove from myFT</button>
51
51
  </div>
52
52
  </div>
53
53
  );
@@ -41,8 +41,7 @@ function InstantAlertsPreferencesModal(_ref) {
41
41
  {
42
42
  className: 'n-myft-ui__preferences-modal ' + (visible ? 'n-myft-ui__preferences-modal--show' : ''),
43
43
  'data-component-id': 'myft-preferences-modal',
44
- 'data-concept-id': conceptId,
45
- 'data-o-tracking-view': 'true'
44
+ 'data-concept-id': conceptId
46
45
  },
47
46
  _react2.default.createElement(
48
47
  'div',
@@ -58,7 +57,8 @@ function InstantAlertsPreferencesModal(_ref) {
58
57
  type: 'checkbox',
59
58
  name: 'receive-instant-alerts',
60
59
  value: 'receive-instant-alerts',
61
- 'data-component-id': 'myft-preferences-modal-checkbox'
60
+ 'data-component-id': 'myft-preferences-modal-checkbox',
61
+ 'data-trackable-context-concept_id': conceptId
62
62
  }),
63
63
  _react2.default.createElement(
64
64
  'span',
@@ -70,13 +70,13 @@ function InstantAlertsPreferencesModal(_ref) {
70
70
  _react2.default.createElement('p', { 'data-component-id': 'myft-preferences-modal-list', className: 'n-myft-ui__preferences-modal__text' }),
71
71
  _react2.default.createElement(
72
72
  'a',
73
- { className: 'n-myft-ui__preferences-modal__text', href: '/myft/alerts', 'data-trackable': 'pop-up-box|contact-preference' },
74
- 'Manage your preferences here'
73
+ { className: 'n-myft-ui__preferences-modal__text', href: '/myft/alerts', 'data-trackable': 'pop-up-box|contact-preference', 'data-trackable-context-concept_id': conceptId },
74
+ 'Manage your delivery channels here'
75
75
  ),
76
76
  _react2.default.createElement('span', { className: 'n-myft-ui__preferences-modal-error', 'data-component-id': 'myft-preference-modal-error' }),
77
77
  _react2.default.createElement(
78
78
  'button',
79
- { className: 'n-myft-ui__preferences-modal__remove-button', 'data-component-id': 'myft-preference-modal-remove', 'data-trackable': 'pop-up-box|remove-from-myFT' },
79
+ { className: 'n-myft-ui__preferences-modal__remove-button', 'data-component-id': 'myft-preference-modal-remove', 'data-trackable': 'pop-up-box|remove-from-myFT', 'data-trackable-context-concept_id': conceptId },
80
80
  'Remove from myFT'
81
81
  )
82
82
  )
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@financial-times/n-myft-ui",
3
- "version": "30.4.4",
3
+ "version": "31.0.0",
4
4
  "description": "Client side component for interaction with myft",
5
5
  "main": "server.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1",
8
8
  "commit": "commit-wizard",
9
- "prepare": "npx snyk protect || npx snyk protect -d || true",
10
- "preinstall": "[ \"$INIT_CWD\" != \"$PWD\" ] || npm_config_yes=true npx check-engine"
9
+ "prepare": "npx snyk protect || npx snyk protect -d || true"
11
10
  },
12
11
  "repository": {
13
12
  "type": "git",
@@ -20,48 +19,48 @@
20
19
  },
21
20
  "homepage": "https://github.com/Financial-Times/n-myft-ui#readme",
22
21
  "devDependencies": {
23
- "@financial-times/dotcom-build-base": "^8.1.0",
24
- "@financial-times/dotcom-build-code-splitting": "^8.1.0",
25
- "@financial-times/dotcom-build-js": "^8.1.0",
26
- "@financial-times/dotcom-build-sass": "^8.1.0",
27
- "@financial-times/dotcom-server-handlebars": "^8.1.0",
28
- "@financial-times/n-express": "^27.5.0",
29
- "@financial-times/n-gage": "^8.3.2",
22
+ "@financial-times/dotcom-build-base": "^8.2.1",
23
+ "@financial-times/dotcom-build-code-splitting": "^8.2.1",
24
+ "@financial-times/dotcom-build-js": "^8.2.1",
25
+ "@financial-times/dotcom-build-sass": "^8.2.1",
26
+ "@financial-times/dotcom-server-handlebars": "^8.2.1",
27
+ "@financial-times/n-express": "^28.0.3",
28
+ "@financial-times/n-gage": "^9.0.1",
30
29
  "ascii-table": "0.0.9",
31
30
  "autoprefixer": "9.7.0",
32
31
  "aws-sdk-mock": "4.5.0",
33
32
  "babel-cli": "^6.26.0",
34
- "babel-core": "^6.2.1",
33
+ "babel-core": "^6.26.3",
35
34
  "babel-loader": "7.1.4",
36
35
  "babel-plugin-add-module-exports": "^0.3.0",
37
36
  "babel-plugin-transform-async-to-generator": "^6.24.1",
38
- "babel-plugin-transform-es2015-classes": "^6.8.0",
39
- "babel-plugin-transform-es2015-modules-commonjs": "^6.5.2",
37
+ "babel-plugin-transform-es2015-classes": "^6.24.1",
38
+ "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
40
39
  "babel-plugin-transform-runtime": "^6.23.0",
41
40
  "babel-preset-env": "^1.7.0",
42
41
  "babel-preset-es2015": "^6.6.0",
43
42
  "babel-preset-react": "^6.24.1",
44
- "babel-runtime": "^6.9.2",
45
- "brotli": "^1.3.1",
46
- "chai": "4.2.0",
43
+ "babel-runtime": "^6.26.0",
44
+ "brotli": "^1.3.3",
45
+ "chai": "4.3.8",
47
46
  "chalk": "2.4.2",
48
- "check-engine": "^1.10.1",
47
+ "check-engine": "^1.12.0",
49
48
  "css-loader": "^0.23.1",
50
49
  "denodeify": "^1.2.1",
51
50
  "eslint": "6.5.1",
52
- "eslint-plugin-react": "^7.33.1",
51
+ "eslint-plugin-react": "^7.33.2",
53
52
  "extract-css-block-webpack-plugin": "^1.3.0",
54
53
  "fetch-mock": "^5.0.3",
55
- "handlebars": "^4.0.6",
56
- "handlebars-loader": "^1.4.0",
54
+ "handlebars": "^4.7.8",
55
+ "handlebars-loader": "^1.7.3",
57
56
  "http-server": "^0.11.1",
58
57
  "hyperons": "^0.4.1",
59
58
  "imports-loader": "0.8.0",
60
59
  "inject-loader": "^4.0.1",
61
60
  "karma": "4.4.1",
62
- "karma-browserstack-launcher": "1.5.1",
61
+ "karma-browserstack-launcher": "1.6.0",
63
62
  "karma-chai": "^0.1.0",
64
- "karma-chrome-launcher": "3.1.0",
63
+ "karma-chrome-launcher": "3.2.0",
65
64
  "karma-firefox-launcher": "^1.0.0",
66
65
  "karma-html-reporter": "^0.2.6",
67
66
  "karma-mocha": "^1.3.0",
@@ -71,22 +70,23 @@
71
70
  "karma-viewport": "^1.0.9",
72
71
  "karma-webpack": "^4.0.2",
73
72
  "lintspaces-cli": "^0.7.0",
74
- "lolex": "5.1.1",
73
+ "lolex": "5.1.2",
75
74
  "mocha": "6.2.2",
76
75
  "mockery": "2.1.0",
77
76
  "node-fetch": "2.6.0",
78
77
  "nodemon": "^1.9.2",
79
- "npm-prepublish": "^1.2.1",
80
- "pa11y-ci": "^2.1.1",
78
+ "npm-prepublish": "^1.2.3",
79
+ "pa11y-ci": "^3.0.1",
81
80
  "postcss-loader": "^0.9.1",
81
+ "puppeteer": "^18.2.1",
82
82
  "regenerator-runtime": "^0.13.3",
83
- "sass": "^1.51.0",
83
+ "sass": "^1.68.0",
84
84
  "semver": "6.3.0",
85
85
  "sinon": "^7.1.0",
86
- "sinon-chai": "^3.2.0",
87
- "snyk": "^1.216.5",
86
+ "sinon-chai": "^3.7.0",
87
+ "snyk": "^1.1227.0",
88
88
  "sucrase": "^3.34.0",
89
- "webpack": "^4.46.0",
89
+ "webpack": "^4.47.0",
90
90
  "webpack-cli": "^4.9.2"
91
91
  },
92
92
  "peerDependencies": {
@@ -104,8 +104,7 @@
104
104
  "react": "^16.14.0"
105
105
  },
106
106
  "dependencies": {
107
- "@financial-times/o-tracking": "^4.5.0",
108
- "date-fns": "2.16.1",
107
+ "date-fns": "2.30.0",
109
108
  "fetchres": "^1.7.2",
110
109
  "form-serialize": "^0.7.2",
111
110
  "ftdomdelegate": "^4.0.6",
@@ -115,12 +114,14 @@
115
114
  "ready-state": "^2.0.5",
116
115
  "superstore-sync": "^2.1.1"
117
116
  },
117
+ "overrides": {
118
+ "puppeteer": "$puppeteer"
119
+ },
118
120
  "volta": {
119
- "node": "16.14.2",
120
- "npm": "7.24.2"
121
+ "node": "18.18.0"
121
122
  },
122
123
  "engines": {
123
- "node": "16.x",
124
+ "node": "16.x || 18.x",
124
125
  "npm": "7.x || 8.x || 9.x"
125
126
  },
126
127
  "x-dash": {