1 <% export("cbi_apply_widget", function(redirect_ok, rollback_token) -%>
2 <script type="text/javascript">//<![CDATA[
4 uci_apply_auth = { sid: '<%=luci.dispatcher.context.authsession%>', token: '<%=token%>' },
5 uci_apply_rollback = <%=math.max(luci.config and luci.config.apply and luci.config.apply.rollback or 30, 30)%>,
6 uci_apply_holdoff = <%=math.max(luci.config and luci.config.apply and luci.config.apply.holdoff or 4, 1)%>,
7 uci_apply_timeout = <%=math.max(luci.config and luci.config.apply and luci.config.apply.timeout or 5, 1)%>,
8 uci_apply_display = <%=math.max(luci.config and luci.config.apply and luci.config.apply.display or 1.5, 1)%>,
9 uci_confirm_auth = <% if rollback_token then %>{ token: '<%=rollback_token%>' }<% else %>null<% end %>,
10 was_xhr_poll_running = false;
12 function uci_status_message(type, content) {
14 var message = showModal('', '');
16 message.classList.add('alert-message');
17 DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/));
20 message.innerHTML = content;
22 if (!was_xhr_poll_running) {
23 was_xhr_poll_running = XHR.running();
30 if (was_xhr_poll_running)
35 function uci_rollback(checked) {
37 uci_status_message('warning spinning',
38 '<p><%:Failed to confirm apply within %ds, waiting for rollback…%></p>'.format(uci_apply_rollback));
40 var call = function(r, data, duration) {
41 if (r.status === 204) {
42 uci_status_message('warning',
43 '<h4><%:Configuration has been rolled back!%></h4>' +
44 '<p><%:The device could not be reached within %d seconds after applying the pending changes, which caused the configuration to be rolled back for safety reasons. If you believe that the configuration changes are correct nonetheless, proceed by applying anyway. Alternatively, you can dismiss this warning and edit changes before attempting to apply again, or revert all pending changes to keep the currently working configuration state.%></p>'.format(uci_apply_rollback) +
45 '<div class="right">' +
46 '<input type="button" class="btn" onclick="uci_status_message(false)" value="<%:Dismiss%>" /> ' +
47 '<input type="button" class="btn cbi-button-action important" onclick="uci_revert()" value="<%:Revert changes%>" /> ' +
48 '<input type="button" class="btn cbi-button-negative important" onclick="uci_apply(false)" value="<%:Apply anyway%>" />' +
54 var delay = isNaN(duration) ? 0 : Math.max(1000 - duration, 0);
55 window.setTimeout(function() {
56 xhr.post('<%=url("admin/uci/confirm")%>', uci_apply_auth, call, uci_apply_timeout * 1000);
63 uci_status_message('warning',
64 '<h4><%:Device unreachable!%></h4>' +
65 '<p><%:Could not regain access to the device after applying the configuration changes. You might need to reconnect if you modified network related settings such as the IP address or wireless security credentials.%></p>');
69 function uci_confirm(checked, deadline) {
73 uci_status_message('notice');
75 var call = function(r, data, duration) {
76 if (Date.now() >= deadline) {
77 window.clearTimeout(tt);
78 uci_rollback(checked);
81 else if (r && (r.status === 200 || r.status === 204)) {
82 var indicator = document.querySelector('.uci_change_indicator');
83 if (indicator) indicator.style.display = 'none';
85 uci_status_message('notice', '<p><%:Configuration has been applied.%></p>');
87 window.clearTimeout(tt);
88 window.setTimeout(function() {
89 <% if redirect_ok then -%>
90 location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
92 window.location = window.location.href.split('#')[0];
94 }, uci_apply_display * 1000);
99 var delay = isNaN(duration) ? 0 : Math.max(1000 - duration, 0);
100 window.setTimeout(function() {
101 xhr.post('<%=url("admin/uci/confirm")%>', uci_confirm_auth, call, uci_apply_timeout * 1000);
105 var tick = function() {
106 var now = Date.now();
108 uci_status_message('notice spinning',
109 '<p><%:Waiting for configuration to be applied… %ds%></p>'.format(Math.max(Math.floor((deadline - Date.now()) / 1000), 0)));
114 tt = window.setTimeout(tick, 1000 - (now - ts));
120 /* wait a few seconds for the settings to become effective */
121 window.setTimeout(call, Math.max(uci_apply_holdoff * 1000 - ((ts + uci_apply_rollback * 1000) - deadline), 1));
124 function uci_apply(checked) {
125 uci_status_message('notice spinning', '<p><%:Starting configuration apply…%></p>');
127 xhr.post('<%=url("admin/uci")%>/' + (checked ? 'apply_rollback' : 'apply_unchecked'), uci_apply_auth, function(r, tok) {
128 if (r.status === (checked ? 200 : 204)) {
129 if (checked && tok !== null && typeof(tok) === 'object' && typeof(tok.token) === 'string')
130 uci_confirm_auth = tok;
132 uci_confirm(checked, Date.now() + uci_apply_rollback * 1000);
134 else if (checked && r.status === 204) {
135 uci_status_message('notice', '<p><%:There are no changes to apply.%></p>');
136 window.setTimeout(function() {
137 <% if redirect_ok then -%>
138 location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
140 uci_status_message(false);
142 }, uci_apply_display * 1000);
145 uci_status_message('warning', '<p><%_Apply request failed with status <code>%h</code>%></p>'.format(r.responseText || r.statusText || r.status));
146 window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000);
151 function uci_revert() {
152 uci_status_message('notice spinning', '<p><%:Reverting configuration…%></p>');
154 xhr.post('<%=url("admin/uci/revert")%>', uci_apply_auth, function(r) {
155 if (r.status === 200) {
156 uci_status_message('notice', '<p><%:Changes have been reverted.%></p>');
157 window.setTimeout(function() {
158 <% if redirect_ok then -%>
159 location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
161 window.location = window.location.href.split('#')[0];
163 }, uci_apply_display * 1000);
166 uci_status_message('warning', '<p><%_Revert request failed with status <code>%h</code>%></p>'.format(r.statusText || r.status));
167 window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000);