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

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.
@@ -10,6 +10,7 @@
10
10
  "hasInstallScript": true,
11
11
  "license": "ISC",
12
12
  "dependencies": {
13
+ "@financial-times/o-tracking": "^4.5.0",
13
14
  "date-fns": "2.16.1",
14
15
  "fetchres": "^1.7.2",
15
16
  "form-serialize": "^0.7.2",
@@ -3378,6 +3379,22 @@
3378
3379
  "@financial-times/o-visual-effects": "^4.0.1"
3379
3380
  }
3380
3381
  },
3382
+ "node_modules/@financial-times/o-tracking": {
3383
+ "version": "4.5.0",
3384
+ "resolved": "https://registry.npmjs.org/@financial-times/o-tracking/-/o-tracking-4.5.0.tgz",
3385
+ "integrity": "sha512-gPnAmMPqlYWf8xXNJkAYKQMpEWvHpjxajB4YnadbGhOGl2Zy8y5LJJqyzsfpqoBh51P7VDIc7yBF+A7fgaymYw==",
3386
+ "dependencies": {
3387
+ "ftdomdelegate": "^5"
3388
+ },
3389
+ "engines": {
3390
+ "npm": "^7 || ^8"
3391
+ }
3392
+ },
3393
+ "node_modules/@financial-times/o-tracking/node_modules/ftdomdelegate": {
3394
+ "version": "5.0.0",
3395
+ "resolved": "https://registry.npmjs.org/ftdomdelegate/-/ftdomdelegate-5.0.0.tgz",
3396
+ "integrity": "sha512-P9UmLMIq/ibxxFVBHlE2EIoHcFNDpamn3urRCwVWMnj3o9nAgLtqe64WVuqcGtkN4wujrBYeyxKCuN1/WO+bQw=="
3397
+ },
3381
3398
  "node_modules/@financial-times/o-typography": {
3382
3399
  "version": "7.5.0",
3383
3400
  "resolved": "https://registry.npmjs.org/@financial-times/o-typography/-/o-typography-7.5.0.tgz",
@@ -31386,6 +31403,21 @@
31386
31403
  "ftdomdelegate": "^4.0.6"
31387
31404
  }
31388
31405
  },
31406
+ "@financial-times/o-tracking": {
31407
+ "version": "4.5.0",
31408
+ "resolved": "https://registry.npmjs.org/@financial-times/o-tracking/-/o-tracking-4.5.0.tgz",
31409
+ "integrity": "sha512-gPnAmMPqlYWf8xXNJkAYKQMpEWvHpjxajB4YnadbGhOGl2Zy8y5LJJqyzsfpqoBh51P7VDIc7yBF+A7fgaymYw==",
31410
+ "requires": {
31411
+ "ftdomdelegate": "^5"
31412
+ },
31413
+ "dependencies": {
31414
+ "ftdomdelegate": {
31415
+ "version": "5.0.0",
31416
+ "resolved": "https://registry.npmjs.org/ftdomdelegate/-/ftdomdelegate-5.0.0.tgz",
31417
+ "integrity": "sha512-P9UmLMIq/ibxxFVBHlE2EIoHcFNDpamn3urRCwVWMnj3o9nAgLtqe64WVuqcGtkN4wujrBYeyxKCuN1/WO+bQw=="
31418
+ }
31419
+ }
31420
+ },
31389
31421
  "@financial-times/o-typography": {
31390
31422
  "version": "7.5.0",
31391
31423
  "resolved": "https://registry.npmjs.org/@financial-times/o-typography/-/o-typography-7.5.0.tgz",
@@ -40,7 +40,6 @@ const instantAlertsIconUpdate = ({ event, followPlusInstantAlerts }) => {
40
40
  return;
41
41
  }
42
42
 
43
-
44
43
  const instantAlertsOn = Boolean(currentConcept && currentConcept.rel && currentConcept.rel.properties && currentConcept.rel.properties.instant);
45
44
  toggleInstantAlertsClass({instantAlertsOn, followPlusInstantAlerts });
46
45
  };
@@ -72,5 +71,6 @@ export default () => {
72
71
  followPlusInstantAlerts.addEventListener('click', () => sendModalToggleEvent({followPlusInstantAlerts}));
73
72
 
74
73
  document.body.addEventListener('myft.user.followed.concept.load', (event) => instantAlertsIconLoad({event, followPlusInstantAlerts}));
74
+
75
75
  document.body.addEventListener('myft.user.followed.concept.update', (event) => instantAlertsIconUpdate({event, followPlusInstantAlerts}));
76
76
  };
@@ -1,5 +1,6 @@
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';
3
4
 
4
5
  const csrfToken = getToken();
5
6
 
