@financial-times/n-myft-ui 30.4.2 → 30.4.3
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.
@@ -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,83 @@
|
|
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
|
+
},
|
46
|
+
_react2.default.createElement(
|
47
|
+
'div',
|
48
|
+
{ className: 'n-myft-ui__preferences-modal__content' },
|
49
|
+
_react2.default.createElement(
|
50
|
+
'span',
|
51
|
+
{ className: 'o-forms-input o-forms-input--checkbox' },
|
52
|
+
_react2.default.createElement(
|
53
|
+
'label',
|
54
|
+
{ htmlFor: 'receive-instant-alerts' },
|
55
|
+
_react2.default.createElement('input', {
|
56
|
+
id: 'receive-instant-alerts',
|
57
|
+
type: 'checkbox',
|
58
|
+
name: 'receive-instant-alerts',
|
59
|
+
value: 'receive-instant-alerts',
|
60
|
+
'data-component-id': 'myft-preferences-modal-checkbox'
|
61
|
+
}),
|
62
|
+
_react2.default.createElement(
|
63
|
+
'span',
|
64
|
+
{ className: 'o-forms-input__label n-myft-ui__preferences-modal__checkbox__message' },
|
65
|
+
'Get instant alerts for this topic'
|
66
|
+
)
|
67
|
+
)
|
68
|
+
),
|
69
|
+
_react2.default.createElement('p', { 'data-component-id': 'myft-preferences-modal-list', className: 'n-myft-ui__preferences-modal__text' }),
|
70
|
+
_react2.default.createElement(
|
71
|
+
'a',
|
72
|
+
{ className: 'n-myft-ui__preferences-modal__text', href: '/myft/alerts' },
|
73
|
+
'Manage your preferences here'
|
74
|
+
),
|
75
|
+
_react2.default.createElement('span', { className: 'n-myft-ui__preferences-modal-error', 'data-component-id': 'myft-preference-modal-error' }),
|
76
|
+
_react2.default.createElement(
|
77
|
+
'button',
|
78
|
+
{ className: 'n-myft-ui__preferences-modal__remove-button', 'data-component-id': 'myft-preference-modal-remove' },
|
79
|
+
'Remove from myFT'
|
80
|
+
)
|
81
|
+
)
|
82
|
+
);
|
83
|
+
};
|