@financial-times/n-myft-ui 25.0.1 → 27.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,9 +10,17 @@
10
10
  {{#concepts}}
11
11
  <li class="collection__concept">
12
12
  {{#if ../liteStyle}}
13
- {{{renderReactComponent localPath="components/follow-button/follow-button" variant="primary" buttonText=name flags=@root.flags collectionName=../collectionName}}}
13
+ {{> n-myft-ui/components/follow-button/follow-button
14
+ variant="primary"
15
+ buttonText=name
16
+ collectionName=../collectionName
17
+ }}
14
18
  {{else}}
15
- {{{renderReactComponent localPath="components/follow-button/follow-button" variant="inverse" buttonText=name flags=@root.flags collectionName=../collectionName}}}
19
+ {{> n-myft-ui/components/follow-button/follow-button
20
+ variant="inverse"
21
+ buttonText=name
22
+ collectionName=../collectionName
23
+ }}
16
24
  {{/if}}
17
25
  </li>
18
26
  {{/concepts}}
@@ -42,7 +50,7 @@
42
50
  {{~/unless~}}
43
51
  {{~/concepts~}}"
44
52
  />
45
- {{{renderReactComponent localPath="components/csrf-token/input"}}}
53
+ {{> n-myft-ui/components/csrf-token/input}}
46
54
  <input
47
55
  type="hidden"
48
56
  name="name"
@@ -20,7 +20,10 @@
20
20
  class="concept-list__concept">
21
21
  {{prefLabel}}
22
22
  </a>
23
- {{{renderReactComponent localPath="components/follow-button/follow-button" conceptId=id name=prefLabel flags=@root.flags}}}
23
+ {{> n-myft-ui/components/follow-button/follow-button
24
+ conceptId=id
25
+ name=prefLabel
26
+ }}
24
27
  </li>
25
28
  {{/each}}
26
29
  </ul>
@@ -0,0 +1,5 @@
1
+ <input
2
+ data-myft-csrf-token
3
+ value="{{#if @root.cacheablePersonalisedUrl}}{{@root.csrfToken}}{{/if}}"
4
+ type="hidden"
5
+ name="token">
@@ -0,0 +1,79 @@
1
+ {{#if @root.flags.myFtApiWrite}}
2
+ <form
3
+ class="n-myft-ui n-myft-ui--follow {{extraClasses}}"
4
+ method="GET"
5
+ data-myft-ui="follow"
6
+ data-concept-id="{{conceptId}}"
7
+ {{#if collectionName}}data-myft-tracking="collectionName={{collectionName}}"{{/if}}
8
+ {{#if followPlusDigestEmail}}
9
+ action="/__myft/api/core/follow-plus-digest-email/{{conceptId}}?method=put"
10
+ data-myft-ui-variant="followPlusDigestEmail"
11
+ {{else}}
12
+ {{#ifAll setFollowButtonStateToSelected @root.cacheablePersonalisedUrl}}
13
+ action="/myft/remove/{{conceptId}}"
14
+ data-js-action="/__myft/api/core/followed/concept/{{conceptId}}?method=delete"
15
+ {{else}}
16
+ action="/myft/add/{{conceptId}}"
17
+ data-js-action="/__myft/api/core/followed/concept/{{conceptId}}?method=put"
18
+ {{/ifAll}}
19
+ {{/if}}>
20
+ {{> n-myft-ui/components/csrf-token/input}}
21
+ <div
22
+ class="n-myft-ui__announcement o-normalise-visually-hidden"
23
+ aria-live="assertive"
24
+ data-pressed-text="Now following {{name}}."
25
+ data-unpressed-text="No longer following {{name}}."
26
+ ></div>
27
+ <button
28
+ {{#ifAll setFollowButtonStateToSelected @root.cacheablePersonalisedUrl}}
29
+ aria-label="Remove {{name}} from myFT"
30
+ title="Remove {{name}} from myFT"
31
+ data-alternate-label="Add {{name}} to myFT"
32
+ aria-pressed="true"
33
+ {{#if alternateText}}
34
+ data-alternate-text="{{alternateText}}"
35
+ {{else}}
36
+ {{#if buttonText}}
37
+ data-alternate-text="{{buttonText}}"
38
+ {{else}}
39
+ data-alternate-text="Add to myFT"
40
+ {{/if}}
41
+ {{/if}}
42
+ {{else}}
43
+ aria-pressed="false"
44
+ aria-label="Add {{name}} to myFT"
45
+ title="Add {{name}} to myFT"
46
+ data-alternate-label="Remove {{name}} from myFT"
47
+ {{#if alternateText}}
48
+ data-alternate-text="{{alternateText}}"
49
+ {{else}}
50
+ {{#if buttonText}}
51
+ data-alternate-text="{{buttonText}}"
52
+ {{else}}
53
+ data-alternate-text="Added"
54
+ {{/if}}
55
+ {{/if}}
56
+ {{/ifAll}}
57
+ class="{{extraButtonClasses}}
58
+ n-myft-follow-button
59
+ {{~#variant}} n-myft-follow-button--{{this}}{{/variant~}}"
60
+ data-concept-id="{{conceptId}}" {{! duplicated here for tracking}}
61
+ {{#if followPlusDigestEmail}}
62
+ data-trackable-context-messaging="add-to-myft-plus-digest-button"
63
+ {{/if}}
64
+ data-trackable="follow"
65
+ type="submit">
66
+ {{~#if buttonText~}}
67
+ {{buttonText}}
68
+ {{~else~}}
69
+ {{~#ifAll setFollowButtonStateToSelected @root.cacheablePersonalisedUrl~}}
70
+ Added
71
+ {{~else~}}
72
+ Add to myFT
73
+ {{~/ifAll~}}
74
+ {{~/if~}}
75
+ </button>
76
+ </form>
77
+ {{else}}
78
+ <!-- Add to myFT button hidden due to myFtApiWrite being off -->
79
+ {{/if}}
@@ -5,7 +5,7 @@
5
5
  data-concept-id="{{conceptId}}"
6
6
  action="/myft/add/{{conceptId}}?instant=true"
7
7
  data-js-action="/__myft/api/core/followed/concept/{{conceptId}}?method=put">
8
- {{{renderReactComponent localPath="components/csrf-token/input"}}}
8
+ {{> n-myft-ui/components/csrf-token/input}}
9
9
  <input type="hidden" value="{{name}}" name="name">
10
10
  {{#if directType}}
11
11
  <input type="hidden" value="{{directType}}" name="directType">
@@ -2,7 +2,7 @@
2
2
  <span class="myft-pin-divider"></span>
3
3
  <div class="myft-pin-button-wrapper">
4
4
  <form method="post" action="/__myft/api/core/prioritised/concept/{{id}}?method={{#if prioritised}}delete{{else}}put{{/if}}" data-myft-prioritise>
5
- {{{renderReactComponent localPath="components/csrf-token/input"}}}
5
+ {{> n-myft-ui/components/csrf-token/input }}
6
6
  <input type="hidden" value="{{name}}" name="name"> {{#if directType}}
7
7
  <input type="hidden" value="{{directType}}" name="directType"> {{else}}
8
8
  <input type="hidden" value="http://www.ft.com/ontology/concept/Concept" name="directType"> {{/if}}
@@ -4,7 +4,7 @@
4
4
  data-myft-ui="saved"
5
5
  action="/myft/save/{{contentId}}"
6
6
  data-js-action="/__myft/api/core/saved/content/{{contentId}}?method=put">
7
- {{{renderReactComponent localPath="components/csrf-token/input"}}}
7
+ {{> n-myft-ui/components/csrf-token/input}}
8
8
  <div
9
9
  class="n-myft-ui__announcement o-normalise-visually-hidden"
10
10
  aria-live="assertive"
@@ -2,12 +2,12 @@
2
2
  // the detail => https://github.com/date-fns/date-fns/blob/HEAD/CHANGELOG.md#200---2019-08-20
3
3
  // By adding validation for dates before their functions allows us to know it when unexpected value passed.
4
4
 
5
- import isTodayOriginal from 'date-fns/src/isToday';
6
- import isAfterOriginal from 'date-fns/src/isAfter';
7
- import addMinutesOriginal from 'date-fns/src/addMinutes';
8
- import startOfDayOriginal from 'date-fns/src/startOfDay';
9
- import isValidOriginal from 'date-fns/src/isValid';
10
- import parseISO from 'date-fns/src/parseISO';
5
+ import isTodayOriginal from "date-fns/src/isToday";
6
+ import isAfterOriginal from "date-fns/src/isAfter";
7
+ import addMinutesOriginal from "date-fns/src/addMinutes";
8
+ import startOfDayOriginal from "date-fns/src/startOfDay";
9
+ import isValidOriginal from "date-fns/src/isValid";
10
+ import parseISO from "date-fns/src/parseISO";
11
11
 
12
12
  const isValid = (date) => {
13
13
  if (!isValidOriginal(date)) {
package/demos/app.js CHANGED
@@ -1,17 +1,11 @@
1
- require('sucrase/register');
2
1
  const nExpress = require('@financial-times/n-express');
3
2
  const chalk = require('chalk');
4
3
  const errorHighlight = chalk.bold.red;
5
4
  const highlight = chalk.bold.green;
6
- const { PageKitReactJSX } = require('@financial-times/dotcom-server-react-jsx');
7
- const fs = require('fs');
8
5
  const path = require('path');
9
6
  const handlebars = require('handlebars');
10
7
  const { PageKitHandlebars, helpers } = require('@financial-times/dotcom-server-handlebars');
11
8
 
12
- const demoJSX = require('./templates/demo').default;
13
- const demoLayoutSource = fs.readFileSync(path.join(__dirname, './templates/demo-layout.html'),'utf8').toString();
14
-
15
9
  const fixtures = {
16
10
  followButton: require('./fixtures/follow-button'),
17
11
  saveButton: require('./fixtures/save-button'),
@@ -37,7 +31,6 @@ const app = module.exports = nExpress({
37
31
 
38
32
  app.set('views', path.join(__dirname, '/templates'));
39
33
  app.set('view engine', '.html');
40
-
41
34
  app.engine('.html', new PageKitHandlebars({
42
35
  cache: false,
43
36
  handlebars,
@@ -48,8 +41,6 @@ app.engine('.html', new PageKitHandlebars({
48
41
 
49
42
  app.use('/public', nExpress.static(path.join(__dirname, '../public'), { redirect: false }));
50
43
 
51
- const jsxRenderer = (new PageKitReactJSX({ includeDoctype: false }));
52
-
53
44
  app.get('/', (req, res) => {
54
45
  res.render('demo', Object.assign({
55
46
  title: 'n-myft-ui demo',
@@ -60,22 +51,6 @@ app.get('/', (req, res) => {
60
51
  }, fixtures));
61
52
  });
62
53
 
63
- app.get('/demo-jsx', async (req, res) => {
64
- let demo = await jsxRenderer.render(demoJSX, Object.assign({
65
- title: 'n-myft-ui demo',
66
- flags: {
67
- myFtApi: true,
68
- myFtApiWrite: true
69
- }
70
- }, fixtures));
71
-
72
- let template = handlebars.compile(demoLayoutSource);
73
- let result = template({body: demo});
74
-
75
- res.send(result);
76
- });
77
-
78
-
79
54
  function runPa11yTests () {
80
55
  const spawn = require('child_process').spawn;
81
56
  const pa11y = spawn('pa11y-ci');
@@ -32,7 +32,7 @@
32
32
  </h2>
33
33
 
34
34
  {{#followButton}}
35
- {{{renderReactComponent localPath="components/follow-button/follow-button" flags=@root.flags}}}
35
+ {{> n-myft-ui/components/follow-button/follow-button}}
36
36
  {{/followButton}}
37
37
 
38
38
  <h2
@@ -41,7 +41,7 @@
41
41
  </h2>
42
42
 
43
43
  {{#followButton}}
44
- {{{renderReactComponent localPath="components/follow-button/follow-button" buttonText=name flags=@root.flags}}}
44
+ {{> n-myft-ui/components/follow-button/follow-button buttonText=name}}
45
45
  {{/followButton}}
46
46
 
47
47
  {{#saveButton}}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@financial-times/n-myft-ui",
3
- "version": "25.0.1",
3
+ "version": "27.1.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
9
  "prepare": "npx snyk protect || npx snyk protect -d || true",
10
- "preinstall": "[ \"$INIT_CWD\" != \"$PWD\" ] || npm_config_yes=true npx check-engine"
10
+ "preinstall": "npm_config_yes=true npx check-engine"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",
@@ -20,18 +20,14 @@
20
20
  },
21
21
  "homepage": "https://github.com/Financial-Times/n-myft-ui#readme",
22
22
  "devDependencies": {
23
- "@financial-times/dotcom-build-bower-resolve": "0.4.1",
24
- "@financial-times/dotcom-build-code-splitting": "0.4.1",
25
- "@financial-times/dotcom-build-js": "0.4.1",
26
- "@financial-times/dotcom-build-sass": "0.4.1",
27
- "@financial-times/dotcom-page-kit-cli": "0.4.1",
28
- "@financial-times/dotcom-server-handlebars": "^3.0.0",
29
- "@financial-times/dotcom-server-react-jsx": "^2.6.2",
30
- "@financial-times/n-express": "^22.4.1",
23
+ "@financial-times/dotcom-build-bower-resolve": "^2.6.2",
24
+ "@financial-times/dotcom-build-code-splitting": "^5.0.0",
25
+ "@financial-times/dotcom-build-js": "^5.0.0",
26
+ "@financial-times/dotcom-build-sass": "^5.0.0",
27
+ "@financial-times/dotcom-page-kit-cli": "^0.6.5",
28
+ "@financial-times/dotcom-server-handlebars": "^5.0.0",
29
+ "@financial-times/n-express": "^23.0.1",
31
30
  "@financial-times/n-gage": "^8.3.2",
32
- "@sucrase/jest-plugin": "^2.2.0",
33
- "@testing-library/jest-dom": "^5.16.1",
34
- "@testing-library/react": "^12.1.2",
35
31
  "ascii-table": "0.0.9",
36
32
  "autoprefixer": "9.7.0",
37
33
  "aws-sdk-mock": "4.5.0",
@@ -55,18 +51,14 @@
55
51
  "css-loader": "^0.23.1",
56
52
  "denodeify": "^1.2.1",
57
53
  "eslint": "6.5.1",
58
- "eslint-plugin-react": "^7.27.1",
59
54
  "extract-css-block-webpack-plugin": "^1.3.0",
60
- "extract-text-webpack-plugin": "3.0.2",
61
55
  "fetch-mock": "^5.0.3",
62
56
  "handlebars": "^4.0.6",
63
57
  "handlebars-loader": "^1.4.0",
64
58
  "http-server": "^0.11.1",
65
59
  "hyperons": "^0.4.1",
66
60
  "imports-loader": "0.8.0",
67
- "inject-loader": "^3.0.0",
68
- "jest": "^27.4.5",
69
- "jsdom": "^19.0.0",
61
+ "inject-loader": "^4.0.1",
70
62
  "karma": "4.4.1",
71
63
  "karma-browserstack-launcher": "1.5.1",
72
64
  "karma-chai": "^0.1.0",
@@ -77,31 +69,29 @@
77
69
  "karma-sinon": "^1.0.5",
78
70
  "karma-sinon-chai": "2.0.2",
79
71
  "karma-sourcemap-loader": "^0.3.7",
80
- "karma-webpack": "^3.0.0",
72
+ "karma-webpack": "^4.0.2",
81
73
  "lintspaces-cli": "^0.7.0",
82
74
  "lolex": "5.1.1",
83
75
  "mocha": "6.2.2",
84
76
  "mockery": "2.1.0",
85
77
  "node-fetch": "2.6.0",
86
- "node-sass": "^4.14.1",
78
+ "node-sass": "^6.0.1",
87
79
  "nodemon": "^1.9.2",
88
80
  "npm-prepublish": "^1.2.1",
89
81
  "pa11y-ci": "^2.1.1",
90
82
  "postcss-loader": "^0.9.1",
91
- "react": "^17.0.2",
92
83
  "regenerator-runtime": "^0.13.3",
93
84
  "semver": "6.3.0",
94
85
  "sinon": "^7.1.0",
95
86
  "sinon-chai": "^3.2.0",
96
- "snyk": "^1.216.5",
97
- "sucrase": "^3.10.1"
87
+ "snyk": "^1.216.5"
98
88
  },
99
89
  "volta": {
100
- "node": "12.22.5",
90
+ "node": "16.14.2",
101
91
  "npm": "7.20.2"
102
92
  },
103
93
  "engines": {
104
- "node": "12.x",
94
+ "node": "14.x || 16.x",
105
95
  "npm": "7.x || 8.x"
106
96
  },
107
97
  "x-dash": {
@@ -1,23 +0,0 @@
1
- import React from 'react';
2
- import CsrfToken from '../input';
3
- import { render } from '@testing-library/react';
4
- import '@testing-library/jest-dom';
5
-
6
- const props = {
7
- cacheablePersonalisedUrl: false
8
- };
9
-
10
- describe('Csrf Token Input', () => {
11
-
12
- test('It renders default button', async () => {
13
- let { container } = render(<CsrfToken {...props} />);
14
- expect(container.querySelector('[name=\'token\']')).toBeTruthy();
15
- });
16
-
17
- test('It renders csrf token attribute', async () => {
18
- let { container } = render(<CsrfToken cacheablePersonalisedUrl={true} csrfToken={'test-token'} />);
19
- expect(container.querySelector('[data-myft-csrf-token=\'test-token\']')).toBeTruthy();
20
- });
21
-
22
-
23
- });
@@ -1,26 +0,0 @@
1
- import React from 'react';
2
-
3
- export default function CsrfToken ({ cacheablePersonalisedUrl, csrfToken }) {
4
-
5
- let inputProps = {};
6
-
7
- if (cacheablePersonalisedUrl) {
8
- inputProps = {
9
- ...inputProps,
10
- 'data-myft-csrf-token': csrfToken
11
- };
12
- }
13
-
14
- if(csrfToken) {
15
- inputProps.value = csrfToken;
16
- }
17
-
18
- return (
19
- <input
20
- {...inputProps}
21
- type="hidden"
22
- name="token"
23
- />
24
- );
25
-
26
- }
@@ -1,40 +0,0 @@
1
- import React from 'react';
2
- import FollowButton from '../follow-button';
3
- import { render, screen } from '@testing-library/react';
4
- import '@testing-library/jest-dom';
5
-
6
- const props = {
7
- flags: {
8
- myFtApi: true,
9
- myFtApiWrite: true
10
- },
11
- conceptId: '0000-000000-00000-0000',
12
- name: 'Follow button'
13
- };
14
-
15
- describe('Follow button', () => {
16
-
17
- test('It renders default button', async () => {
18
- render(<FollowButton {...props} />);
19
- expect(screen.findByText('Add to myFT')).toBeTruthy();
20
- });
21
-
22
- test('It renders a variant', async () => {
23
- const { container } = render(<FollowButton {...props} variant={'standard'} />);
24
- expect(container.getElementsByClassName('n-myft-follow-button--standard')).toHaveLength(1);
25
- });
26
-
27
- test('It renders follow button form', async () => {
28
- const { container } = render(<FollowButton {...props} variant={'standard'} />);
29
- expect(container.querySelector(`form[action='/myft/add/${props.conceptId}']`)).toBeTruthy();
30
- });
31
-
32
- test('Button state changes when attributes change', () => {
33
- render(<FollowButton {...props}
34
- variant={'standard'}
35
- setFollowButtonStateToSelected={true}
36
- cacheablePersonalisedUrl={true} />);
37
- expect(screen.findByText('Added')).toBeTruthy();
38
- });
39
-
40
- });
@@ -1,174 +0,0 @@
1
- import React from 'react';
2
- import CsrfToken from '../csrf-token/input';
3
-
4
- function generateFormProps (props) {
5
- let generatedProps = {};
6
-
7
- const {
8
- collectionName,
9
- followPlusDigestEmail,
10
- conceptId,
11
- setFollowButtonStateToSelected,
12
- cacheablePersonalisedUrl
13
- } = props;
14
-
15
- if (collectionName) {
16
- generatedProps['data-myft-tracking'] = `collectionName=${collectionName}`;
17
- }
18
-
19
- if(followPlusDigestEmail) {
20
- generatedProps['action'] = `/__myft/api/core/follow-plus-digest-email/${conceptId}?method=put`;
21
- generatedProps['data-myft-ui-variant'] = 'followPlusDigestEmail';
22
- } else {
23
- if(setFollowButtonStateToSelected && cacheablePersonalisedUrl) {
24
- generatedProps['action'] = `/myft/remove/${conceptId}`;
25
- generatedProps['data-js-action'] = `/__myft/api/core/followed/concept/${conceptId}?method=delete`;
26
- } else {
27
- generatedProps['action'] = `/myft/add/${conceptId}`;
28
- generatedProps['data-js-action'] = `/__myft/api/core/followed/concept/${conceptId}?method=put`;
29
- }
30
- }
31
-
32
- return generatedProps;
33
-
34
- }
35
-
36
- function generateButtonProps (props) {
37
-
38
- const {
39
- cacheablePersonalisedUrl,
40
- setFollowButtonStateToSelected,
41
- name,
42
- buttonText,
43
- variant,
44
- conceptId,
45
- alternateText,
46
- followPlusDigestEmail
47
- } = props;
48
-
49
- let generatedProps = {
50
- 'data-concept-id': conceptId,
51
- 'n-myft-follow-button': 'true',
52
- 'data-trackable': 'follow',
53
- type: 'submit'
54
- };
55
-
56
- if (cacheablePersonalisedUrl && setFollowButtonStateToSelected) {
57
- generatedProps['aria-label'] = `Remove ${name} from myFT`;
58
- generatedProps['title'] = `Remove ${name} from myFT`
59
- generatedProps['data-alternate-label'] = `Add ${name} to myFT`;
60
- generatedProps['aria-pressed'] = true;
61
-
62
- if(alternateText) {
63
- generatedProps['data-alternate-text'] = alternateText;
64
- } else {
65
- if(buttonText) {
66
- generatedProps['data-alternate-text'] = buttonText;
67
- } else {
68
- generatedProps['data-alternate-text'] = 'Add to myFT';
69
- }
70
- }
71
- } else {
72
- generatedProps['aria-pressed'] = false;
73
- generatedProps['aria-label'] = `Add ${name} to myFT`;
74
- generatedProps['title'] = `Add ${name} to myFT`;
75
- generatedProps['data-alternate-label'] = `Remove ${name} from myFT`;
76
- if (alternateText) {
77
- generatedProps['data-alternate-text'] = alternateText;
78
- } else {
79
- if (buttonText) {
80
- generatedProps['data-alternate-text'] = buttonText;
81
- } else {
82
- generatedProps['data-alternate-text'] = 'Added';
83
- }
84
- }
85
- }
86
-
87
- if(variant) {
88
- generatedProps[`n-myft-follow-button--${variant}`] = 'true';
89
- }
90
-
91
- if(followPlusDigestEmail) {
92
- generatedProps['data-trackable-context-messaging'] = 'add-to-myft-plus-digest-button';
93
- }
94
-
95
- return generatedProps;
96
- }
97
-
98
- function getButtonText (props) {
99
-
100
- const {
101
- buttonText,
102
- setFollowButtonStateToSelected,
103
- cacheablePersonalisedUrl
104
- } = props;
105
- let outputText;
106
-
107
- if(buttonText) {
108
- outputText = buttonText;
109
- } else {
110
- if(setFollowButtonStateToSelected && cacheablePersonalisedUrl) {
111
- outputText = 'Added';
112
- } else {
113
- outputText = 'Add to myFT';
114
- }
115
- }
116
-
117
- return outputText;
118
- }
119
-
120
- /**
121
- *
122
- * @param {Object} props
123
- * @param {string} props.name
124
- * @param {Object} props.flags
125
- * @param {string} props.extraClasses
126
- * @param {string} props.conceptId
127
- * @param {string} props.variant
128
- * @param {string} props.buttonText
129
- * @param {*} props.setFollowButtonStateToSelected
130
- * @param {string} props.cacheablePersonalisedUrl
131
- * @param {string} props.alternateText
132
- * @param {*} props.followPlusDigestEmail
133
- * @param {string} props.collectionName
134
- */
135
- export default function FollowButton (props) {
136
-
137
- const {
138
- name,
139
- flags,
140
- extraClasses,
141
- conceptId,
142
- variant,
143
- } = props;
144
-
145
- const formProps = generateFormProps(props);
146
- const buttonProps = generateButtonProps(props);
147
-
148
- const getVariantClass = (variant) => variant ? `n-myft-follow-button--${variant}` : '';
149
-
150
- return (
151
- <>
152
- {flags.myFtApiWrite && <form
153
- className={`n-myft-ui n-myft-ui--follow ${extraClasses || ''}`}
154
- method="GET"
155
- data-myft-ui="follow"
156
- data-concept-id={conceptId}
157
- {...formProps}>
158
- <CsrfToken cacheablePersonalisedUrl={props.cacheablePersonalisedUrl} csrfToken={props.csrfToken} />
159
- <div
160
- className="n-myft-ui__announcement o-normalise-visually-hidden"
161
- aria-live="assertive"
162
- data-pressed-text={`Now following ${name}.`}
163
- data-unpressed-text={`No longer following ${name}.`}
164
- ></div>
165
- <button
166
- {...buttonProps}
167
- className={[`n-myft-follow-button ${getVariantClass(variant)}`]}>
168
- {getButtonText(props)}
169
- </button>
170
- </form>}
171
- </>
172
- );
173
-
174
- }
@@ -1,25 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <head>
5
- <meta charset="utf-8">
6
- <title>{{title}}</title>
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
- <link rel="stylesheet" href="/public/main.css">
9
- </head>
10
-
11
- <body>
12
-
13
- <div class="o-grid-container o-grid-container--snappy">
14
- <div class="o-grid-row">
15
- <ul>
16
- <li><a href="/">Basic</a></li>
17
- <li><a href="/demo-jsx">JSX demo</a></li>
18
- </ul>
19
- </div>
20
- </div>
21
-
22
- {{{body}}}
23
- </body>
24
-
25
- </html>