@nice-digital/global-nav 7.1.1201-GN-264-load-aws-chal → 7.1.1202
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.
- package/README.md +0 -98
- package/lib/Footer/Footer.js +2 -9
- package/lib/Footer/Pages/Pages.js +1 -3
- package/lib/Footer/Services/Services.js +11 -14
- package/lib/Header/Account/Account.js +18 -23
- package/lib/Header/Account/nice-accounts.js +2 -10
- package/lib/Header/Header.js +57 -58
- package/lib/Header/Nav/Dropdown/Components/AboutUs.js +29 -31
- package/lib/Header/Nav/Dropdown/Components/Grid.js +13 -12
- package/lib/Header/Nav/Dropdown/Components/LifeSciences.js +13 -15
- package/lib/Header/Nav/Dropdown/Components/MoreFromNICE.js +11 -13
- package/lib/Header/Nav/Dropdown/Components/StandardsAndIndicators.js +10 -12
- package/lib/Header/Nav/Dropdown/Dropdown.js +15 -19
- package/lib/Header/Nav/Nav.js +11 -15
- package/lib/Header/Nav/NavLinks/NavLinks.js +33 -37
- package/lib/Header/Nav/SubNav/SubNav.js +3 -7
- package/lib/Header/Search/Autocomplete/Autocomplete.js +32 -25
- package/lib/Header/Search/Autocomplete/suggester/index.js +4 -6
- package/lib/Header/Search/Autocomplete/suggester/phrase-finder.js +3 -5
- package/lib/Header/Search/Autocomplete/suggester/term-finder.js +3 -5
- package/lib/Header/Search/Search.js +11 -10
- package/lib/Header/context/HeaderContext.js +10 -5
- package/lib/Main/Main.js +15 -16
- package/lib/TrackedLink/TrackedLink.js +18 -14
- package/lib/hooks/useIsClient.js +6 -1
- package/lib/renderer.js +11 -17
- package/package.json +4 -9
- package/types.d.ts +0 -10
- package/lib/aws-waf/index.js +0 -131
- package/lib/aws-waf/integrations.js +0 -184
- package/lib/aws-waf/propTypes.js +0 -20
- package/lib/hooks/useAwsWafChallenge.js +0 -19
package/README.md
CHANGED
|
@@ -313,13 +313,6 @@ 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
|
-
|
|
323
316
|
##### Header props
|
|
324
317
|
|
|
325
318
|
###### Header.service
|
|
@@ -670,27 +663,6 @@ If the authentication provider has been set to "idam", then an array of links mu
|
|
|
670
663
|
|
|
671
664
|
The displayName is the user's name and must be provided if the "idam" provider is used and the user is logged in.
|
|
672
665
|
|
|
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
|
-
|
|
694
666
|
##### Footer props
|
|
695
667
|
|
|
696
668
|
###### Footer.service
|
|
@@ -702,13 +674,6 @@ The `Header`, `Footer` and `Main` components all take this prop and all behave t
|
|
|
702
674
|
The identifier of the currently active service.
|
|
703
675
|
See [services.json](src/services.json) for a list of the available service identifiers.
|
|
704
676
|
|
|
705
|
-
###### Footer.awsWafScriptURL
|
|
706
|
-
|
|
707
|
-
- Type: `String | false`
|
|
708
|
-
- Default: `undefined`
|
|
709
|
-
|
|
710
|
-
See [Header.awsWafScriptURL](#headerawswafscripturl).
|
|
711
|
-
|
|
712
677
|
### CDN
|
|
713
678
|
|
|
714
679
|
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:
|
|
@@ -851,69 +816,6 @@ The footer renders by default, set `footer` to `false` to stop it from rendering
|
|
|
851
816
|
Or, pass an object of key/value pairs of settings specific to the footer.
|
|
852
817
|
See the [footer props](#footer-props) section for available options.
|
|
853
818
|
|
|
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
|
-
|
|
917
819
|
## Deployments
|
|
918
820
|
|
|
919
821
|
We create 2 deployment artifacts: one for deploying to the CDN and one test site for previewing the header and footer.
|
package/lib/Footer/Footer.js
CHANGED
|
@@ -14,16 +14,10 @@ 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");
|
|
19
17
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
20
18
|
//TODO add string type for service prop
|
|
21
19
|
const Footer = _ref => {
|
|
22
|
-
let
|
|
23
|
-
service,
|
|
24
|
-
awsWafScriptURL
|
|
25
|
-
} = _ref;
|
|
26
|
-
(0, _useAwsWafChallenge.useAwsWafChallenge)(awsWafScriptURL);
|
|
20
|
+
let service = _ref.service;
|
|
27
21
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("footer", {
|
|
28
22
|
className: _FooterModule.default.footer,
|
|
29
23
|
"data-tracking": "Global footer",
|
|
@@ -45,7 +39,6 @@ const Footer = _ref => {
|
|
|
45
39
|
});
|
|
46
40
|
};
|
|
47
41
|
Footer.propTypes = {
|
|
48
|
-
service: _propTypes.default.string
|
|
49
|
-
awsWafScriptURL: _propTypes2.awsWafScriptURLPropType
|
|
42
|
+
service: _propTypes.default.string
|
|
50
43
|
};
|
|
51
44
|
var _default = exports.default = Footer;
|
|
@@ -13,9 +13,7 @@ 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
|
|
17
|
-
service
|
|
18
|
-
} = _ref;
|
|
16
|
+
let service = _ref.service;
|
|
19
17
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("nav", {
|
|
20
18
|
className: _PagesModule.default.wrapper,
|
|
21
19
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("ul", {
|
|
@@ -5,12 +5,15 @@ 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"));
|
|
8
9
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
9
10
|
var _ServicesModule = _interopRequireDefault(require("./Services.module.scss"));
|
|
10
11
|
var _TrackedLink = _interopRequireDefault(require("../../TrackedLink"));
|
|
11
12
|
var _tracker = require("../../tracker");
|
|
12
13
|
var _services = _interopRequireDefault(require("../../services.json"));
|
|
13
14
|
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; }
|
|
14
17
|
const Services = () => {
|
|
15
18
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("nav", {
|
|
16
19
|
className: _ServicesModule.default.wrapper,
|
|
@@ -22,14 +25,10 @@ const Services = () => {
|
|
|
22
25
|
}).map(function (link) {
|
|
23
26
|
if (link.nestedLinks) {
|
|
24
27
|
return link.nestedLinks.map(nestedLink => {
|
|
25
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, {
|
|
26
|
-
...nestedLink
|
|
27
|
-
}, nestedLink.id);
|
|
28
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, _objectSpread({}, nestedLink), nestedLink.id);
|
|
28
29
|
});
|
|
29
30
|
} else {
|
|
30
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, {
|
|
31
|
-
...link
|
|
32
|
-
}, link.id);
|
|
31
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FooterLink, _objectSpread({}, link), link.id);
|
|
33
32
|
}
|
|
34
33
|
})
|
|
35
34
|
})
|
|
@@ -46,16 +45,14 @@ FooterLink.propTypes = {
|
|
|
46
45
|
title: _propTypes.default.string
|
|
47
46
|
};
|
|
48
47
|
function FooterLink(_ref) {
|
|
49
|
-
let
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
title
|
|
55
|
-
} = _ref;
|
|
48
|
+
let host = _ref.host,
|
|
49
|
+
landingPath = _ref.landingPath,
|
|
50
|
+
text = _ref.text,
|
|
51
|
+
abbreviation = _ref.abbreviation,
|
|
52
|
+
title = _ref.title;
|
|
56
53
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
|
|
57
54
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_TrackedLink.default, {
|
|
58
|
-
href:
|
|
55
|
+
href: "https://".concat(host).concat(landingPath),
|
|
59
56
|
eventAction: _tracker.footerClickEventAction,
|
|
60
57
|
eventLabel: text,
|
|
61
58
|
className: _ServicesModule.default.link,
|
|
@@ -5,6 +5,8 @@ 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"));
|
|
8
10
|
var _react = require("react");
|
|
9
11
|
var _HeaderContext = require("../context/HeaderContext");
|
|
10
12
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
@@ -13,16 +15,18 @@ var _niceAccounts = require("./nice-accounts");
|
|
|
13
15
|
var _AccountModule = _interopRequireDefault(require("./Account.module.scss"));
|
|
14
16
|
var _tracker = require("../../tracker");
|
|
15
17
|
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; }
|
|
16
20
|
function Account(props) {
|
|
17
|
-
const
|
|
18
|
-
provider = "niceAccounts"
|
|
19
|
-
} = props;
|
|
21
|
+
const _props$provider = props.provider,
|
|
22
|
+
provider = _props$provider === void 0 ? "niceAccounts" : _props$provider;
|
|
20
23
|
// We've left this is state as per the pre-hook implementation
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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;
|
|
26
30
|
const keypress = (0, _react.useRef)(),
|
|
27
31
|
myAccountButton = (0, _react.useRef)(),
|
|
28
32
|
myAccountMenu = (0, _react.useRef)();
|
|
@@ -72,19 +76,14 @@ function Account(props) {
|
|
|
72
76
|
//idam supplies links like:[{ key: "My profile", value: "/Account/todo" },{ key: "Sign out", value: "/Account/Logout" }]
|
|
73
77
|
//the following just converts the idam format to the nice accounts format.
|
|
74
78
|
|
|
75
|
-
const
|
|
76
|
-
displayName
|
|
77
|
-
} = props;
|
|
79
|
+
const displayName = props.displayName;
|
|
78
80
|
const isLoggedIn = !!displayName;
|
|
79
81
|
let links = props.links.reduce(function (links, link) {
|
|
80
82
|
links[link.text] = link.url;
|
|
81
83
|
return links;
|
|
82
84
|
}, {});
|
|
83
85
|
if (isLoggedIn) {
|
|
84
|
-
links = {
|
|
85
|
-
...consultationsResponsesLink,
|
|
86
|
-
...links
|
|
87
|
-
};
|
|
86
|
+
links = _objectSpread(_objectSpread({}, consultationsResponsesLink), links);
|
|
88
87
|
}
|
|
89
88
|
const convertedData = {
|
|
90
89
|
display_name: displayName,
|
|
@@ -97,10 +96,7 @@ function Account(props) {
|
|
|
97
96
|
//NICE accounts
|
|
98
97
|
(0, _niceAccounts.checkIsLoggedIn)(props.environment).then(function (data) {
|
|
99
98
|
if (props.onLoginStatusChecked) {
|
|
100
|
-
data.links = {
|
|
101
|
-
...consultationsResponsesLink,
|
|
102
|
-
...data.links
|
|
103
|
-
};
|
|
99
|
+
data.links = _objectSpread(_objectSpread({}, consultationsResponsesLink), data.links);
|
|
104
100
|
props.onLoginStatusChecked(data);
|
|
105
101
|
}
|
|
106
102
|
}).catch(function (e) {
|
|
@@ -108,10 +104,9 @@ function Account(props) {
|
|
|
108
104
|
});
|
|
109
105
|
}
|
|
110
106
|
}, []);
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
environment = "live"
|
|
114
|
-
} = props;
|
|
107
|
+
const accountsData = props.accountsData,
|
|
108
|
+
_props$environment = props.environment,
|
|
109
|
+
environment = _props$environment === void 0 ? "live" : _props$environment;
|
|
115
110
|
let signInLink = {};
|
|
116
111
|
if (doesUseIdAM) {
|
|
117
112
|
signInLink = props.links[0];
|
|
@@ -4,20 +4,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getDomainBaseUrl = exports.checkIsLoggedIn = void 0;
|
|
7
|
-
var _awsWaf = require("../../aws-waf");
|
|
8
7
|
// Checks if you are logged in via NICE Accounts
|
|
9
8
|
// Returns a promise that resolves with the data from NICE Accounts.
|
|
10
9
|
// Returns a promise that rejects if the data could not be loaded.
|
|
11
10
|
|
|
12
11
|
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) {
|
|
21
12
|
return new Promise(function (resolve, reject) {
|
|
22
13
|
const url = getDomainBaseUrl(environment) + "tophat";
|
|
23
14
|
var body = document.body;
|
|
@@ -39,7 +30,8 @@ const loadAccountsData = function (environment) {
|
|
|
39
30
|
body.insertBefore(script, body.firstChild);
|
|
40
31
|
});
|
|
41
32
|
};
|
|
33
|
+
exports.checkIsLoggedIn = checkIsLoggedIn;
|
|
42
34
|
const getDomainBaseUrl = function (environment) {
|
|
43
|
-
return
|
|
35
|
+
return "https://".concat(environment !== "live" ? environment + "-" : "", "accounts.nice.org.uk/");
|
|
44
36
|
};
|
|
45
37
|
exports.getDomainBaseUrl = getDomainBaseUrl;
|
package/lib/Header/Header.js
CHANGED
|
@@ -5,6 +5,8 @@ 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"));
|
|
8
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
11
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
12
|
var _LogoFull = _interopRequireDefault(require("@nice-digital/icons/lib/LogoFull"));
|
|
@@ -15,31 +17,40 @@ var _Search = _interopRequireDefault(require("./Search"));
|
|
|
15
17
|
var _Account = _interopRequireDefault(require("./Account"));
|
|
16
18
|
var _SkipLink = _interopRequireDefault(require("./SkipLink"));
|
|
17
19
|
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; }
|
|
24
26
|
const Header = _ref => {
|
|
25
|
-
let
|
|
26
|
-
skipLinkId = "content-start",
|
|
27
|
-
renderSearchOnly =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
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];
|
|
43
54
|
(0, _react.useEffect)(() => {
|
|
44
55
|
if (!document.getElementById(skipLinkId)) {
|
|
45
56
|
const firstH1OnPage = document.getElementsByTagName("h1")[0];
|
|
@@ -85,18 +96,15 @@ const Header = _ref => {
|
|
|
85
96
|
}
|
|
86
97
|
};
|
|
87
98
|
if (renderSearchOnly) {
|
|
88
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
|
|
99
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
|
|
89
100
|
skipLinkId: skipLinkId,
|
|
90
|
-
onNavigating: onNavigating
|
|
91
|
-
|
|
92
|
-
});
|
|
101
|
+
onNavigating: onNavigating
|
|
102
|
+
}, search));
|
|
93
103
|
}
|
|
94
104
|
return enabled !== false && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_HeaderContext.HeaderContextProvider, {
|
|
95
105
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_HeaderContext.HeaderContext.Consumer, {
|
|
96
106
|
children: _ref2 => {
|
|
97
|
-
let
|
|
98
|
-
idOfOpenDropdown
|
|
99
|
-
} = _ref2;
|
|
107
|
+
let idOfOpenDropdown = _ref2.idOfOpenDropdown;
|
|
100
108
|
dropdownToggleHandler(idOfOpenDropdown);
|
|
101
109
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
102
110
|
id: "scrim",
|
|
@@ -116,7 +124,7 @@ const Header = _ref => {
|
|
|
116
124
|
"aria-label": "Accessibility links",
|
|
117
125
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
|
|
118
126
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SkipLink.default, {
|
|
119
|
-
to:
|
|
127
|
+
to: "#".concat(skipLinkId),
|
|
120
128
|
children: "Skip to content"
|
|
121
129
|
})
|
|
122
130
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
|
|
@@ -142,11 +150,10 @@ const Header = _ref => {
|
|
|
142
150
|
className: _HeaderModule.default.wrapper,
|
|
143
151
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
144
152
|
className: _HeaderModule.default.search,
|
|
145
|
-
children: search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
|
|
153
|
+
children: search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
|
|
146
154
|
skipLinkId: skipLinkId,
|
|
147
|
-
onNavigating: onNavigating
|
|
148
|
-
|
|
149
|
-
})
|
|
155
|
+
onNavigating: onNavigating
|
|
156
|
+
}, search))
|
|
150
157
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
151
158
|
className: _HeaderModule.default.mobileMenuBtn,
|
|
152
159
|
id: "header-menu-button",
|
|
@@ -159,12 +166,11 @@ const Header = _ref => {
|
|
|
159
166
|
children: isExpanded ? "Close" : "Menu"
|
|
160
167
|
}), auth !== false && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
161
168
|
className: _HeaderModule.default.account,
|
|
162
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, {
|
|
169
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, _objectSpread({
|
|
163
170
|
onLoginStatusChecked: handleLoginStatusChecked,
|
|
164
171
|
isLoggedIn: isLoggedIn,
|
|
165
|
-
accountsData: accountsData
|
|
166
|
-
|
|
167
|
-
})
|
|
172
|
+
accountsData: accountsData
|
|
173
|
+
}, auth))
|
|
168
174
|
})]
|
|
169
175
|
})]
|
|
170
176
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Nav.default, {
|
|
@@ -227,10 +233,9 @@ class OldHeader extends _react.Component {
|
|
|
227
233
|
}
|
|
228
234
|
dropdownToggleHandler(idOfOpenDropdown) {
|
|
229
235
|
// If we've got an onDropdownOpen or onDropdownClose prop call the onDropdownOpen or onDropdownClose callback based on idOfOpenDropdown.
|
|
230
|
-
const
|
|
231
|
-
onDropdownOpen,
|
|
232
|
-
onDropdownClose
|
|
233
|
-
} = this.props;
|
|
236
|
+
const _this$props = this.props,
|
|
237
|
+
onDropdownOpen = _this$props.onDropdownOpen,
|
|
238
|
+
onDropdownClose = _this$props.onDropdownClose;
|
|
234
239
|
if (onDropdownOpen && idOfOpenDropdown !== null) {
|
|
235
240
|
const onDropdownOpenCallback = (0, _utils.getCallbackFunction)(onDropdownOpen);
|
|
236
241
|
if (onDropdownOpenCallback) {
|
|
@@ -246,18 +251,15 @@ class OldHeader extends _react.Component {
|
|
|
246
251
|
}
|
|
247
252
|
render() {
|
|
248
253
|
if (this.props.renderSearchOnly) {
|
|
249
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
|
|
254
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
|
|
250
255
|
skipLinkId: this.props.skipLinkId,
|
|
251
|
-
onNavigating: this.props.onNavigating
|
|
252
|
-
|
|
253
|
-
});
|
|
256
|
+
onNavigating: this.props.onNavigating
|
|
257
|
+
}, this.props.search));
|
|
254
258
|
}
|
|
255
259
|
return this.props.enabled !== false && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_HeaderContext.HeaderContextProvider, {
|
|
256
260
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_HeaderContext.HeaderContext.Consumer, {
|
|
257
261
|
children: _ref3 => {
|
|
258
|
-
let
|
|
259
|
-
idOfOpenDropdown
|
|
260
|
-
} = _ref3;
|
|
262
|
+
let idOfOpenDropdown = _ref3.idOfOpenDropdown;
|
|
261
263
|
this.dropdownToggleHandler(idOfOpenDropdown);
|
|
262
264
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
263
265
|
id: "scrim",
|
|
@@ -277,7 +279,7 @@ class OldHeader extends _react.Component {
|
|
|
277
279
|
"aria-label": "Accessibility links",
|
|
278
280
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
|
|
279
281
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_SkipLink.default, {
|
|
280
|
-
to:
|
|
282
|
+
to: "#".concat(this.props.skipLinkId),
|
|
281
283
|
children: "Skip to content"
|
|
282
284
|
})
|
|
283
285
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
|
|
@@ -303,11 +305,10 @@ class OldHeader extends _react.Component {
|
|
|
303
305
|
className: _HeaderModule.default.wrapper,
|
|
304
306
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
305
307
|
className: _HeaderModule.default.search,
|
|
306
|
-
children: this.props.search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, {
|
|
308
|
+
children: this.props.search && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Search.default, _objectSpread({
|
|
307
309
|
skipLinkId: this.props.skipLinkId,
|
|
308
|
-
onNavigating: this.props.onNavigating
|
|
309
|
-
|
|
310
|
-
})
|
|
310
|
+
onNavigating: this.props.onNavigating
|
|
311
|
+
}, this.props.search))
|
|
311
312
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
312
313
|
className: _HeaderModule.default.mobileMenuBtn,
|
|
313
314
|
id: "header-menu-button",
|
|
@@ -320,12 +321,11 @@ class OldHeader extends _react.Component {
|
|
|
320
321
|
children: this.state.isExpanded ? "Close" : "Menu"
|
|
321
322
|
}), this.props.auth !== false && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
322
323
|
className: _HeaderModule.default.account,
|
|
323
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, {
|
|
324
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Account.default, _objectSpread({
|
|
324
325
|
onLoginStatusChecked: this.handleLoginStatusChecked,
|
|
325
326
|
isLoggedIn: this.state.isLoggedIn,
|
|
326
|
-
accountsData: this.state.accountsData
|
|
327
|
-
|
|
328
|
-
})
|
|
327
|
+
accountsData: this.state.accountsData
|
|
328
|
+
}, this.props.auth))
|
|
329
329
|
})]
|
|
330
330
|
})]
|
|
331
331
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Nav.default, {
|
|
@@ -356,8 +356,7 @@ 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
|
|
360
|
-
awsWafScriptURL: _propTypes2.awsWafScriptURLPropType
|
|
359
|
+
renderSearchOnly: _propTypes.default.bool
|
|
361
360
|
};
|
|
362
361
|
OldHeader.propTypes = {
|
|
363
362
|
service: _propTypes.default.string,
|