@nice-digital/global-nav 7.1.1202 → 7.1.1203-GN-264-load-aws-chal

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.
Files changed (32) hide show
  1. package/README.md +98 -0
  2. package/lib/Footer/Footer.js +9 -2
  3. package/lib/Footer/Pages/Pages.js +3 -1
  4. package/lib/Footer/Services/Services.js +14 -11
  5. package/lib/Header/Account/Account.js +23 -18
  6. package/lib/Header/Account/nice-accounts.js +10 -2
  7. package/lib/Header/Header.js +58 -57
  8. package/lib/Header/Nav/Dropdown/Components/AboutUs.js +31 -29
  9. package/lib/Header/Nav/Dropdown/Components/Grid.js +12 -13
  10. package/lib/Header/Nav/Dropdown/Components/LifeSciences.js +15 -13
  11. package/lib/Header/Nav/Dropdown/Components/MoreFromNICE.js +13 -11
  12. package/lib/Header/Nav/Dropdown/Components/StandardsAndIndicators.js +12 -10
  13. package/lib/Header/Nav/Dropdown/Dropdown.js +19 -15
  14. package/lib/Header/Nav/Nav.js +15 -11
  15. package/lib/Header/Nav/NavLinks/NavLinks.js +37 -33
  16. package/lib/Header/Nav/SubNav/SubNav.js +7 -3
  17. package/lib/Header/Search/Autocomplete/Autocomplete.js +25 -32
  18. package/lib/Header/Search/Autocomplete/suggester/index.js +6 -4
  19. package/lib/Header/Search/Autocomplete/suggester/phrase-finder.js +5 -3
  20. package/lib/Header/Search/Autocomplete/suggester/term-finder.js +5 -3
  21. package/lib/Header/Search/Search.js +10 -11
  22. package/lib/Header/context/HeaderContext.js +5 -10
  23. package/lib/Main/Main.js +16 -15
  24. package/lib/TrackedLink/TrackedLink.js +14 -18
  25. package/lib/aws-waf/index.js +131 -0
  26. package/lib/aws-waf/integrations.js +138 -0
  27. package/lib/aws-waf/propTypes.js +20 -0
  28. package/lib/hooks/useAwsWafChallenge.js +19 -0
  29. package/lib/hooks/useIsClient.js +1 -6
  30. package/lib/renderer.js +17 -11
  31. package/package.json +9 -4
  32. package/types.d.ts +10 -0
