@financial-times/n-myft-ui 30.4.0 → 30.4.3
Sign up to get free protection for your applications and to get access to all the features.
- package/.babelrc +9 -0
- package/.circleci/config.yml +3 -0
- package/.eslintignore +1 -0
- package/Makefile +3 -0
- package/build-state/npm-shrinkwrap.json +16686 -8227
- package/components/jsx/preferences-modal/main.scss +1 -0
- 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 +83 -0
- package/package.json +3 -1
@@ -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
|
+
};
|
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.3",
|
4
4
|
"description": "Client side component for interaction with myft",
|
5
5
|
"main": "server.js",
|
6
6
|
"scripts": {
|
@@ -30,6 +30,7 @@
|
|
30
30
|
"ascii-table": "0.0.9",
|
31
31
|
"autoprefixer": "9.7.0",
|
32
32
|
"aws-sdk-mock": "4.5.0",
|
33
|
+
"babel-cli": "^6.26.0",
|
33
34
|
"babel-core": "^6.2.1",
|
34
35
|
"babel-loader": "7.1.4",
|
35
36
|
"babel-plugin-add-module-exports": "^0.3.0",
|
@@ -39,6 +40,7 @@
|
|
39
40
|
"babel-plugin-transform-runtime": "^6.23.0",
|
40
41
|
"babel-preset-env": "^1.7.0",
|
41
42
|
"babel-preset-es2015": "^6.6.0",
|
43
|
+
"babel-preset-react": "^6.24.1",
|
42
44
|
"babel-runtime": "^6.9.2",
|
43
45
|
"brotli": "^1.3.1",
|
44
46
|
"chai": "4.2.0",
|