@ons/design-system 45.2.2 → 46.1.1
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/components/address-input/autosuggest.address.js +93 -118
- package/components/autosuggest/autosuggest.js +3 -11
- package/components/autosuggest/autosuggest.ui.js +3 -10
- package/components/footer/_footer.scss +6 -0
- package/components/footer/_macro.njk +2 -1
- package/components/lists/_macro.njk +8 -12
- package/components/modal/_macro.njk +1 -1
- package/components/panel/_macro.njk +5 -1
- package/components/panel/_panel.scss +4 -0
- package/components/timeout-modal/_macro.njk +3 -2
- package/components/timeout-modal/{timeout.dom.js → timeout-modal.dom.js} +2 -2
- package/components/timeout-modal/timeout-modal.js +62 -0
- package/components/timeout-panel/_macro.njk +26 -0
- package/components/timeout-panel/timeout-panel.dom.js +17 -0
- package/css/census.css +1 -1
- package/css/main.css +1 -1
- package/js/abortable-fetch.js +13 -38
- package/js/main.js +2 -1
- package/{components/timeout-modal → js}/timeout.js +42 -79
- package/layout/_template.njk +32 -4
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +2 -2
|
@@ -74,81 +74,68 @@ export default class AutosuggestAddress {
|
|
|
74
74
|
this.checkAPIStatus();
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
checkAPIStatus() {
|
|
77
|
+
async checkAPIStatus() {
|
|
78
78
|
this.fetch = abortableFetch(this.lookupURL + 'CF142&limit=10', {
|
|
79
79
|
method: 'GET',
|
|
80
80
|
headers: this.setAuthorization(this.authorizationToken),
|
|
81
81
|
});
|
|
82
|
-
|
|
83
|
-
.send()
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (status > 400) {
|
|
87
|
-
if (this.isEditable) {
|
|
88
|
-
this.handleAPIError();
|
|
89
|
-
} else {
|
|
90
|
-
this.autosuggest.handleNoResults(status);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
.catch(error => {
|
|
95
|
-
console.log(error);
|
|
82
|
+
try {
|
|
83
|
+
const response = await this.fetch.send();
|
|
84
|
+
const status = (await response.json()).status.code;
|
|
85
|
+
if (status > 400) {
|
|
96
86
|
if (this.isEditable) {
|
|
97
87
|
this.handleAPIError();
|
|
98
88
|
} else {
|
|
99
89
|
this.autosuggest.handleNoResults(status);
|
|
100
90
|
}
|
|
101
|
-
}
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.log(error);
|
|
94
|
+
if (this.isEditable) {
|
|
95
|
+
this.handleAPIError();
|
|
96
|
+
} else {
|
|
97
|
+
this.autosuggest.handleNoResults(status);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
102
100
|
}
|
|
103
101
|
|
|
104
|
-
suggestAddresses(query, [], grouped) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
102
|
+
async suggestAddresses(query, [], grouped) {
|
|
103
|
+
if (this.fetch && this.fetch.status !== 'DONE') {
|
|
104
|
+
this.fetch.abort();
|
|
105
|
+
}
|
|
109
106
|
|
|
110
|
-
|
|
111
|
-
this.findAddress(query, grouped)
|
|
112
|
-
.then(resolve)
|
|
113
|
-
.catch(reject);
|
|
114
|
-
});
|
|
107
|
+
return await this.findAddress(query, grouped);
|
|
115
108
|
}
|
|
116
109
|
|
|
117
|
-
findAddress(text, grouped) {
|
|
118
|
-
|
|
119
|
-
let queryURL, fullQueryURL;
|
|
110
|
+
async findAddress(text, grouped) {
|
|
111
|
+
let queryURL, fullQueryURL;
|
|
120
112
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
113
|
+
if (this.manualQueryParams) {
|
|
114
|
+
const manualQueryParams = this.container.getAttribute('data-query-params');
|
|
115
|
+
fullQueryURL = this.lookupURL + text + manualQueryParams;
|
|
116
|
+
} else {
|
|
117
|
+
const fullPostcodeQuery = this.testFullPostcodeQuery(text);
|
|
118
|
+
let limit = fullPostcodeQuery ? 100 : 10;
|
|
127
119
|
|
|
128
|
-
|
|
120
|
+
queryURL = grouped ? this.lookupGroupURL + this.groupQuery : this.lookupURL + text + '&limit=' + limit;
|
|
129
121
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
122
|
+
fullQueryURL = this.generateURLParams(queryURL);
|
|
123
|
+
if (fullPostcodeQuery && grouped !== false) {
|
|
124
|
+
fullQueryURL = fullQueryURL + '&groupfullpostcodes=combo';
|
|
134
125
|
}
|
|
126
|
+
}
|
|
135
127
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
});
|
|
140
|
-
this.fetch
|
|
141
|
-
.send()
|
|
142
|
-
.then(async data => {
|
|
143
|
-
const response = await data.json();
|
|
144
|
-
const status = response.status.code;
|
|
145
|
-
const addresses = response.response;
|
|
146
|
-
const limit = response.response.limit;
|
|
147
|
-
const results = await this.mapFindResults(addresses, limit, status);
|
|
148
|
-
resolve(results);
|
|
149
|
-
})
|
|
150
|
-
.catch(reject);
|
|
128
|
+
this.fetch = abortableFetch(fullQueryURL, {
|
|
129
|
+
method: 'GET',
|
|
130
|
+
headers: this.setAuthorization(this.authorizationToken),
|
|
151
131
|
});
|
|
132
|
+
const data = await this.fetch.send();
|
|
133
|
+
const response = await data.json();
|
|
134
|
+
const status = response.status.code;
|
|
135
|
+
const addresses = response.response;
|
|
136
|
+
const limit = response.response.limit;
|
|
137
|
+
const results = await this.mapFindResults(addresses, limit, status);
|
|
138
|
+
return results;
|
|
152
139
|
}
|
|
153
140
|
|
|
154
141
|
async mapFindResults(results, limit, status) {
|
|
@@ -262,75 +249,66 @@ export default class AutosuggestAddress {
|
|
|
262
249
|
}
|
|
263
250
|
}
|
|
264
251
|
|
|
265
|
-
retrieveAddress(id, type = null) {
|
|
266
|
-
|
|
267
|
-
let retrieveUrl = this.retrieveURL + id;
|
|
268
|
-
|
|
269
|
-
const fullUPRNURL = this.generateURLParams(retrieveUrl, id, type);
|
|
252
|
+
async retrieveAddress(id, type = null) {
|
|
253
|
+
let retrieveUrl = this.retrieveURL + id;
|
|
270
254
|
|
|
271
|
-
|
|
272
|
-
method: 'GET',
|
|
273
|
-
headers: this.setAuthorization(this.authorizationToken),
|
|
274
|
-
});
|
|
255
|
+
const fullUPRNURL = this.generateURLParams(retrieveUrl, id, type);
|
|
275
256
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const data = await response.json();
|
|
280
|
-
resolve(data);
|
|
281
|
-
})
|
|
282
|
-
.catch(reject);
|
|
257
|
+
this.fetch = abortableFetch(fullUPRNURL, {
|
|
258
|
+
method: 'GET',
|
|
259
|
+
headers: this.setAuthorization(this.authorizationToken),
|
|
283
260
|
});
|
|
261
|
+
|
|
262
|
+
const response = await this.fetch.send();
|
|
263
|
+
const data = await response.json();
|
|
264
|
+
return data;
|
|
284
265
|
}
|
|
285
266
|
|
|
286
|
-
onAddressSelect(selectedResult) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
this.retrieveAddress(selectedResult.uprn, selectedResult.type)
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
reject();
|
|
313
|
-
});
|
|
314
|
-
} else if (selectedResult.postcode) {
|
|
315
|
-
this.autosuggest.input.value =
|
|
316
|
-
selectedResult.streetName +
|
|
317
|
-
', ' +
|
|
318
|
-
(selectedResult.townName === selectedResult.postTown
|
|
319
|
-
? selectedResult.postTown
|
|
320
|
-
: selectedResult.townName + ', ' + selectedResult.postTown) +
|
|
321
|
-
', ' +
|
|
322
|
-
selectedResult.postcode;
|
|
323
|
-
this.autosuggest.input.focus();
|
|
324
|
-
this.groupQuery =
|
|
325
|
-
'postcode=' + selectedResult.postcode + '&streetname=' + selectedResult.streetName + '&townname=' + selectedResult.townName;
|
|
326
|
-
this.autosuggest.handleChange(true);
|
|
267
|
+
async onAddressSelect(selectedResult) {
|
|
268
|
+
if (selectedResult.uprn) {
|
|
269
|
+
try {
|
|
270
|
+
const data = await this.retrieveAddress(selectedResult.uprn, selectedResult.type);
|
|
271
|
+
if (this.isEditable) {
|
|
272
|
+
if (data.status.code >= 403) {
|
|
273
|
+
this.autosuggest.handleNoResults(403);
|
|
274
|
+
} else {
|
|
275
|
+
this.addressSetter.setAddress(this.createAddressLines(data));
|
|
276
|
+
this.addressSelected = true;
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
this.selectedAddressValue = selectedResult.displayText;
|
|
280
|
+
this.autosuggest.input.value = selectedResult.displayText;
|
|
281
|
+
this.uprn.value = selectedResult.uprn;
|
|
282
|
+
this.addressSelected = true;
|
|
283
|
+
}
|
|
284
|
+
} catch (error) {
|
|
285
|
+
console.log(error);
|
|
286
|
+
if (this.isEditable) {
|
|
287
|
+
this.handleAPIError();
|
|
288
|
+
} else {
|
|
289
|
+
this.autosuggest.handleNoResults(403);
|
|
290
|
+
}
|
|
291
|
+
throw error;
|
|
327
292
|
}
|
|
328
|
-
})
|
|
293
|
+
} else if (selectedResult.postcode) {
|
|
294
|
+
this.autosuggest.input.value =
|
|
295
|
+
selectedResult.streetName +
|
|
296
|
+
', ' +
|
|
297
|
+
(selectedResult.townName === selectedResult.postTown
|
|
298
|
+
? selectedResult.postTown
|
|
299
|
+
: selectedResult.townName + ', ' + selectedResult.postTown) +
|
|
300
|
+
', ' +
|
|
301
|
+
selectedResult.postcode;
|
|
302
|
+
this.autosuggest.input.focus();
|
|
303
|
+
this.groupQuery =
|
|
304
|
+
'postcode=' + selectedResult.postcode + '&streetname=' + selectedResult.streetName + '&townname=' + selectedResult.townName;
|
|
305
|
+
this.autosuggest.handleChange(true);
|
|
306
|
+
}
|
|
329
307
|
}
|
|
330
308
|
|
|
331
|
-
createAddressLines(data
|
|
309
|
+
createAddressLines(data) {
|
|
332
310
|
const values = data.response.address;
|
|
333
|
-
|
|
311
|
+
return {
|
|
334
312
|
addressLine1: values.addressLine1,
|
|
335
313
|
addressLine2: values.addressLine2,
|
|
336
314
|
addressLine3: values.addressLine3,
|
|
@@ -338,9 +316,6 @@ export default class AutosuggestAddress {
|
|
|
338
316
|
postcode: values.postcode,
|
|
339
317
|
uprn: values.uprn,
|
|
340
318
|
};
|
|
341
|
-
resolve();
|
|
342
|
-
|
|
343
|
-
return addressLines;
|
|
344
319
|
}
|
|
345
320
|
|
|
346
321
|
generateURLParams(baseURL, uprn, type) {
|
|
@@ -14,19 +14,11 @@ export default class Autosuggest {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
onSelect(result) {
|
|
18
|
-
|
|
19
|
-
this.autosuggest.input.value = result.displayText;
|
|
20
|
-
|
|
21
|
-
resolve();
|
|
22
|
-
});
|
|
17
|
+
async onSelect(result) {
|
|
18
|
+
this.autosuggest.input.value = result.displayText;
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
onUnsetResult() {
|
|
26
|
-
return new Promise(resolve => {
|
|
27
|
-
resolve();
|
|
28
|
-
});
|
|
29
|
-
}
|
|
21
|
+
async onUnsetResult() {}
|
|
30
22
|
|
|
31
23
|
onError(error) {
|
|
32
24
|
console.error(error);
|
|
@@ -120,17 +120,10 @@ export default class AutosuggestUI {
|
|
|
120
120
|
this.bindEventListeners();
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
fetchData() {
|
|
123
|
+
async fetchData() {
|
|
124
124
|
this.fetch = abortableFetch(this.autosuggestData);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
.send()
|
|
128
|
-
.then(async response => {
|
|
129
|
-
this.data = await response.json();
|
|
130
|
-
resolve(this.data);
|
|
131
|
-
})
|
|
132
|
-
.catch(reject);
|
|
133
|
-
});
|
|
125
|
+
const response = await this.fetch.send();
|
|
126
|
+
this.data = await response.json();
|
|
134
127
|
}
|
|
135
128
|
|
|
136
129
|
bindEventListeners() {
|
|
@@ -163,6 +163,7 @@
|
|
|
163
163
|
<div class="ons-grid__col">
|
|
164
164
|
{{
|
|
165
165
|
onsList({
|
|
166
|
+
"classes": "ons-footer--rows",
|
|
166
167
|
"variants": ["bare", "inline"],
|
|
167
168
|
"itemsList": row.itemsList
|
|
168
169
|
})
|
|
@@ -227,7 +228,7 @@
|
|
|
227
228
|
<div class="ons-grid__col">
|
|
228
229
|
{{
|
|
229
230
|
onsList({
|
|
230
|
-
"classes": 'ons-u-mb-m',
|
|
231
|
+
"classes": 'ons-u-mb-m ons-footer--rows',
|
|
231
232
|
"variants": ['bare', 'inline'],
|
|
232
233
|
"itemsList": legal.itemsList
|
|
233
234
|
})
|
|
@@ -13,23 +13,18 @@
|
|
|
13
13
|
{% set otherClasses = '' %}
|
|
14
14
|
{% endif %}
|
|
15
15
|
|
|
16
|
-
{% if params.element is defined and params.element %}
|
|
16
|
+
{% if params.element is defined and params.element and listLength > 1 %}
|
|
17
17
|
{% set listEl = params.element | lower %}
|
|
18
|
+
{% elif (params.element is defined and params.element == 'ol') and listLength < 2 %}
|
|
19
|
+
{% set listEl = 'p' %}
|
|
18
20
|
{% else %}
|
|
19
21
|
{% set listEl = 'ul' %}
|
|
20
22
|
{% endif %}
|
|
21
|
-
|
|
22
|
-
{% if (params.element is defined and params.element == 'ol') and listLength < 2 %}
|
|
23
|
-
<p {% if params.id is defined and params.id %}id="{{ params.id }}"{% endif %}{% if params.classes is defined and params.classes %} class="{{ params.classes -}}"{% endif %}>
|
|
24
|
-
{%- for item in params.itemsList -%}
|
|
25
|
-
{{ item.text }}
|
|
26
|
-
{%- endfor -%}
|
|
27
|
-
</p>
|
|
28
|
-
{% else %}
|
|
29
|
-
<{{listEl}} {% if params.id is defined and params.id %}id="{{ params.id }}"{% endif %}class="{% if listLength > 1 %}ons-list{% endif %}{% if params.classes is defined and params.classes %} {{ params.classes -}}{% endif %}{% if params.variants is defined and params.variants %}{% if params.variants is not string %}{% for variant in params.variants %} ons-list--{{ variant }}{% endfor %}{% else %} ons-list--{{ params.variants }}{% endif %}{% endif %}{% if otherClasses %} {{ otherClasses -}}{% endif %}">
|
|
23
|
+
<{{listEl}} {% if params.id is defined and params.id %}id="{{ params.id }}"{% endif %}class="{% if listLength > 1 or listEl == 'ul' %}ons-list{% else %}ons-list--p{% endif %}{% if params.classes is defined and params.classes %} {{ params.classes -}}{% endif %}{% if params.variants is defined and params.variants %}{% if params.variants is not string %}{% for variant in params.variants %} ons-list--{{ variant }}{% endfor %}{% else %} ons-list--{{ params.variants }}{% endif %}{% endif %}{% if otherClasses %} {{ otherClasses -}}{% endif %}">
|
|
30
24
|
{%- for item in (params.itemsList if params.itemsList is iterable else params.itemsList.items()) -%}
|
|
25
|
+
{% if listLength > 1 or listEl == 'ul' %}
|
|
31
26
|
<li class="ons-list__item{% if item.listClasses is defined and item.listClasses %} {{ item.listClasses }}{% endif %}"{% if item.current is defined and item.current %} aria-current="true"{% endif %}>
|
|
32
|
-
|
|
27
|
+
{% endif %}
|
|
33
28
|
{% set itemText = item.text %}
|
|
34
29
|
|
|
35
30
|
{% if params.itemsList[0] is defined and item.iconType is defined and item.iconType %}
|
|
@@ -94,8 +89,9 @@
|
|
|
94
89
|
}}
|
|
95
90
|
{%- endif -%} </span>
|
|
96
91
|
{%- endif -%}
|
|
92
|
+
{% if listLength > 1 or listEl == 'ul' %}
|
|
97
93
|
</li>
|
|
94
|
+
{% endif %}
|
|
98
95
|
{%- endfor -%}
|
|
99
96
|
</{{listEl}}>
|
|
100
|
-
{% endif %}
|
|
101
97
|
{% endmacro %}
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
{% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
|
|
30
30
|
<div class="{{containerClass}}">
|
|
31
31
|
<div class="ons-container">
|
|
32
|
+
{% elif params.type is defined and params.type == "warn" %}
|
|
33
|
+
<div class="ons-container">
|
|
32
34
|
{% endif %}
|
|
33
35
|
|
|
34
36
|
<div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="ons-panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
|
|
@@ -86,7 +88,7 @@
|
|
|
86
88
|
{% endif %}
|
|
87
89
|
{% endif %}
|
|
88
90
|
|
|
89
|
-
<div class="ons-panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} ons-svg-icon-margin--{{ params.iconSize }}{% endif %}"
|
|
91
|
+
<div class="ons-panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} ons-svg-icon-margin--{{ params.iconSize }}{% endif %}">{{ (params.body if params else "") | safe }}
|
|
90
92
|
{{ caller() if caller }}
|
|
91
93
|
</div>
|
|
92
94
|
|
|
@@ -95,6 +97,8 @@
|
|
|
95
97
|
{% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
|
|
96
98
|
</div>
|
|
97
99
|
</div>
|
|
100
|
+
{% elif params.type is defined and params.type == "warn" %}
|
|
101
|
+
</div>
|
|
98
102
|
{% endif %}
|
|
99
103
|
|
|
100
104
|
{% endmacro %}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% from "components/modal/_macro.njk" import onsModal %}
|
|
2
|
-
{% macro onsTimeoutModal(params) %}
|
|
2
|
+
{% macro onsTimeoutModal(params) %}
|
|
3
3
|
{% call onsModal({
|
|
4
4
|
"title": params.title,
|
|
5
5
|
"btnText": params.btnText,
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
"data-show-modal-time": params.showModalTimeInSeconds,
|
|
11
11
|
"data-server-session-expiry-endpoint": params.serverSessionExpiryEndpoint,
|
|
12
12
|
"data-countdown-text": params.countdownText,
|
|
13
|
-
"data-
|
|
13
|
+
"data-countdown-expired-text": params.countdownExpiredText,
|
|
14
14
|
"data-minutes-text-singular": params.minutesTextSingular,
|
|
15
15
|
"data-minutes-text-plural": params.minutesTextPlural,
|
|
16
16
|
"data-seconds-text-singular": params.secondsTextSingular,
|
|
17
17
|
"data-seconds-text-plural": params.secondsTextPlural,
|
|
18
|
+
"data-full-stop": params.endWithFullStop,
|
|
18
19
|
"aria-describedby": "timeout-time-remaining"
|
|
19
20
|
}
|
|
20
21
|
})
|
|
@@ -4,12 +4,12 @@ async function modals() {
|
|
|
4
4
|
const timeouts = [...document.querySelectorAll('.ons-js-timeout-modal')];
|
|
5
5
|
|
|
6
6
|
if (timeouts.length) {
|
|
7
|
-
const
|
|
7
|
+
const TimeoutModal = (await import('./timeout-modal')).default;
|
|
8
8
|
|
|
9
9
|
timeouts.forEach(context => {
|
|
10
10
|
let url = context.getAttribute('data-server-session-expiry-endpoint');
|
|
11
11
|
let time = context.getAttribute('data-server-session-expires-at');
|
|
12
|
-
new
|
|
12
|
+
new TimeoutModal(context, url, time);
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Modal from '../modal/modal';
|
|
2
|
+
import Timeout from '../../js/timeout';
|
|
3
|
+
|
|
4
|
+
export default class TimeoutModal {
|
|
5
|
+
constructor(context, sessionExpiryEndpoint, initialExpiryTime) {
|
|
6
|
+
this.context = context;
|
|
7
|
+
this.sessionExpiryEndpoint = sessionExpiryEndpoint;
|
|
8
|
+
this.initialExpiryTime = initialExpiryTime;
|
|
9
|
+
this.continueButton = context.querySelector('.ons-js-modal-btn');
|
|
10
|
+
this.modalVisibleInMilliseconds = context.getAttribute('data-show-modal-time') * 1000;
|
|
11
|
+
|
|
12
|
+
// Create modal instance
|
|
13
|
+
this.modal = new Modal(this.context);
|
|
14
|
+
|
|
15
|
+
// Create timeout instance
|
|
16
|
+
this.timeout = new Timeout(this.context, this.sessionExpiryEndpoint, this.initialExpiryTime, true);
|
|
17
|
+
|
|
18
|
+
this.bindEventListeners();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
bindEventListeners() {
|
|
22
|
+
window.onload = this.startTimeout();
|
|
23
|
+
window.addEventListener('keydown', this.escToClose.bind(this));
|
|
24
|
+
this.continueButton.addEventListener('click', this.closeModalAndRestartTimeout.bind(this));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
startTimeout() {
|
|
28
|
+
clearTimeout(this.showModalTimeout);
|
|
29
|
+
if (this.initialExpiryTime) {
|
|
30
|
+
this.expiryTimeInMilliseconds = this.timeout.convertTimeToMilliSeconds(this.initialExpiryTime);
|
|
31
|
+
} else {
|
|
32
|
+
// For demo purposes
|
|
33
|
+
this.expiryTimeInMilliseconds = 60000;
|
|
34
|
+
}
|
|
35
|
+
this.showModalTimeout = setTimeout(
|
|
36
|
+
this.openModalAndStartCountdown.bind(this),
|
|
37
|
+
this.expiryTimeInMilliseconds - this.modalVisibleInMilliseconds,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async openModalAndStartCountdown() {
|
|
42
|
+
const modalWillOpen = await this.timeout.hasExpiryTimeResetInAnotherTab();
|
|
43
|
+
if (modalWillOpen && !this.modal.isDialogOpen()) {
|
|
44
|
+
this.modal.openDialog();
|
|
45
|
+
this.timeout.startUiCountdown();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
closeModalAndRestartTimeout() {
|
|
50
|
+
if (this.modal.isDialogOpen()) {
|
|
51
|
+
this.modal.closeDialog();
|
|
52
|
+
}
|
|
53
|
+
this.timeout.restartTimeout();
|
|
54
|
+
this.startTimeout();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
escToClose(event) {
|
|
58
|
+
if (this.modal.isDialogOpen() && event.keyCode === 27) {
|
|
59
|
+
this.closeModalAndRestartTimeout();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{% from "components/panel/_macro.njk" import onsPanel %}
|
|
2
|
+
{% macro onsTimeoutPanel(params) %}
|
|
3
|
+
{% call onsPanel({
|
|
4
|
+
"id": params.id,
|
|
5
|
+
"classes": "ons-js-panel-with-countdown",
|
|
6
|
+
"type": "warn",
|
|
7
|
+
"attributes": {
|
|
8
|
+
"data-redirect-url": params.redirectUrl,
|
|
9
|
+
"data-server-session-expires-at": params.sessionExpiresAt,
|
|
10
|
+
"data-server-session-expiry-endpoint": params.serverSessionExpiryEndpoint,
|
|
11
|
+
"data-countdown-text": params.countdownText,
|
|
12
|
+
"data-countdown-expired-text": params.countdownExpiredText,
|
|
13
|
+
"data-minutes-text-singular": params.minutesTextSingular,
|
|
14
|
+
"data-minutes-text-plural": params.minutesTextPlural,
|
|
15
|
+
"data-seconds-text-singular": params.secondsTextSingular,
|
|
16
|
+
"data-seconds-text-plural": params.secondsTextPlural,
|
|
17
|
+
"data-full-stop": params.endWithFullStop,
|
|
18
|
+
"aria-describedby": "timeout-time-remaining"
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
%}
|
|
22
|
+
<noscript><p class="ons-js-nojs-text">{{ params.nojsText }}</p></noscript>
|
|
23
|
+
<p class="ons-js-timeout-timer" aria-hidden="true" aria-relevant="additions"></p>
|
|
24
|
+
<p class="ons-js-timeout-timer-acc ons-u-vh" role="status" id="timeout-time-remaining"></p>
|
|
25
|
+
{% endcall %}
|
|
26
|
+
{% endmacro %}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import domready from '../../js/domready';
|
|
2
|
+
|
|
3
|
+
async function timeoutPanels() {
|
|
4
|
+
const panels = [...document.querySelectorAll('.ons-js-panel-with-countdown')];
|
|
5
|
+
|
|
6
|
+
if (panels.length) {
|
|
7
|
+
const Timeout = (await import('../../js/timeout')).default;
|
|
8
|
+
|
|
9
|
+
panels.forEach(context => {
|
|
10
|
+
let url = context.getAttribute('data-server-session-expiry-endpoint');
|
|
11
|
+
let time = context.getAttribute('data-server-session-expires-at');
|
|
12
|
+
new Timeout(context, url, time, false, true);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
domready(timeoutPanels);
|