|
@@ -6,20 +6,26 @@
|
|
|
*/
|
|
|
|
|
|
//tourStepFactory generate a function that renders the steps in tourModal
|
|
|
-//Keys: element, title, desc, tab, zone, callback
|
|
|
-// elements -> Elements to focus on
|
|
|
+//Keys: {element, title, desc, tab, pos, scrollto, callback}
|
|
|
+// elements -> Element (selector) to focus on
|
|
|
// tab -> Tab ID to switch pages
|
|
|
// pos -> Where to display the tour modal, {topleft, topright, bottomleft, bottomright, center}
|
|
|
+// scrollto -> Element (selector) to scroll to, can be different from elements
|
|
|
+function adjustTourModalOverlayToElement(element){;
|
|
|
+ if ($(element) == undefined || $(element).offset() == undefined){
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
-function adjustTourModalOverlayToElement(element){
|
|
|
$("#tourModalOverlay").css({
|
|
|
"top": $(element).offset().top,
|
|
|
"left": $(element).offset().left,
|
|
|
"width": $(element).width(),
|
|
|
"height": $(element).height(),
|
|
|
- })
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
+var tourOverlayUpdateTicker;
|
|
|
+
|
|
|
function tourStepFactory(config){
|
|
|
return function(){
|
|
|
//Check if this step require tab swap
|
|
@@ -38,17 +44,23 @@ function tourStepFactory(config){
|
|
|
$(".tourFocusObject").removeClass("tourFocusObject");
|
|
|
$(config.element).addClass("tourFocusObject");
|
|
|
$("#tourModal").removeClass("nofocus");
|
|
|
-
|
|
|
- //Match the overlay to element position and size
|
|
|
- $(window).off("resize").on("resize", function(){
|
|
|
+ $("#tourModalOverlay").hide();
|
|
|
+ setTimeout(function(){
|
|
|
+ //Match the overlay to element position and size
|
|
|
+ $(window).off("resize").on("resize", function(){
|
|
|
+ adjustTourModalOverlayToElement(config.element);
|
|
|
+ });
|
|
|
+ if (tourOverlayUpdateTicker != undefined){
|
|
|
+ clearInterval(tourOverlayUpdateTicker);
|
|
|
+ }
|
|
|
+ tourOverlayUpdateTicker = setInterval(function(){
|
|
|
+ adjustTourModalOverlayToElement(config.element);
|
|
|
+ }, 300);
|
|
|
adjustTourModalOverlayToElement(config.element);
|
|
|
- })
|
|
|
- adjustTourModalOverlayToElement(config.element);
|
|
|
- $("#tourModalOverlay").show();
|
|
|
+ $("#tourModalOverlay").fadeIn();
|
|
|
+ }, 300);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
//Get the modal location of this step
|
|
|
let showupZone = "center";
|
|
|
if (config.pos != undefined){
|
|
@@ -62,9 +74,116 @@ function tourStepFactory(config){
|
|
|
if (config.callback != undefined){
|
|
|
config.callback();
|
|
|
}
|
|
|
+
|
|
|
+ //If there is a target element to scroll to
|
|
|
+ console.log(config.scrollto);
|
|
|
+ if (config.scrollto != undefined){
|
|
|
+ $('html, body').animate({
|
|
|
+ scrollTop: $(config.scrollto).offset().top - 100
|
|
|
+ }, 500);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function startQuickStartTour(){
|
|
|
+ if (currentQuickSetupClass == ""){
|
|
|
+ msgbox("No selected setup service tour", false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //Show the tour modal
|
|
|
+ $("#tourModal").show();
|
|
|
+ //Load the tour steps
|
|
|
+ if (tourSteps[currentQuickSetupClass] == undefined || tourSteps[currentQuickSetupClass].length == 0){
|
|
|
+ //This tour is not defined or empty
|
|
|
+ let notFound = tourStepFactory({
|
|
|
+ title: "😭 Tour not found",
|
|
|
+ desc: "Seems you are requesting a tour that has not been developed yet. Check back on later!"
|
|
|
+ });
|
|
|
+ notFound();
|
|
|
+
|
|
|
+ //Enable the finish button
|
|
|
+ $("#tourModal .nextStepAvaible").hide();
|
|
|
+ $("#tourModal .nextStepFinish").show();
|
|
|
+ return;
|
|
|
+ }else{
|
|
|
+ tourSteps[currentQuickSetupClass][0]();
|
|
|
+ }
|
|
|
+
|
|
|
+ updateTourStepCount();
|
|
|
+
|
|
|
+ //Disable the previous button
|
|
|
+ if (tourSteps[currentQuickSetupClass].length == 1){
|
|
|
+ //There are only 1 step in this tour
|
|
|
+ $("#tourModal .nextStepAvaible").hide();
|
|
|
+ $("#tourModal .nextStepFinish").show();
|
|
|
+ }else{
|
|
|
+ $("#tourModal .nextStepAvaible").show();
|
|
|
+ $("#tourModal .nextStepFinish").hide();
|
|
|
+ }
|
|
|
+ $("#tourModal .tourStepButtonBack").addClass("disabled");
|
|
|
+
|
|
|
+ //Disable body scroll and let tour steps to handle scrolling
|
|
|
+ $("body").css("overflow-y","hidden");
|
|
|
+ $("#mainmenu").css("pointer-events", "none");
|
|
|
+}
|
|
|
+
|
|
|
+function updateTourStepCount(){
|
|
|
+ let tourlistLength = tourSteps[currentQuickSetupClass]==undefined?1:tourSteps[currentQuickSetupClass].length;
|
|
|
+ $("#tourModal .tourStepCounter").text((currentQuickSetupTourStep + 1) + " / " + tourlistLength);
|
|
|
+}
|
|
|
+
|
|
|
+function nextTourStep(){
|
|
|
+ //Add one to the tour steps
|
|
|
+ currentQuickSetupTourStep++;
|
|
|
+ if (currentQuickSetupTourStep == tourSteps[currentQuickSetupClass].length - 1){
|
|
|
+ //Already the last step
|
|
|
+ $("#tourModal .nextStepAvaible").hide();
|
|
|
+ $("#tourModal .nextStepFinish").show();
|
|
|
+ }
|
|
|
+ updateTourStepCount();
|
|
|
+ tourSteps[currentQuickSetupClass][currentQuickSetupTourStep]();
|
|
|
+ if (currentQuickSetupTourStep > 0){
|
|
|
+ $("#tourModal .tourStepButtonBack").removeClass("disabled");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+function previousTourStep(){
|
|
|
+ if (currentQuickSetupTourStep > 0){
|
|
|
+ currentQuickSetupTourStep--;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (currentQuickSetupTourStep != tourSteps[currentQuickSetupClass].length - 1){
|
|
|
+ //Not at the last step
|
|
|
+ $("#tourModal .nextStepAvaible").show();
|
|
|
+ $("#tourModal .nextStepFinish").hide();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (currentQuickSetupTourStep == 0){
|
|
|
+ //Cant go back anymore
|
|
|
+ $("#tourModal .tourStepButtonBack").addClass("disabled");
|
|
|
+ }
|
|
|
+ updateTourStepCount();
|
|
|
+ tourSteps[currentQuickSetupClass][currentQuickSetupTourStep]();
|
|
|
+}
|
|
|
+
|
|
|
+//End tour and reset everything
|
|
|
+function endTourFocus(){
|
|
|
+ $(".tourFocusObject").removeClass("tourFocusObject");
|
|
|
+ $(".serviceOption.active").removeClass("active");
|
|
|
+ currentQuickSetupClass = "";
|
|
|
+ currentQuickSetupTourStep = 0;
|
|
|
+ $("#tourModal").hide();
|
|
|
+ $("#tourModal .nextStepAvaible").show();
|
|
|
+ $("#tourModal .nextStepFinish").hide();
|
|
|
+ $("#tourModalOverlay").hide();
|
|
|
+ if (tourOverlayUpdateTicker != undefined){
|
|
|
+ clearInterval(tourOverlayUpdateTicker);
|
|
|
+ }
|
|
|
+ $("body").css("overflow-y","auto");
|
|
|
+ $("#mainmenu").css("pointer-events", "auto");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
var tourSteps = {
|
|
|
//Homepage steps
|
|
|
"homepage": [
|
|
@@ -73,7 +192,7 @@ var tourSteps = {
|
|
|
desc: "In this tour, you will be guided through the steps required to setup a basic static website using your own domain name with Zoraxy."
|
|
|
}),
|
|
|
tourStepFactory({
|
|
|
- title: "Pointing your domain's DNS to Zoraxy's IP",
|
|
|
+ title: "👉 Pointing domain DNS to Zoraxy's IP",
|
|
|
desc: `Setup a DNS A Record that points your domain name to this Zoraxy instances public IP address. <br>
|
|
|
Assume your public IP is 93.184.215.14, you should have an A record like this.
|
|
|
<table class="ui celled collapsing basic striped table">
|
|
@@ -93,14 +212,46 @@ var tourSteps = {
|
|
|
</tbody>
|
|
|
</table>
|
|
|
<br>If the IP of Zoraxy start from 192.168, you might want to use your router's public IP address and setup port forward for both port 80 and 443 as well.`,
|
|
|
-
|
|
|
+ callback: function(){
|
|
|
+ $.get("/api/acme/wizard?step=10", function(data){
|
|
|
+ if (data.error == undefined){
|
|
|
+ //Should return the public IP address from acme wizard
|
|
|
+ //Overwrite the sample IP address
|
|
|
+ let originalText = $("#tourModal .tourStepContent").html();
|
|
|
+ originalText = originalText.split("93.184.215.14").join(data);
|
|
|
+ $("#tourModal .tourStepContent").html(originalText);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
}),
|
|
|
tourStepFactory({
|
|
|
- title: "Setup Default Site",
|
|
|
- desc: `If you already have an apache or nginx web server running, use "Reverse Proxy Target". <br>Otherwise, pick "Internal Static Web Server" and click "Apply Change"`,
|
|
|
+ title: "🏠 Setup Default Site",
|
|
|
+ desc: `If you already have an apache or nginx web server running, use "Reverse Proxy Target" and enter your current web server IP address. <br>Otherwise, pick "Internal Static Web Server" and click "Apply Change"`,
|
|
|
tab: "setroot",
|
|
|
- element: $("#setroot"),
|
|
|
+ element: "#setroot",
|
|
|
+ pos: "bottomright"
|
|
|
+ }),
|
|
|
+ tourStepFactory({
|
|
|
+ title: "🌐 Enable Static Web Server",
|
|
|
+ desc: `Enable the static web server if it is not already enabled. Skip this step if you are using external web servers like Apache or Nginx.`,
|
|
|
+ tab: "webserv",
|
|
|
+ element: "#webserv",
|
|
|
pos: "bottomright"
|
|
|
+ }),
|
|
|
+ tourStepFactory({
|
|
|
+ title: "📤 Upload Static Website",
|
|
|
+ desc: `Upload your static website files (e.g. HTML files) to the web directory. If remote access is not avaible, you can also upload it with the web server file manager here.`,
|
|
|
+ tab: "webserv",
|
|
|
+ element: "#webserv",
|
|
|
+ pos: "bottomright",
|
|
|
+ scrollto: "#webserv_dirManager"
|
|
|
+ }),
|
|
|
+ tourStepFactory({
|
|
|
+ title: "💡 Start Zoraxy HTTP listener",
|
|
|
+ desc: `Start Zoraxy (if it is not already running) by pressing the "Start Service" button.<br>You should now be able to visit your domain and see the static web server contents show up in your browser.`,
|
|
|
+ tab: "status",
|
|
|
+ element: $("#status .poweroptions"),
|
|
|
+ pos: "bottomright",
|
|
|
})
|
|
|
],
|
|
|
|