@@ -50,6 +51,20 @@ const preferenceModalShowAndHide = ({ event, preferencesModal }) => {
50
51
 
51
52
  if (preferencesModal.classList.contains('n-myft-ui__preferences-modal--show')) {
52
53
  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);
53
68
  } else {
54
69
  // Remove existing errors when hiding the modal
55
70
  renderError({
@@ -74,6 +89,12 @@ const removeTopic = async ({ event, conceptId, preferencesModal }) => {
74
89
  event.target.removeAttribute('disabled');
75
90
  };
76
91
 
92
+ const getAlertsPreferenceText = (addedTextBuffer) => {
93
+ 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;
96
+ };
97
+
77
98
  const getAlertsPreferences = async ({ event, preferencesModal }) => {
78
99
  const preferencesList = preferencesModal.querySelector('[data-component-id="myft-preferences-modal-list"]');
79
100
 
@@ -91,6 +112,8 @@ const getAlertsPreferences = async ({ event, preferencesModal }) => {
91
112
  }
92
113
  });
93
114
 
115
+ preferencesList.innerHTML = getAlertsPreferenceText(addedTextBuffer);
116
+
94
117
  try {
95
118
  // We need the service worker registration to check for a subscription
96
119
  const serviceWorkerRegistration = await navigator.serviceWorker.ready;
@@ -98,43 +121,50 @@ const getAlertsPreferences = async ({ event, preferencesModal }) => {
98
121
  if (subscription) {
99
122
  addedTextBuffer.push('browser');
100
123
  }
101
-
102
124
  } catch (error) {
103
125
  // eslint-disable-next-line no-console
104
126
  console.warn('There was an error fetching the browser notification preferences', error);
105
127
  }
106
- const alertsEnabledText = `Your delivery channels: ${addedTextBuffer.join(', ')}.`;
107
- const alertsDisabledText = 'You have previously disabled all delivery channels';
108
- preferencesList.innerHTML = addedTextBuffer.length > 0 ? alertsEnabledText : alertsDisabledText;
128
+
129
+ preferencesList.innerHTML = getAlertsPreferenceText(addedTextBuffer);
109
130
  };
110
131
 
111
132
  const setCheckboxForAlertConcept = ({ event, preferencesModal }) => {
112
133
  const conceptId = preferencesModal.dataset.conceptId;
113
134
  const instantAlertsCheckbox = preferencesModal.querySelector('[data-component-id="myft-preferences-modal-checkbox"]');
135
+
114
136
  // search through all the concepts that the user has followed and check whether
115
137
  // 1. the concept which this instant alert modal controls is within them, AND;
116
138
  // 2. the said concept has instant alert enabled
117
139
  // if so, check the checkbox within the modal
118
140
  const currentConcept = event.detail.items.find(item => item && item.uuid === conceptId);
119
141
  if (currentConcept && currentConcept._rel && currentConcept._rel.instant) {
142
+ instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-off';
120
143
  instantAlertsCheckbox.checked = true;
121
144
  } else {
145
+ instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-on';
122
146
  instantAlertsCheckbox.checked = false;
123
147
  }
124
148
  };
125
149
 
126
150
  const toggleInstantAlertsPreference = async ({ event, conceptId, preferencesModal }) => {
127
- const instantAlertsToggle = event.target;
151
+ const instantAlertsCheckbox = event.target;
128
152
 
129
- instantAlertsToggle.setAttribute('disabled', true);
153
+ if (!instantAlertsCheckbox) {
154
+ return;
155
+ }
156
+
157
+ instantAlertsCheckbox.setAttribute('disabled', true);
130
158
 
131
159
  const data = {
132
160
  token: csrfToken
133
161
  };
134
162
 
135
- if (instantAlertsToggle.checked) {
163
+ if (instantAlertsCheckbox.checked) {
164
+ instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-off';
136
165
  data._rel = {instant: 'true'};
137
166
  } else {
167
+ instantAlertsCheckbox.dataset.trackable = 'pop-up-box|set-instant-alert-on';
138
168
  data._rel = {instant: 'false'};
139
169
  }
140
170
 
@@ -146,12 +176,12 @@ const toggleInstantAlertsPreference = async ({ event, conceptId, preferencesModa
146
176
  preferencesModal
147
177
  });
148
178
 
149
- instantAlertsToggle.checked = instantAlertsToggle.checked
179
+ instantAlertsCheckbox.checked = instantAlertsCheckbox.checked
150
180
  ? false
151
181
  : true;
152
182
  }
153
183
 
154
- instantAlertsToggle.removeAttribute('disabled');
184
+ instantAlertsCheckbox.removeAttribute('disabled');
155
185
  };
156
186
 
157
187
  export default () => {
@@ -162,16 +192,25 @@ export default () => {
162
192
  * If this was to be used in other locations it would need some additional work to avoid being singleton
163
193
  */
164
194
  const preferencesModal = document.querySelector('[data-component-id="myft-preferences-modal"]');
195
+
196
+ if (!preferencesModal) {
197
+ return;
198
+ }
165
199
  const conceptId = preferencesModal.dataset.conceptId;
166
200
 
167
- if (!preferencesModal || !conceptId) {
201
+ if (!conceptId) {
168
202
  return;
169
203
  }
170
204
 
171
205
  const removeTopicButton = preferencesModal.querySelector('[data-component-id="myft-preference-modal-remove"]');
172
206
  const instantAlertsCheckbox = preferencesModal.querySelector('[data-component-id="myft-preferences-modal-checkbox"]');
173
207
 
208
+ if (!removeTopicButton || !instantAlertsCheckbox) {
209
+ return;
210
+ }
211
+
174
212
  removeTopicButton.addEventListener('click', event => removeTopic({ event, conceptId, preferencesModal }));
213
+
175
214
  instantAlertsCheckbox.addEventListener('change', event => toggleInstantAlertsPreference({ event, conceptId, preferencesModal }));
176
215
 
177
216
  document.addEventListener('myft.preference-modal.show-hide.toggle', event => preferenceModalShowAndHide({ event, preferencesModal }));
@@ -26,6 +26,7 @@ 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"
29
30
  >
30
31
  <div className="n-myft-ui__preferences-modal__content">
31
32
  <span className="o-forms-input o-forms-input--checkbox">
@@ -44,9 +45,9 @@ export default function InstantAlertsPreferencesModal({ flags, conceptId, visibl
44
45
  </span>
45
46
 
46
47
  <p data-component-id="myft-preferences-modal-list" className="n-myft-ui__preferences-modal__text"></p>
47
- <a className="n-myft-ui__preferences-modal__text" href="/myft/alerts">Manage your preferences here</a>
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
49
  <span className="n-myft-ui__preferences-modal-error" data-component-id="myft-preference-modal-error"></span>
49
- <button className="n-myft-ui__preferences-modal__remove-button" data-component-id="myft-preference-modal-remove">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">Remove from myFT</button>
50
51
  </div>
51
52
  </div>
52
53
  );
@@ -41,7 +41,8 @@ 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
44
+ 'data-concept-id': conceptId,
45
+ 'data-o-tracking-view': 'true'
45
46
  },
46
47
  _react2.default.createElement(
47
48
  'div',
@@ -69,13 +70,13 @@ function InstantAlertsPreferencesModal(_ref) {
69
70
  _react2.default.createElement('p', { 'data-component-id': 'myft-preferences-modal-list', className: 'n-myft-ui__preferences-modal__text' }),
70
71
  _react2.default.createElement(
71
72
  'a',
72
- { className: 'n-myft-ui__preferences-modal__text', href: '/myft/alerts' },
73
+ { className: 'n-myft-ui__preferences-modal__text', href: '/myft/alerts', 'data-trackable': 'pop-up-box|contact-preference' },
73
74
  'Manage your preferences here'
74
75
  ),
75
76
  _react2.default.createElement('span', { className: 'n-myft-ui__preferences-modal-error', 'data-component-id': 'myft-preference-modal-error' }),
76
77
  _react2.default.createElement(
77
78
  'button',
78
- { className: 'n-myft-ui__preferences-modal__remove-button', 'data-component-id': 'myft-preference-modal-remove' },
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
80
  'Remove from myFT'
80
81
  )
81
82
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/n-myft-ui",
3
- "version": "30.4.3",
3
+ "version": "30.4.4",
4
4
  "description": "Client side component for interaction with myft",
5
5
  "main": "server.js",
6
6
  "scripts": {
@@ -104,6 +104,7 @@
104
104
  "react": "^16.14.0"
105
105
  },
106
106
  "dependencies": {
107
+ "@financial-times/o-tracking": "^4.5.0",
107
108
  "date-fns": "2.16.1",
108
109
  "fetchres": "^1.7.2",
109
110
  "form-serialize": "^0.7.2",
package/secrets.js CHANGED
@@ -6,6 +6,7 @@ module.exports = {
6
6
  '190b4443-dc03-bd53-e79b-b4b6fbd04e64', // segment ID for subscribe URL
7
7
  'ce23dd51-4421-32fc-23df-30099f38f1a4', // segment ID for USG test https://financialtimes.atlassian.net/browse/UG-1191
8
8
  'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', // regex for uuid generator
9
- 'a5676e20-5c92-47f3-a76c-11f9761121f5' // test/navigationAlphaTest.spec.js
9
+ 'a5676e20-5c92-47f3-a76c-11f9761121f5', // test/navigationAlphaTest.spec.js
10
+ '72de123e-5082-11ee-be56-0242ac120002' // components/jsx/preferences-modal/index.js
10
11
  ]
11
12
  };