mirror of
https://github.com/pi-hole/web.git
synced 2025-12-20 02:38:28 +00:00
Add progress reporting (#2829)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
/* global utils:false */
|
||||
/* global utils:false, NProgress:false */
|
||||
|
||||
function getParams() {
|
||||
var GETDict = {};
|
||||
@@ -104,6 +104,7 @@ function wrongPassword(isError = false, isSuccess = false, data = null) {
|
||||
|
||||
function doLogin(password) {
|
||||
wrongPassword(false, false, null);
|
||||
NProgress.start();
|
||||
utils.disableAll();
|
||||
$.ajax({
|
||||
url: "/api/auth",
|
||||
@@ -115,10 +116,12 @@ function doLogin(password) {
|
||||
})
|
||||
.done(function (data) {
|
||||
wrongPassword(false, true, data);
|
||||
NProgress.done();
|
||||
redirect();
|
||||
})
|
||||
.fail(function (data) {
|
||||
wrongPassword(true, false, data);
|
||||
NProgress.done();
|
||||
utils.enableAll();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -177,8 +177,8 @@ function saveSettings() {
|
||||
"Successfully saved and applied settings",
|
||||
""
|
||||
);
|
||||
// Reload page
|
||||
location.reload();
|
||||
// Show loading overlay
|
||||
utils.loadingOverlay(true);
|
||||
})
|
||||
.fail(function (data, exception) {
|
||||
utils.enableAll();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* This file is copyright under the latest version of the EUPL.
|
||||
* Please see LICENSE file for your rights under this license. */
|
||||
|
||||
/* global moment:false, apiFailure: false, updateFtlInfo: false */
|
||||
/* global moment:false, apiFailure: false, updateFtlInfo: false, NProgress:false */
|
||||
|
||||
$(function () {
|
||||
// CSRF protection for AJAX requests, this has to be configured globally
|
||||
@@ -630,6 +630,46 @@ function listAlert(type, items, data) {
|
||||
);
|
||||
}
|
||||
|
||||
// Callback function for the loading overlay timeout
|
||||
function loadingOverlayTimeoutCallback(reloadAfterTimeout) {
|
||||
// Try to ping FTL to see if it finished restarting
|
||||
$.ajax({
|
||||
url: "/api/info/login",
|
||||
method: "GET",
|
||||
cache: false,
|
||||
dataType: "json",
|
||||
})
|
||||
.done(function () {
|
||||
// FTL is running again, hide loading overlay
|
||||
NProgress.done();
|
||||
if (reloadAfterTimeout) {
|
||||
location.reload();
|
||||
} else {
|
||||
$(".wrapper").waitMe("hide");
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
// FTL is not running yet, try again in 500ms
|
||||
setTimeout(loadingOverlayTimeoutCallback, 500, reloadAfterTimeout);
|
||||
});
|
||||
}
|
||||
|
||||
function loadingOverlay(reloadAfterTimeout = false) {
|
||||
NProgress.start();
|
||||
$(".wrapper").waitMe({
|
||||
effect: "bounce",
|
||||
text: "Pi-hole is currently applying your changes...",
|
||||
bg: "rgba(0,0,0,0.7)",
|
||||
color: "#fff",
|
||||
maxSize: "",
|
||||
textPos: "vertical",
|
||||
});
|
||||
// Start checking for FTL status after 2 seconds
|
||||
setTimeout(loadingOverlayTimeoutCallback, 2000, reloadAfterTimeout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function that calls a function only if the page is currently visible. This is
|
||||
// useful to prevent unnecessary API calls when the page is not visible (e.g.
|
||||
// when the user is on another tab).
|
||||
@@ -700,6 +740,7 @@ window.utils = (function () {
|
||||
hexEncode: hexEncode,
|
||||
hexDecode: hexDecode,
|
||||
listsAlert: listAlert,
|
||||
loadingOverlay: loadingOverlay,
|
||||
setTimer: setTimer,
|
||||
setInter: setInter,
|
||||
};
|
||||
|
||||
@@ -78,6 +78,8 @@ is_authenticated = mg.request_info.is_authenticated
|
||||
html { background-color: #000; }
|
||||
</style>
|
||||
<? end ?>
|
||||
<script src="<?=pihole.fileversion('scripts/vendor/nprogress.min.js')?>"></script>
|
||||
<link rel="stylesheet" href="<?=pihole.fileversion('style/vendor/nprogress.min.css')?>">
|
||||
|
||||
<!-- Theme fonts -->
|
||||
<? if theme.name == 'lcars' then ?>
|
||||
@@ -118,3 +120,5 @@ if startsWith(scriptname, 'groups') then
|
||||
<script src="<?=pihole.fileversion('scripts/vendor/bootstrap-notify.min.js')?>"></script>
|
||||
<script src="<?=pihole.fileversion('style/vendor/font-awesome/js/all.min.js')?>"></script>
|
||||
<script src="<?=pihole.fileversion('scripts/pi-hole/js/utils.js')?>"></script>
|
||||
<script src="<?=pihole.fileversion('scripts/vendor/waitMe.min.js')?>"></script>
|
||||
<link rel="stylesheet" href="<?=pihole.fileversion('style/vendor/waitMe.min.css')?>">
|
||||
|
||||
128
scripts/vendor/nprogress.min.js
vendored
Normal file
128
scripts/vendor/nprogress.min.js
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
|
||||
* @license MIT */
|
||||
(function(e,n){"function"==typeof define&&define.amd?define(n):"object"==typeof exports?module.exports=n():e.NProgress=n()})(this,function(){
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
function e(e){return"object"==typeof HTMLElement?e instanceof HTMLElement:e&&"object"==typeof e&&1===e.nodeType&&"string"==typeof e.nodeName}function n(e,n,t){return e<n?n:e>t?t:e}
|
||||
/**
|
||||
* (Internal) converts a percentage (`0..1`) to a bar translateX
|
||||
* percentage (`-100%..0%`).
|
||||
*/function t(e){return 100*(-1+e)}
|
||||
/**
|
||||
* (Internal) returns the correct CSS for changing the bar's
|
||||
* position given an n percentage, and speed and ease from Settings
|
||||
*/function r(e,n,r){var i;return i="translate3d"===d.positionUsing?{transform:"translate3d("+t(e)+"%,0,0)"}:"translate"===d.positionUsing?{transform:"translate("+t(e)+"%,0)"}:{"margin-left":t(e)+"%"},i.transition="all "+n+"ms "+r,i}
|
||||
/**
|
||||
* (Internal) Queues a function to be executed.
|
||||
*/
|
||||
/**
|
||||
* (Internal) Determines if an element or space separated list of class names contains a class name.
|
||||
*/
|
||||
function i(e,n){var t="string"==typeof e?e:a(e);return t.indexOf(" "+n+" ")>=0}
|
||||
/**
|
||||
* (Internal) Adds a class to an element.
|
||||
*/function o(e,n){var t=a(e),r=t+n;i(t,n)||(
|
||||
// Trim the opening space.
|
||||
e.className=r.substring(1))}
|
||||
/**
|
||||
* (Internal) Removes a class from an element.
|
||||
*/function s(e,n){var t,r=a(e);i(e,n)&&(
|
||||
// Replace the class name.
|
||||
t=r.replace(" "+n+" "," "),
|
||||
// Trim the opening and closing spaces.
|
||||
e.className=t.substring(1,t.length-1))}
|
||||
/**
|
||||
* (Internal) Gets a space separated list of the class names on the element.
|
||||
* The list is wrapped with a single space on each end to facilitate finding
|
||||
* matches within the list.
|
||||
*/function a(e){return(" "+(e&&e.className||"")+" ").replace(/\s+/gi," ")}
|
||||
/**
|
||||
* (Internal) Removes an element from the DOM.
|
||||
*/function u(e){e&&e.parentNode&&e.parentNode.removeChild(e)}var c,l,f={version:"0.2.0"},d=f.settings={minimum:.08,easing:"linear",positionUsing:"",speed:200,trickle:!0,trickleSpeed:200,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};
|
||||
/**
|
||||
* Updates configuration.
|
||||
*
|
||||
* NProgress.configure({
|
||||
* minimum: 0.1
|
||||
* });
|
||||
*/
|
||||
f.configure=function(e){var n,t;for(n in e)t=e[n],void 0!==t&&e.hasOwnProperty(n)&&(d[n]=t);return this},
|
||||
/**
|
||||
* Last number.
|
||||
*/
|
||||
f.status=null,
|
||||
/**
|
||||
* Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
|
||||
*
|
||||
* NProgress.set(0.4);
|
||||
* NProgress.set(1.0);
|
||||
*/
|
||||
f.set=function(e){var t=f.isStarted();e=n(e,d.minimum,1),f.status=1===e?null:e;var i=f.render(!t),o=i.querySelector(d.barSelector),s=d.speed,a=d.easing;return i.offsetWidth,/* Repaint */
|
||||
p(function(n){
|
||||
// Set positionUsing if it hasn't already been set
|
||||
""===d.positionUsing&&(d.positionUsing=f.getPositioningCSS()),
|
||||
// Add transition
|
||||
m(o,r(e,s,a)),1===e?(
|
||||
// Fade out
|
||||
m(i,{transition:"none",opacity:1}),i.offsetWidth,/* Repaint */
|
||||
setTimeout(function(){m(i,{transition:"all "+s+"ms linear",opacity:0}),setTimeout(function(){f.remove(),n()},s)},s)):setTimeout(n,s)}),this},f.isStarted=function(){return"number"==typeof f.status},
|
||||
/**
|
||||
* Shows the progress bar.
|
||||
* This is the same as setting the status to 0%, except that it doesn't go backwards.
|
||||
*
|
||||
* NProgress.start();
|
||||
*
|
||||
*/
|
||||
f.start=function(){f.status||f.set(0);var e=function(){setTimeout(function(){f.status&&(f.trickle(),e())},d.trickleSpeed)};return d.trickle&&e(),this},
|
||||
/**
|
||||
* Hides the progress bar.
|
||||
* This is the *sort of* the same as setting the status to 100%, with the
|
||||
* difference being `done()` makes some placebo effect of some realistic motion.
|
||||
*
|
||||
* NProgress.done();
|
||||
*
|
||||
* If `true` is passed, it will show the progress bar even if its hidden.
|
||||
*
|
||||
* NProgress.done(true);
|
||||
*/
|
||||
f.done=function(e){return e||f.status?f.inc(.3+.5*Math.random()).set(1):this},
|
||||
/**
|
||||
* Increments by a random amount.
|
||||
*/
|
||||
f.inc=function(e){var t=f.status;return t?t>1?void 0:("number"!=typeof e&&(e=t>=0&&t<.2?.1:t>=.2&&t<.5?.04:t>=.5&&t<.8?.02:t>=.8&&t<.99?.005:0),t=n(t+e,0,.994),f.set(t)):f.start()},f.trickle=function(){return f.inc()},
|
||||
/**
|
||||
* Waits for all supplied jQuery promises and
|
||||
* increases the progress as the promises resolve.
|
||||
*
|
||||
* @param $promise jQUery Promise
|
||||
*/
|
||||
c=0,l=0,f.promise=function(e){return e&&"resolved"!==e.state()?(0===l&&f.start(),c++,l++,e.always(function(){l--,0===l?(c=0,f.done()):f.set((c-l)/c)}),this):this},
|
||||
/**
|
||||
* (Internal) renders the progress bar markup based on the `template`
|
||||
* setting.
|
||||
*/
|
||||
f.render=function(n){if(f.isRendered())return document.getElementById("nprogress");o(document.documentElement,"nprogress-busy");var r=document.createElement("div");r.id="nprogress",r.innerHTML=d.template;var i,s=r.querySelector(d.barSelector),a=n?"-100":t(f.status||0),c=e(d.parent)?d.parent:document.querySelector(d.parent);return m(s,{transition:"all 0 linear",transform:"translate3d("+a+"%,0,0)"}),d.showSpinner||(i=r.querySelector(d.spinnerSelector),i&&u(i)),c!=document.body&&o(c,"nprogress-custom-parent"),c.appendChild(r),r},
|
||||
/**
|
||||
* Removes the element. Opposite of render().
|
||||
*/
|
||||
f.remove=function(){s(document.documentElement,"nprogress-busy");var n=e(d.parent)?d.parent:document.querySelector(d.parent);s(n,"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&u(t)},
|
||||
/**
|
||||
* Checks if the progress bar is rendered.
|
||||
*/
|
||||
f.isRendered=function(){return!!document.getElementById("nprogress")},
|
||||
/**
|
||||
* Determine which positioning CSS rule to use.
|
||||
*/
|
||||
f.getPositioningCSS=function(){
|
||||
// Sniff on document.body.style
|
||||
var e=document.body.style,n="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";
|
||||
// Sniff prefixes
|
||||
return n+"Perspective"in e?"translate3d":n+"Transform"in e?"translate":"margin"};var p=function(){function e(){var t=n.shift();t&&t(e)}var n=[];return function(t){n.push(t),1==n.length&&e()}}(),m=function(){function e(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(e,n){return n.toUpperCase()})}function n(e){var n=document.body.style;if(e in n)return e;for(var t,r=i.length,o=e.charAt(0).toUpperCase()+e.slice(1);r--;)if(t=i[r]+o,t in n)return t;return e}function t(t){return t=e(t),o[t]||(o[t]=n(t))}function r(e,n,r){n=t(n),e.style[n]=r}var i=["Webkit","O","Moz","ms"],o={};return function(e,n){var t,i,o=arguments;if(2==o.length)for(t in n)i=n[t],void 0!==i&&n.hasOwnProperty(t)&&r(e,t,i);else r(e,o[1],o[2])}}();
|
||||
/**
|
||||
* (Internal) Applies css properties to an element, similar to the jQuery
|
||||
* css method.
|
||||
*
|
||||
* While this helper does assist with vendor prefixed property names, it
|
||||
* does not perform any manipulation of values prior to setting styles.
|
||||
*/return f});
|
||||
13
scripts/vendor/waitMe.min.js
vendored
Normal file
13
scripts/vendor/waitMe.min.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
waitMe - 1.19 [31.10.17]
|
||||
Author: vadimsva
|
||||
Github: https://github.com/vadimsva/waitMe
|
||||
*/
|
||||
(function(b){b.fn.waitMe=function(p){return this.each(function(){function y(){var a=f.attr("data-waitme_id");f.removeClass("waitMe_container").removeAttr("data-waitme_id");f.find('.waitMe[data-waitme_id="'+a+'"]').remove()}var f=b(this),z,g,e,r=!1,t="background-color",u="",q="",v,a,w,n={init:function(){function n(a){l.css({top:"auto",transform:"translateY("+a+"px) translateZ(0)"})}a=b.extend({effect:"bounce",text:"",bg:"rgba(255,255,255,0.7)",color:"#000",maxSize:"",waitTime:-1,textPos:"vertical",
|
||||
fontSize:"",source:"",onClose:function(){}},p);w=(new Date).getMilliseconds();v=b('<div class="waitMe" data-waitme_id="'+w+'"></div>');switch(a.effect){case "none":e=0;break;case "bounce":e=3;break;case "rotateplane":e=1;break;case "stretch":e=5;break;case "orbit":e=2;r=!0;break;case "roundBounce":e=12;break;case "win8":e=5;r=!0;break;case "win8_linear":e=5;r=!0;break;case "ios":e=12;break;case "facebook":e=3;break;case "rotation":e=1;t="border-color";break;case "timer":e=2;var c=b.isArray(a.color)?
|
||||
a.color[0]:a.color;u="border-color:"+c;break;case "pulse":e=1;t="border-color";break;case "progressBar":e=1;break;case "bouncePulse":e=3;break;case "img":e=1}""!==u&&(u+=";");if(0<e){if("img"===a.effect)q='<img src="'+a.source+'">';else for(var d=1;d<=e;++d)b.isArray(a.color)?(c=a.color[d],void 0==c&&(c="#000")):c=a.color,q=r?q+('<div class="waitMe_progress_elem'+d+'"><div style="'+t+":"+c+'"></div></div>'):q+('<div class="waitMe_progress_elem'+d+'" style="'+t+":"+c+'"></div>');g=b('<div class="waitMe_progress '+
|
||||
a.effect+'" style="'+u+'">'+q+"</div>")}a.text&&(c=b.isArray(a.color)?a.color[0]:a.color,z=b('<div class="waitMe_text" style="color:'+c+";"+(""!=a.fontSize?"font-size:"+a.fontSize:"")+'">'+a.text+"</div>"));var k=f.find("> .waitMe");k&&k.remove();c=b('<div class="waitMe_content '+a.textPos+'"></div>');c.append(g,z);v.append(c);"HTML"==f[0].tagName&&(f=b("body"));f.addClass("waitMe_container").attr("data-waitme_id",w).append(v);k=f.find("> .waitMe");var l=f.find(".waitMe_content");k.css({background:a.bg});
|
||||
""!==a.maxSize&&"none"!=a.effect&&(c=g.outerHeight(),g.outerWidth(),"img"===a.effect?(g.css({height:a.maxSize+"px"}),g.find(">img").css({maxHeight:"100%"}),l.css({marginTop:-l.outerHeight()/2+"px"})):a.maxSize<c&&("stretch"==a.effect?(g.css({height:a.maxSize+"px",width:a.maxSize+"px"}),g.find("> div").css({margin:"0 5%"})):(c=a.maxSize/c-.2,d="-50%","roundBounce"==a.effect?(d="-75%",a.text&&(d="75%")):"win8"==a.effect||"timer"==a.effect||"orbit"==a.effect?(d="-20%",a.text&&(d="20%")):"ios"==a.effect&&
|
||||
(d="-15%",a.text&&(d="15%")),"rotation"==a.effect&&a.text&&(d="75%"),g.css({transform:"scale("+c+") translateX("+d+")",whiteSpace:"nowrap"}))));l.css({marginTop:-l.outerHeight()/2+"px"});if(f.outerHeight()>b(window).height()){c=b(window).scrollTop();var h=l.outerHeight(),m=f.offset().top,x=f.outerHeight();d=c-m+b(window).height()/2;0>d&&(d=Math.abs(d));0<=d-h&&d+h<=x?m-c>b(window).height()/2&&(d=h):d=c>m+x-h?c-m-h:c-m+h;n(d);b(document).scroll(function(){var a=b(window).scrollTop()-m+b(window).height()/
|
||||
2;0<=a-h&&a+h<=x&&n(a)})}0<a.waitTime&&setTimeout(function(){y()},a.waitTime);k.on("destroyed",function(){if(a.onClose&&b.isFunction(a.onClose))a.onClose(f);k.trigger("close",{el:f})});b.event.special.destroyed={remove:function(a){a.handler&&a.handler()}};return k},hide:function(){y()}};if(n[p])return n[p].apply(this,Array.prototype.slice.call(arguments,1));if("object"===typeof p||!p)return n.init.apply(this,arguments)})};b(window).on("load",function(){b("body.waitMe_body").addClass("hideMe");setTimeout(function(){b("body.waitMe_body").find(".waitMe_container:not([data-waitme_id])").remove();
|
||||
b("body.waitMe_body").removeClass("waitMe_body hideMe")},200)})})(jQuery);
|
||||
1
style/vendor/nprogress.min.css
vendored
Normal file
1
style/vendor/nprogress.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0,-4px);-ms-transform:rotate(3deg) translate(0,-4px);transform:rotate(3deg) translate(0,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
|
||||
6
style/vendor/waitMe.min.css
vendored
Normal file
6
style/vendor/waitMe.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user