package/README.md CHANGED
@@ -313,6 +313,13 @@ For a full list of all the available props, see the [props section](#props) belo
313
313
 
314
314
  Optional spacing between page content and footer back-to-top link.
315
315
 
316
+ ###### Main.awsWafScriptURL
317
+
318
+ - Type: `String | false`
319
+ - Default: `undefined`
320
+
321
+ See [Header.awsWafScriptURL](#headerawswafscripturl).
322
+
316
323
  ##### Header props
317
324
 
318
325
  ###### Header.service
@@ -663,6 +670,27 @@ If the authentication provider has been set to "idam", then an array of links mu
663
670
 
664
671
  The displayName is the user's name and must be provided if the "idam" provider is used and the user is logged in.
665
672
 
673
+ ###### Header.awsWafScriptURL
674
+
675
+ - Type: `String | false`
676
+ - Default: `undefined`
677
+
678
+ Overrides how the [AWS WAF challenge](#aws-waf-challenge) script is loaded. Leave it out and Global Nav loads the script for the page's hostname, if it knows of one.
679
+
680
+ Pass a URL to load that script instead, for example to test against a stand-in locally:
681
+
682
+ ```js
683
+ <Header awsWafScriptURL="https://localhost:4000/mock-aws-waf-jsapi.js" />
684
+ ```
685
+
686
+ Pass `false` to stop Global Nav loading the script at all, for example because your app includes it itself:
687
+
688
+ ```js
689
+ <Header awsWafScriptURL={false} />
690
+ ```
691
+
692
+ The `Header`, `Footer` and `Main` components all take this prop and all behave the same way, because no one of them is on every page of every service. Whichever mounts first does the work. `false` from any of them switches the challenge off for the rest of the page's life, so there's no need to pass it to all three as long as the one you pass it to mounts first - the header, usually.
693
+
666
694
  ##### Footer props
667
695
 
668
696
  ###### Footer.service
@@ -674,6 +702,13 @@ The displayName is the user's name and must be provided if the "idam" provider i
674
702
  The identifier of the currently active service.
675
703
  See [services.json](src/services.json) for a list of the available service identifiers.
676
704
 
705
+ ###### Footer.awsWafScriptURL
706
+
707
+ - Type: `String | false`
708
+ - Default: `undefined`
709
+
710
+ See [Header.awsWafScriptURL](#headerawswafscripturl).
711
+
677
712
  ### CDN
678
713
 
679
714
  Reference the Global Nav bundle directly from the NICE CDN to render the Global Nav. We recommend including this before the closing `</body>` tag but before your application's scripts:
@@ -816,6 +851,69 @@ The footer renders by default, set `footer` to `false` to stop it from rendering
816
851
  Or, pass an object of key/value pairs of settings specific to the footer.
817
852
  See the [footer props](#footer-props) section for available options.
818
853
 
854
+ ##### awsWafScriptURL
855
+
856
+ - Type: `String | Boolean`
857
+ - Default: `undefined`
858
+
859
+ Overrides how the [AWS WAF challenge](#aws-waf-challenge) script is loaded: a URL to load that script instead of the one for the page's hostname, or `false` to not load it at all e.g. `global_nav_config = { awsWafScriptURL: false }`.
860
+
861
+ This sits at the top level of the config, next to `service`, rather than under `header` or `footer`. That's deliberate: it still applies when either of those is set to `false`.
862
+
863
+ ### AWS WAF challenge
864
+
865
+ Global Nav loads the [AWS WAF JavaScript SDK](https://docs.aws.amazon.com/waf/latest/developerguide/waf-js-challenge-api.html) on services that sit behind an AWS WAF web ACL. The SDK silently acquires an `aws-waf-token` cookie in the background. The web ACL checks requests for that token and challenges the ones without it, which is how we tell real browsers from bots.
866
+
867
+ It's the web ACL that keeps the bots out, not this script. The script is there so that real users already hold a token by the time they need one, and never see the challenge interstitial.
868
+
869
+ Global Nav carries this because it's the one piece of code already on every NICE service. The alternative is each service adding the script for itself.
870
+
871
+ #### How it picks the script
872
+
873
+ Each web ACL issues its own script URL, and the ids in that URL are generated by AWS, so it can't be worked out from the hostname. Instead there's a lookup table in [_src/aws-waf/integrations.js_](src/aws-waf/integrations.js), with one entry per web ACL listing the hostnames it protects.
874
+
875
+ When Global Nav loads, it looks up `window.location.hostname` in that table. If there's an entry, it adds the script to the `<head>`. If there isn't, it does nothing, which is what we want for localhost and for any environment with no web ACL in front of it.
876
+
877
+ > The table lists ops' sandbox and our live, alpha, beta, test and dev hostnames already, but a `scriptURL` stays empty until ops create that web ACL. An entry with an empty URL does nothing, so on the other hostnames the script only loads when `awsWafScriptURL` prop is passed.
878
+
879
+ The script is only ever added once per page. Global Nav also does nothing if the SDK is already there, i.e. `window.AwsWafIntegration` exists or the page has its own script tag pointing at `awswaf.com`.
880
+
881
+ Use [`awsWafScriptURL`](#headerawswafscripturl) to override the lookup, or to switch the whole thing off.
882
+
883
+ #### Adding or filling in a web ACL
884
+
885
+ Each entry in [_src/aws-waf/integrations.js_](src/aws-waf/integrations.js) looks like this:
886
+
887
+ ```js
888
+ export const integrations = [
889
+ {
890
+ hosts: ['www.nice.org.uk'],
891
+ scriptURL: 'https://<id>.eu-west-1.sdk.awswaf.com/<id>/<id>/challenge.js',
892
+ cookieDomains: ['.nice.org.uk'],
893
+ },
894
+ ];
895
+ ```
896
+
897
+ - `hosts` are exact hostnames, or a leading wildcard like `*.nice.org.uk`, which matches any subdomain at any depth but not the bare domain. An exact hostname always wins over a wildcard, wherever either one is in the table. Hostnames that share a load balancer (or CloudFront distribution) share a web ACL, so list them all against the one entry. The entries we ship were grouped by which hostnames resolve to the same address, which is a best guess at that: confirm it against the web ACLs ops actually create, and merge or split entries to match.
898
+ - `scriptURL` comes from _Application integration_ in the AWS WAF console. Ops are issuing the _Intelligent threat integration_ URL, which ends in `challenge.js`; the _CAPTCHA integration_ one ends in `jsapi.js` and works the same way. It isn't a secret: it ends up in the page source. Leave it empty for a web ACL that doesn't exist yet and the entry does nothing.
899
+ - `cookieDomains` is optional, e.g. `['.nice.org.uk']`. It widens the token cookie from the exact hostname so that one token works across subdomains. It's only valid once the same domain is on the web ACL's token domain list, otherwise AWS rejects the tokens, so ask ops for that at the same time as the URL. The shipped entries all set it.
900
+
901
+ A new or changed entry needs a Global Nav release. Services loading the unversioned CDN bundle pick that up straight away; services using the npm package pick it up when they next upgrade and deploy.
902
+
903
+ #### NICE Accounts
904
+
905
+ NICE Accounts sits behind a web ACL too, and the header calls it to find out whether you're signed in. That call is a script tag, which can't send the token as a header, so it relies on the `aws-waf-token` cookie instead. Global Nav waits for the SDK to have a token before it makes the call, so the cookie is there to send. With no SDK on the page it doesn't wait at all, and if the SDK hasn't got a token after 5 seconds it makes the call anyway.
906
+
907
+ This only works when the cookie reaches `accounts.nice.org.uk`:
908
+
909
+ - The page has to be on `nice.org.uk`. A browser won't send a cookie from one domain to another, so services on other domains, and sandbox on `sandbox1-ds.net`, call NICE Accounts without a token.
910
+ - The cookie has to be set on `.nice.org.uk` and not on the exact hostname. The shipped entries do that with `cookieDomains`. An [`awsWafScriptURL`](#headerawswafscripturl) override doesn't, so set `window.awsWafCookieDomainList = ['.nice.org.uk']` on the page before Global Nav loads.
911
+ - `.nice.org.uk` has to be on the token domain list of both web ACLs: the one in front of the page and the one in front of NICE Accounts.
912
+
913
+ #### Content Security Policy
914
+
915
+ If your service sets a Content Security Policy then `script-src` and `connect-src` need to allow `https://*.awswaf.com`.
916
+
819
917
  ## Deployments
820
918
 
821
919
  We create 2 deployment artifacts: one for deploying to the CDN and one test site for previewing the header and footer.
@@ -14,10 +14,16 @@ var _Pages = _interopRequireDefault(require("./Pages"));
14
14
  var _FooterModule = _interopRequireDefault(require("./Footer.module.scss"));
15
15
  var _TrackedLink = _interopRequireDefault(require("../TrackedLink"));
16
16
  var _tracker = require("../tracker");
17
+ var _propTypes2 = require("../aws-waf/propTypes");
18
+ var _useAwsWafChallenge = require("../hooks/useAwsWafChallenge");
17
19
  var _jsxRuntime = require("react/jsx-runtime");
18
20
  //TODO add string type for service prop
19
21
  const Footer = _ref => {
20
- let service = _ref.service;
22
+ let {
23
+ service,
24
+ awsWafScriptURL
25
+ } = _ref;
26
+ (0, _useAwsWafChallenge.useAwsWafChallenge)(awsWafScriptURL);
21
27
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("footer", {
22
28
  className: _FooterModule.default.footer,
23
29
  "data-tracking": "Global footer",
@@ -39,6 +45,7 @@ const Footer = _ref => {
39
45
  });
40
46
  };
41
47
  Footer.propTypes = {
42
- service: _propTypes.default.string
48
+ service: _propTypes.default.string,
49
+ awsWafScriptURL: _propTypes2.awsWafScriptURLPropType
43
50
  };
44
51
  var _default = exports.default = Footer;
@@ -13,7 +13,9 @@ var _tracker = require("../../tracker");
13
13
  var _jsxRuntime = require("react/jsx-runtime");
14
14
  //TODO add string type for service prop
15
15
  const Pages = _ref => {
16
- let service = _ref.service;
16
+ let {
17
+ service
18
+ } = _ref;
17
19
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("nav", {
18
20
  className: _PagesModule.default.wrapper,
19
21
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
@@ -5,15 +5,12 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
10
9
  var _ServicesModule = _interopRequireDefault(require("./Services.module.scss"));
11
10
  var _TrackedLink = _interopRequireDefault(require("../../TrackedLink"));
12
11
  var _tracker = require("../../tracker");
13
12
  var _services = _interopRequireDefault(require("../../services.json"));
14
13
  var _jsxRuntime = require("react/jsx-runtime");
15
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
16
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
17
14
  const Services = () => {
18
15
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("nav", {
19
16
  className: _ServicesModule.default.wrapper,
@@ -25,10 +22,14 @@ const Services = () => {
25
22
  }).map(function (link) {
26
23
  if (link.nestedLinks) {
27
24
  return link.nestedLinks.map(nestedLink => {
28
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, _objectSpread({}, nestedLink), nestedLink.id);
25
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, {
26
+ ...nestedLink
27
+ }, nestedLink.id);
29
28
  });
30
29
  } else {
31
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, _objectSpread({}, link), link.id);
30
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, {
31
+ ...link
32
+ }, link.id);
32
33
  }
33
34
  })
34
35
  })
@@ -45,14 +46,16 @@ FooterLink.propTypes = {
45
46
  title: _propTypes.default.string
46
47
  };
47
48
  function FooterLink(_ref) {
48
- let host = _ref.host,
49
- landingPath = _ref.landingPath,
50
- text = _ref.text,
51
- abbreviation = _ref.abbreviation,
52
- title = _ref.title;
49
+ let {
50
+ host,
51
+ landingPath,
52
+ text,
53
+ abbreviation,
54
+ title
55
+ } = _ref;
53
56
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
54
57
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_TrackedLink.default, {
55
- href: "https://".concat(host).concat(landingPath),
58
+ href: `https://${host}${landingPath}`,
56
59
  eventAction: _tracker.footerClickEventAction,
57
60
  eventLabel: text,
58
61
  className: _ServicesModule.default.link,
@@ -5,8 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
8
  var _react = require("react");
11
9
  var _HeaderContext = require("../context/HeaderContext");
12
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
@@ -15,18 +13,16 @@ var _niceAccounts = require("./nice-accounts");
15
13
  var _AccountModule = _interopRequireDefault(require("./Account.module.scss"));
16
14
  var _tracker = require("../../tracker");
17
15
  var _jsxRuntime = require("react/jsx-runtime");
18
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
19
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
20
16
  function Account(props) {
21
- const _props$provider = props.provider,
22
- provider = _props$provider === void 0 ? "niceAccounts" : _props$provider;
17
+ const {
18
+ provider = "niceAccounts"
19
+ } = props;
23
20
  // We've left this is state as per the pre-hook implementation
24
- const _useState = (0, _react.useState)(provider == Account.providers.idam),
25
- _useState2 = (0, _slicedToArray2.default)(_useState, 1),
26
- doesUseIdAM = _useState2[0];
27
- const _useContext = (0, _react.useContext)(_HeaderContext.HeaderContext),
28
- accountMenuIsExpanded = _useContext.accountMenuIsExpanded,
29
- setAccountMenuIsExpanded = _useContext.setAccountMenuIsExpanded;
21
+ const [doesUseIdAM] = (0, _react.useState)(provider == Account.providers.idam);
22
+ const {
23
+ accountMenuIsExpanded,
24
+ setAccountMenuIsExpanded
25
+ } = (0, _react.useContext)(_HeaderContext.HeaderContext);
30
26
  const keypress = (0, _react.useRef)(),
31
27
  myAccountButton = (0, _react.useRef)(),
32
28
  myAccountMenu = (0, _react.useRef)();
@@ -76,14 +72,19 @@ function Account(props) {
76
72
  //idam supplies links like:[{ key: "My profile", value: "/Account/todo" },{ key: "Sign out", value: "/Account/Logout" }]
77
73
  //the following just converts the idam format to the nice accounts format.
78
74
 
79
- const displayName = props.displayName;
75
+ const {
76
+ displayName
77
+ } = props;
80
78
  const isLoggedIn = !!displayName;
81
79
  let links = props.links.reduce(function (links, link) {
82
80
  links[link.text] = link.url;
83
81
  return links;
84
82
  }, {});
85
83
  if (isLoggedIn) {
86
- links = _objectSpread(_objectSpread({}, consultationsResponsesLink), links);
84
+ links = {
85
+ ...consultationsResponsesLink,
86
+ ...links
87
+ };
87
88
  }
88
89
  const convertedData = {
89
90
  display_name: displayName,
@@ -96,7 +97,10 @@ function Account(props) {
96
97
  //NICE accounts
97
98
  (0, _niceAccounts.checkIsLoggedIn)(props.environment).then(function (data) {
98
99
  if (props.onLoginStatusChecked) {
99
- data.links = _objectSpread(_objectSpread({}, consultationsResponsesLink), data.links);
100
+ data.links = {
101
+ ...consultationsResponsesLink,
102
+ ...data.links
103
+ };
100
104
  props.onLoginStatusChecked(data);
101
105
  }
102
106
  }).catch(function (e) {
@@ -104,9 +108,10 @@ function Account(props) {
104
108
  });
105
109
  }
106
110
  }, []);
107
- const accountsData = props.accountsData,
108
- _props$environment = props.environment,
109
- environment = _props$environment === void 0 ? "live" : _props$environment;
111
+ const {
112
+ accountsData,
113
+ environment = "live"
114
+ } = props;
110
115
  let signInLink = {};
111
116
  if (doesUseIdAM) {
112
117
  signInLink = props.links[0];
@@ -4,11 +4,20 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.getDomainBaseUrl = exports.checkIsLoggedIn = void 0;
7
+ var _awsWaf = require("../../aws-waf");
7
8
  // Checks if you are logged in via NICE Accounts
8
9
  // Returns a promise that resolves with the data from NICE Accounts.
9
10
  // Returns a promise that rejects if the data could not be loaded.
10
11
 
11
12
  const checkIsLoggedIn = function (environment) {
13
+ // NICE Accounts sits behind an AWS WAF web ACL. A script tag can't send the token as a header,
14
+ // so wait for the SDK to set the token cookie, which the browser then sends along by itself
15
+ return (0, _awsWaf.whenAwsWafTokenReady)().then(function () {
16
+ return loadAccountsData(environment);
17
+ });
18
+ };
19
+ exports.checkIsLoggedIn = checkIsLoggedIn;
20
+ const loadAccountsData = function (environment) {
12
21
  return new Promise(function (resolve, reject) {
13
22
  const url = getDomainBaseUrl(environment) + "tophat";
14
23
  var body = document.body;
@@ -30,8 +39,7 @@ const checkIsLoggedIn = function (environment) {
30
39
  body.insertBefore(script, body.firstChild);
31
40
  });
32
41
  };
33
- exports.checkIsLoggedIn = checkIsLoggedIn;
34
42
  const getDomainBaseUrl = function (environment) {
35
- return "https://".concat(environment !== "live" ? environment + "-" : "", "accounts.nice.org.uk/");
43
+ return `https://${environment !== "live" ? environment + "-" : ""}accounts.nice.org.uk/`;
36
44
  };
37
45
  exports.getDomainBaseUrl = getDomainBaseUrl;
@@ -5,8 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = exports.OldHeader = void 0;
8
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
8
  var _react = _interopRequireWildcard(require("react"));
11
9
  var _propTypes = _interopRequireDefault(require("prop-types"));
12
10
  var _LogoFull = _interopRequireDefault(require("@nice-digital/icons/lib/LogoFull"));
@@ -17,40 +15,31 @@ var _Search = _interopRequireDefault(require("./Search"));
17
15
  var _Account = _interopRequireDefault(require("./Account"));
18
16
  var _SkipLink = _interopRequireDefault(require("./SkipLink"));
19
17
  var _utils = require("../utils");
18
+ var _propTypes2 = require("../aws-waf/propTypes");
19
+ var _useAwsWafChallenge = require("../hooks/useAwsWafChallenge");
20
20
  var _HeaderModule = _interopRequireDefault(require("./Header.module.scss"));
21
21
  var _HeaderContext = require("./context/HeaderContext");
22
22
  var _jsxRuntime = require("react/jsx-runtime");
23
23
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
24
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
25
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
26
24
  const Header = _ref => {
27
- let _ref$skipLinkId = _ref.skipLinkId,
28
- skipLinkId = _ref$skipLinkId === void 0 ? "content-start" : _ref$skipLinkId,
29
- _ref$renderSearchOnly = _ref.renderSearchOnly,
30
- renderSearchOnly = _ref$renderSearchOnly === void 0 ? false : _ref$renderSearchOnly,
31
- onNavigating = _ref.onNavigating,
32
- _ref$search = _ref.search,
33
- search = _ref$search === void 0 ? {} : _ref$search,
34
- enabled = _ref.enabled,
35
- onRendered = _ref.onRendered,
36
- auth = _ref.auth,
37
- service = _ref.service,
38
- _ref$additionalSubMen = _ref.additionalSubMenuItems,
39
- additionalSubMenuItems = _ref$additionalSubMen === void 0 ? [] : _ref$additionalSubMen,
40
- onDropdownOpen = _ref.onDropdownOpen,
41
- onDropdownClose = _ref.onDropdownClose;
42
- const _useState = (0, _react.useState)(false),
43
- _useState2 = (0, _slicedToArray2.default)(_useState, 2),
44
- isExpanded = _useState2[0],
45
- setIsExpanded = _useState2[1];
46
- const _useState3 = (0, _react.useState)(false),
47
- _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
48
- isLoggedIn = _useState4[0],
49
- setIsLoggedIn = _useState4[1];
50
- const _useState5 = (0, _react.useState)(null),
51
- _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
52
- accountsData = _useState6[0],
53
- setAccountsData = _useState6[1];
25
+ let {
26
+ skipLinkId = "content-start",
27
+ renderSearchOnly = false,
28
+ onNavigating,
29
+ search = {},
30
+ enabled,
31
+ onRendered,
32
+ auth,
33
+ service,
34
+ additionalSubMenuItems = [],
35
+ onDropdownOpen,
36
+ onDropdownClose,
37
+ awsWafScriptURL
38
+ } = _ref;
39
+ const [isExpanded, setIsExpanded] = (0, _react.useState)(false);
40
+ const [isLoggedIn, setIsLoggedIn] = (0, _react.useState)(false);
41
+ const [accountsData, setAccountsData] = (0, _react.useState)(null);
42
+ (0, _useAwsWafChallenge.useAwsWafChallenge)(awsWafScriptURL);
54
43
  (0, _react.useEffect)(() => {
55
44
  if (!document.getElementById(skipLinkId)) {
56
45
  const firstH1OnPage = document.getElementsByTagName("h1")[0];
@@ -96,15 +85,18 @@ const Header = _ref => {
96
85
  }
97
86
  };
98
87
  if (renderSearchOnly) {
99
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
88
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
100
89
  skipLinkId: skipLinkId,
101
- onNavigating: onNavigating
102
- }, search));
90
+ onNavigating: onNavigating,
91
+ ...search
92
+ });
103
93
  }
104
94
  return enabled !== false && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_HeaderContext.HeaderContextProvider, {
105
95
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_HeaderContext.HeaderContext.Consumer, {
106
96
  children: _ref2 => {
107
- let idOfOpenDropdown = _ref2.idOfOpenDropdown;
97
+ let {
98
+ idOfOpenDropdown
99
+ } = _ref2;
108
100
  dropdownToggleHandler(idOfOpenDropdown);
109
101
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
110
102
  id: "scrim",
@@ -124,7 +116,7 @@ const Header = _ref => {
124
116
  "aria-label": "Accessibility links",
125
117
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
126
118
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SkipLink.default, {
127
- to: "#".concat(skipLinkId),
119
+ to: `#${skipLinkId}`,
128
120
  children: "Skip to content"
129
121
  })
130
122
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
@@ -150,10 +142,11 @@ const Header = _ref => {
150
142
  className: _HeaderModule.default.wrapper,
151
143
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
152
144
  className: _HeaderModule.default.search,
153
- children: search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
145
+ children: search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
154
146
  skipLinkId: skipLinkId,
155
- onNavigating: onNavigating
156
- }, search))
147
+ onNavigating: onNavigating,
148
+ ...search
149
+ })
157
150
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
158
151
  className: _HeaderModule.default.mobileMenuBtn,
159
152
  id: "header-menu-button",
@@ -166,11 +159,12 @@ const Header = _ref => {
166
159
  children: isExpanded ? "Close" : "Menu"
167
160
  }), auth !== false && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
168
161
  className: _HeaderModule.default.account,
169
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, _objectSpread({
162
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, {
170
163
  onLoginStatusChecked: handleLoginStatusChecked,
171
164
  isLoggedIn: isLoggedIn,
172
- accountsData: accountsData
173
- }, auth))
165
+ accountsData: accountsData,
166
+ ...auth
167
+ })
174
168
  })]
175
169
  })]
176
170
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Nav.default, {
@@ -233,9 +227,10 @@ class OldHeader extends _react.Component {
233
227
  }
234
228
  dropdownToggleHandler(idOfOpenDropdown) {
235
229
  // If we've got an onDropdownOpen or onDropdownClose prop call the onDropdownOpen or onDropdownClose callback based on idOfOpenDropdown.
236
- const _this$props = this.props,
237
- onDropdownOpen = _this$props.onDropdownOpen,
238
- onDropdownClose = _this$props.onDropdownClose;
230
+ const {
231
+ onDropdownOpen,
232
+ onDropdownClose
233
+ } = this.props;
239
234
  if (onDropdownOpen && idOfOpenDropdown !== null) {
240
235
  const onDropdownOpenCallback = (0, _utils.getCallbackFunction)(onDropdownOpen);
241
236
  if (onDropdownOpenCallback) {
@@ -251,15 +246,18 @@ class OldHeader extends _react.Component {
251
246
  }
252
247
  render() {
253
248
  if (this.props.renderSearchOnly) {
254
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
249
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
255
250
  skipLinkId: this.props.skipLinkId,
256
- onNavigating: this.props.onNavigating
257
- }, this.props.search));
251
+ onNavigating: this.props.onNavigating,
252
+ ...this.props.search
253
+ });
258
254
  }
259
255
  return this.props.enabled !== false && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_HeaderContext.HeaderContextProvider, {
260
256
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_HeaderContext.HeaderContext.Consumer, {
261
257
  children: _ref3 => {
262
- let idOfOpenDropdown = _ref3.idOfOpenDropdown;
258
+ let {
259
+ idOfOpenDropdown
260
+ } = _ref3;
263
261
  this.dropdownToggleHandler(idOfOpenDropdown);
264
262
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
265
263
  id: "scrim",
@@ -279,7 +277,7 @@ class OldHeader extends _react.Component {
279
277
  "aria-label": "Accessibility links",
280
278
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
281
279
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SkipLink.default, {
282
- to: "#".concat(this.props.skipLinkId),
280
+ to: `#${this.props.skipLinkId}`,
283
281
  children: "Skip to content"
284
282
  })
285
283
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
@@ -305,10 +303,11 @@ class OldHeader extends _react.Component {
305
303
  className: _HeaderModule.default.wrapper,
306
304
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
307
305
  className: _HeaderModule.default.search,
308
- children: this.props.search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
306
+ children: this.props.search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
309
307
  skipLinkId: this.props.skipLinkId,
310
- onNavigating: this.props.onNavigating
311
- }, this.props.search))
308
+ onNavigating: this.props.onNavigating,
309
+ ...this.props.search
310
+ })
312
311
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
313
312
  className: _HeaderModule.default.mobileMenuBtn,
314
313
  id: "header-menu-button",
@@ -321,11 +320,12 @@ class OldHeader extends _react.Component {
321
320
  children: this.state.isExpanded ? "Close" : "Menu"
322
321
  }), this.props.auth !== false && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
323
322
  className: _HeaderModule.default.account,
324
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, _objectSpread({
323
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, {
325
324
  onLoginStatusChecked: this.handleLoginStatusChecked,
326
325
  isLoggedIn: this.state.isLoggedIn,
327
- accountsData: this.state.accountsData
328
- }, this.props.auth))
326
+ accountsData: this.state.accountsData,
327
+ ...this.props.auth
328
+ })
329
329
  })]
330
330
  })]
331
331
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Nav.default, {
@@ -356,7 +356,8 @@ Header.propTypes = {
356
356
  onDropdownClose: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.string]),
357
357
  onRendered: _propTypes.default.func,
358
358
  additionalSubMenuItems: _propTypes.default.arrayOf(_propTypes.default.object),
359
- renderSearchOnly: _propTypes.default.bool
359
+ renderSearchOnly: _propTypes.default.bool,
360
+ awsWafScriptURL: _propTypes2.awsWafScriptURLPropType
360
361
  };
361
362
  OldHeader.propTypes = {
362
363
  service: _propTypes.default.string,