@financial-times/n-myft-ui 30.4.2 → 30.4.4
Sign up to get free protection for your applications and to get access to all the features.
- package/build-state/npm-shrinkwrap.json +32 -0
- package/components/jsx/follow-plus-instant-alerts/index.js +1 -1
- package/components/jsx/preferences-modal/index.js +49 -10
- package/components/jsx/preferences-modal/main.scss +1 -0
- package/components/jsx/preferences-modal/preferences-modal.jsx +3 -2
- package/dist/csrf-token/input.js +40 -0
- package/dist/follow-plus-instant-alerts/follow-plus-instant-alerts.js +115 -0
- package/dist/preferences-modal/preferences-modal.js +84 -0
- package/package.json +2 -1
- package/secrets.js +2 -1
@@ -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
|
-
|
107
|
-
|
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
|
151
|
+
const instantAlertsCheckbox = event.target;
|
128
152
|
|
129
|
-
|
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 (
|
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
|
-
|
179
|
+
instantAlertsCheckbox.checked = instantAlertsCheckbox.checked
|
150
180
|
? false
|
151
181
|
: true;
|
152
182
|
}
|
153
183
|
|
154
|
-
|
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 (!
|
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
|
);
|
@@ -0,0 +1,40 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
exports.default = CsrfToken;
|
7
|
+
|
8
|
+
var _react = require('react');
|
9
|
+
|
10
|
+
var _react2 = _interopRequireDefault(_react);
|
11
|
+
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @typedef {object} CsrfInputProperties
|
16
|
+
* @property {string} [csrfToken]
|
17
|
+
* A token to mitigate Cross Site Request Forgery
|
18
|
+
* @property {boolean} [cacheablePersonalisedUrl]
|
19
|
+
* An indicator to decide whether its safe to set the button state on the server side. eg. there is no cache or the cache is personalised
|
20
|
+
*/
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Create a follow plus instant alerts button component
|
24
|
+
* @public
|
25
|
+
* @param {CsrfInputProperties}
|
26
|
+
* @returns {React.ReactElement}
|
27
|
+
*/
|
28
|
+
|
29
|
+
function CsrfToken(_ref) {
|
30
|
+
var csrfToken = _ref.csrfToken,
|
31
|
+
cacheablePersonalisedUrl = _ref.cacheablePersonalisedUrl;
|
32
|
+
|
33
|
+
|
34
|
+
var token = cacheablePersonalisedUrl ? csrfToken : '';
|
35
|
+
return _react2.default.createElement('input', {
|
36
|
+
'data-myft-csrf-token': true,
|
37
|
+
value: token,
|
38
|
+
type: 'hidden',
|
39
|
+
name: 'token' });
|
40
|
+
}
|
@@ -0,0 +1,115 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
|
7
|
+
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
8
|
+
|
9
|
+
exports.default = FollowPlusInstantAlerts;
|
10
|
+
|
11
|
+
var _react = require('react');
|
12
|
+
|
13
|
+
var _react2 = _interopRequireDefault(_react);
|
14
|
+
|
15
|
+
var _input = require('../csrf-token/input');
|
16
|
+
|
17
|
+
var _input2 = _interopRequireDefault(_input);
|
18
|
+
|
19
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
20
|
+
|
21
|
+
/**
|
22
|
+
* @typedef {object} FollowProperties
|
23
|
+
* @property {string} conceptId
|
24
|
+
* The ID for the concept
|
25
|
+
* @property {string} name
|
26
|
+
* The user facing label for the concept
|
27
|
+
* @property {string} [csrfToken]
|
28
|
+
* A token to mitigate Cross Site Request Forgery
|
29
|
+
* @property {boolean} [setFollowButtonStateToSelected]
|
30
|
+
* An indicator to state whether the button state should be set to selected on the server side
|
31
|
+
* @property {boolean} [cacheablePersonalisedUrl]
|
32
|
+
* An indicator to decide whether its safe to set the button state on the server side. eg. there is no cache or the cache is personalised
|
33
|
+
* @property {boolean} [setInstantAlertsOn]
|
34
|
+
* An indicator to switch the rendering to show instant alerts as turned on
|
35
|
+
* @property {object.<string, boolean>} flags
|
36
|
+
* FT.com feature flags
|
37
|
+
* @property {string} variant
|
38
|
+
* color variant of the follow button
|
39
|
+
*/
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Create a follow plus instant alerts button component
|
43
|
+
* @public
|
44
|
+
* @param {FollowProperties}
|
45
|
+
* @returns {React.ReactElement}
|
46
|
+
*/
|
47
|
+
|
48
|
+
function FollowPlusInstantAlerts(_ref) {
|
49
|
+
var conceptId = _ref.conceptId,
|
50
|
+
name = _ref.name,
|
51
|
+
csrfToken = _ref.csrfToken,
|
52
|
+
setFollowButtonStateToSelected = _ref.setFollowButtonStateToSelected,
|
53
|
+
cacheablePersonalisedUrl = _ref.cacheablePersonalisedUrl,
|
54
|
+
setInstantAlertsOn = _ref.setInstantAlertsOn,
|
55
|
+
flags = _ref.flags,
|
56
|
+
variant = _ref.variant;
|
57
|
+
|
58
|
+
if (!flags.myFtApiWrite) {
|
59
|
+
return null;
|
60
|
+
}
|
61
|
+
|
62
|
+
var dynamicFormAttributes = setFollowButtonStateToSelected && cacheablePersonalisedUrl ? {
|
63
|
+
'action': '/myft/remove/' + conceptId,
|
64
|
+
'data-js-action': '/__myft/api/core/followed/concept/' + conceptId + '?method=delete'
|
65
|
+
} : {
|
66
|
+
'action': '/myft/add/' + conceptId,
|
67
|
+
'data-js-action': '/__myft/api/core/followed/concept/' + conceptId + '?method=put'
|
68
|
+
};
|
69
|
+
|
70
|
+
var dynamicButtonAttributes = setFollowButtonStateToSelected && cacheablePersonalisedUrl ? {
|
71
|
+
'aria-label': 'Added ' + name + ' to myFT: click to manage alert preferences or remove from myFT',
|
72
|
+
'title': 'Manage ' + name + ' alert preferences or remove from myFT',
|
73
|
+
'data-alternate-label': 'Add to myFT: ' + name,
|
74
|
+
'aria-pressed': true,
|
75
|
+
'data-alternate-text': 'Add to myFT'
|
76
|
+
} : {
|
77
|
+
'aria-label': 'Add ' + name + ' to myFT',
|
78
|
+
'title': 'Add ' + name + ' to myFT',
|
79
|
+
'data-alternate-label': 'Added ' + name + ' to myFT: click to manage alert preferences or remove from myFT',
|
80
|
+
'aria-pressed': false,
|
81
|
+
'data-alternate-text': 'Added'
|
82
|
+
};
|
83
|
+
|
84
|
+
var buttonText = setFollowButtonStateToSelected && cacheablePersonalisedUrl ? 'Added' : 'Add to myFT';
|
85
|
+
|
86
|
+
return _react2.default.createElement(
|
87
|
+
'form',
|
88
|
+
_extends({}, dynamicFormAttributes, {
|
89
|
+
className: 'n-myft-ui n-myft-ui--follow',
|
90
|
+
method: 'GET',
|
91
|
+
'data-myft-ui': 'follow',
|
92
|
+
'data-concept-id': conceptId,
|
93
|
+
'data-myft-ui-variant': 'followPlusInstantAlerts' }),
|
94
|
+
_react2.default.createElement('div', {
|
95
|
+
className: 'n-myft-ui__announcement o-normalise-visually-hidden',
|
96
|
+
'aria-live': 'assertive',
|
97
|
+
'data-pressed-text': 'Now following ' + name + '.',
|
98
|
+
'data-unpressed-text': 'No longer following ' + name + '.'
|
99
|
+
}),
|
100
|
+
_react2.default.createElement(_input2.default, {
|
101
|
+
cacheablePersonalisedUrl: cacheablePersonalisedUrl,
|
102
|
+
csrfToken: csrfToken
|
103
|
+
}),
|
104
|
+
_react2.default.createElement(
|
105
|
+
'button',
|
106
|
+
_extends({}, dynamicButtonAttributes, {
|
107
|
+
className: 'n-myft-follow-button n-myft-follow-button--instant-alerts\n\t\t\t\t\t\t' + (setInstantAlertsOn ? 'n-myft-follow-button--instant-alerts--on' : '') + '\n\t\t\t\t\t\t' + (variant ? 'n-myft-follow-button--' + variant : ''),
|
108
|
+
'data-concept-id': conceptId,
|
109
|
+
'data-trackable': 'follow',
|
110
|
+
type: 'submit',
|
111
|
+
'data-component-id': 'myft-follow-plus-instant-alerts' }),
|
112
|
+
buttonText
|
113
|
+
)
|
114
|
+
);
|
115
|
+
};
|
@@ -0,0 +1,84 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
exports.default = InstantAlertsPreferencesModal;
|
7
|
+
|
8
|
+
var _react = require('react');
|
9
|
+
|
10
|
+
var _react2 = _interopRequireDefault(_react);
|
11
|
+
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @typedef {Object} PreferencesProperties
|
16
|
+
* @property {string} conceptId
|
17
|
+
* Concept id of the concept which the modal controls
|
18
|
+
* @property {Record<string, boolean>} flags
|
19
|
+
* FT.com feature flags
|
20
|
+
* @property {boolean} visible
|
21
|
+
* Controls the visibility of the modal
|
22
|
+
*/
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Create a popup modal to manage myFT alert preferences
|
26
|
+
* @public
|
27
|
+
* @param {PreferencesProperties}
|
28
|
+
* @returns {React.ReactElement}
|
29
|
+
*/
|
30
|
+
function InstantAlertsPreferencesModal(_ref) {
|
31
|
+
var flags = _ref.flags,
|
32
|
+
conceptId = _ref.conceptId,
|
33
|
+
visible = _ref.visible;
|
34
|
+
|
35
|
+
if (!flags.myFtApiWrite) {
|
36
|
+
return null;
|
37
|
+
}
|
38
|
+
|
39
|
+
return _react2.default.createElement(
|
40
|
+
'div',
|
41
|
+
{
|
42
|
+
className: 'n-myft-ui__preferences-modal ' + (visible ? 'n-myft-ui__preferences-modal--show' : ''),
|
43
|
+
'data-component-id': 'myft-preferences-modal',
|
44
|
+
'data-concept-id': conceptId,
|
45
|
+
'data-o-tracking-view': 'true'
|
46
|
+
},
|
47
|
+
_react2.default.createElement(
|
48
|
+
'div',
|
49
|
+
{ className: 'n-myft-ui__preferences-modal__content' },
|
50
|
+
_react2.default.createElement(
|
51
|
+
'span',
|
52
|
+
{ className: 'o-forms-input o-forms-input--checkbox' },
|
53
|
+
_react2.default.createElement(
|
54
|
+
'label',
|
55
|
+
{ htmlFor: 'receive-instant-alerts' },
|
56
|
+
_react2.default.createElement('input', {
|
57
|
+
id: 'receive-instant-alerts',
|
58
|
+
type: 'checkbox',
|
59
|
+
name: 'receive-instant-alerts',
|
60
|
+
value: 'receive-instant-alerts',
|
61
|
+
'data-component-id': 'myft-preferences-modal-checkbox'
|
62
|
+
}),
|
63
|
+
_react2.default.createElement(
|
64
|
+
'span',
|
65
|
+
{ className: 'o-forms-input__label n-myft-ui__preferences-modal__checkbox__message' },
|
66
|
+
'Get instant alerts for this topic'
|
67
|
+
)
|
68
|
+
)
|
69
|
+
),
|
70
|
+
_react2.default.createElement('p', { 'data-component-id': 'myft-preferences-modal-list', className: 'n-myft-ui__preferences-modal__text' }),
|
71
|
+
_react2.default.createElement(
|
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'
|
75
|
+
),
|
76
|
+
_react2.default.createElement('span', { className: 'n-myft-ui__preferences-modal-error', 'data-component-id': 'myft-preference-modal-error' }),
|
77
|
+
_react2.default.createElement(
|
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' },
|
80
|
+
'Remove from myFT'
|
81
|
+
)
|
82
|
+
)
|
83
|
+
);
|
84
|
+
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@financial-times/n-myft-ui",
|
3
|
-
"version": "30.4.
|
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
|
};
|