1 <% export("cbi_apply_widget", function(redirect_ok) -%>
2 <style type="text/css">
3 .alert-message.notice {
4 background: linear-gradient(#fff 0%, #eee 100%);
13 background: rgba(0, 0, 0, 0.7);
18 #cbi_apply_overlay .alert-message {
29 #cbi_apply_overlay .alert-message > h4,
30 #cbi_apply_overlay .alert-message > p,
31 #cbi_apply_overlay .alert-message > div {
35 #cbi_apply_overlay .alert-message > img {
40 body.apply-overlay-active {
45 body.apply-overlay-active #cbi_apply_overlay {
50 <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
51 <script type="text/javascript">//<![CDATA[
53 uci_apply_auth = { sid: '<%=luci.dispatcher.context.authsession%>', token: '<%=token%>' },
54 uci_apply_rollback = <%=math.max(luci.config and luci.config.apply and luci.config.apply.rollback or 30, 30)%>,
55 uci_apply_holdoff = <%=math.max(luci.config and luci.config.apply and luci.config.apply.holdoff or 4, 1)%>,
56 uci_apply_timeout = <%=math.max(luci.config and luci.config.apply and luci.config.apply.timeout or 5, 1)%>,
57 uci_apply_display = <%=math.max(luci.config and luci.config.apply and luci.config.apply.display or 1.5, 1)%>;
59 function uci_status_message(type, content) {
60 var overlay = document.getElementById('cbi_apply_overlay') || document.body.appendChild(E('<div id="cbi_apply_overlay"><div class="alert-message"></div></div>')),
61 message = overlay.querySelector('.alert-message');
63 if (message && type) {
64 if (!message.classList.contains(type)) {
65 message.classList.remove('notice');
66 message.classList.remove('warning');
67 message.classList.add(type);
71 message.innerHTML = content;
73 document.body.classList.add('apply-overlay-active');
76 document.body.classList.remove('apply-overlay-active');
80 function uci_rollback(checked) {
82 uci_status_message('warning',
83 '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
84 '<%:Failed to confirm apply within %ds, waiting for rollback…%>'.format(uci_apply_rollback));
86 var call = function(r) {
87 if (r.status === 204) {
88 uci_status_message('warning',
89 '<h4><%:Configuration has been rolled back!%></h4>' +
90 '<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, perform an unchecked configuration apply. 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) +
91 '<div class="right">' +
92 '<input type="button" class="btn" onclick="uci_status_message(false)" value="<%:Dismiss%>" /> ' +
93 '<input type="button" class="btn" onclick="uci_revert()" value="<%:Revert changes%>" /> ' +
94 '<input type="button" class="btn danger" onclick="uci_apply(false)" value="<%:Apply unchecked%>" />' +
100 xhr.post('<%=url("admin/uci/confirm")%>', uci_apply_auth, call, uci_apply_timeout * 1000);
106 uci_status_message('warning',
107 '<h4><%:Device unreachable!%></h4>' +
108 '<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>');
112 function uci_confirm(checked, deadline) {
116 uci_status_message('notice');
118 var call = function(r) {
119 if (Date.now() >= deadline) {
120 uci_rollback(checked);
123 else if (r && (r.status === 200 || r.status === 204)) {
124 var indicator = document.querySelector('.uci_change_indicator');
125 if (indicator) indicator.style.display = 'none';
127 uci_status_message('notice', '<%:Configuration has been applied.%>');
129 window.clearTimeout(tt);
130 window.setTimeout(function() {
131 <% if redirect_ok then -%>
132 location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
134 window.location = window.location.href.split('#')[0];
136 }, uci_apply_display * 1000);
141 xhr.post('<%=url("admin/uci/confirm")%>', uci_apply_auth, call, uci_apply_timeout * 1000);
144 var tick = function() {
145 var now = Date.now();
147 uci_status_message('notice',
148 '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
149 '<%:Waiting for configuration to get applied… %ds%>'.format(Math.max(Math.floor((deadline - Date.now()) / 1000), 0)));
154 tt = window.setTimeout(tick, 1000 - (now - ts));
160 /* wait a few seconds for the settings to become effective */
161 window.setTimeout(call, Math.max(uci_apply_holdoff * 1000 - ((ts + uci_apply_rollback * 1000) - deadline), 1));
164 function uci_apply(checked) {
165 uci_status_message('notice',
166 '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
167 '<%:Starting configuration apply…%>');
169 xhr.post('<%=url("admin/uci")%>/' + (checked ? 'apply_rollback' : 'apply_unchecked'), uci_apply_auth, function(r) {
170 if (r.status === (checked ? 200 : 204)) {
171 uci_confirm(checked, Date.now() + uci_apply_rollback * 1000);
173 else if (checked && r.status === 204) {
174 uci_status_message('notice', '<%:There are no changes to apply.%>');
175 window.setTimeout(function() {
176 <% if redirect_ok then -%>
177 location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
179 uci_status_message(false);
181 }, uci_apply_display * 1000);
184 uci_status_message('warning', '<%_Apply request failed with status <code>%h</code>%>'.format(r.responseText || r.statusText || r.status));
185 window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000);
190 function uci_revert() {
191 uci_status_message('notice',
192 '<img src="<%=resource%>/icons/loading.gif" alt="" style="vertical-align:middle" /> ' +
193 '<%:Reverting configuration…%>');
195 xhr.post('<%=url("admin/uci/revert")%>', uci_apply_auth, function(r) {
196 if (r.status === 200) {
197 uci_status_message('notice', '<%:Changes have been reverted.%>');
198 window.setTimeout(function() {
199 <% if redirect_ok then -%>
200 location.href = decodeURIComponent('<%=luci.util.urlencode(redirect_ok)%>');
202 window.location = window.location.href.split('#')[0];
204 }, uci_apply_display * 1000);
207 uci_status_message('warning', '<%_Revert request failed with status <code>%h</code>%>'.format(r.statusText || r.status));
208 window.setTimeout(function() { uci_status_message(false); }, uci_apply_display * 1000);