1
0

quicksetup.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. Quick Setup Tour
  3. This script file contains all the required script
  4. for quick setup tour and walkthrough
  5. */
  6. //tourStepFactory generate a function that renders the steps in tourModal
  7. //Keys: {element, title, desc, tab, pos, scrollto, callback}
  8. // elements -> Element (selector) to focus on
  9. // tab -> Tab ID to switch pages
  10. // pos -> Where to display the tour modal, {topleft, topright, bottomleft, bottomright, center}
  11. // scrollto -> Element (selector) to scroll to, can be different from elements
  12. function adjustTourModalOverlayToElement(element){;
  13. if ($(element) == undefined || $(element).offset() == undefined){
  14. return;
  15. }
  16. $("#tourModalOverlay").css({
  17. "top": $(element).offset().top,
  18. "left": $(element).offset().left,
  19. "width": $(element).width(),
  20. "height": $(element).height(),
  21. });
  22. }
  23. var tourOverlayUpdateTicker;
  24. function tourStepFactory(config){
  25. return function(){
  26. //Check if this step require tab swap
  27. if (config.tab != undefined && config.tab != ""){
  28. //This tour require tab swap. call to openTabById
  29. openTabById(config.tab);
  30. }
  31. if (config.element == undefined){
  32. //No focused element in this step.
  33. $(".tourFocusObject").removeClass("tourFocusObject");
  34. $("#tourModal").addClass("nofocus");
  35. $("#tourModalOverlay").hide();
  36. }else{
  37. //Consists of focus element in this step
  38. $(".tourFocusObject").removeClass("tourFocusObject");
  39. $(config.element).addClass("tourFocusObject");
  40. $("#tourModal").removeClass("nofocus");
  41. $("#tourModalOverlay").hide();
  42. setTimeout(function(){
  43. //Match the overlay to element position and size
  44. $(window).off("resize").on("resize", function(){
  45. adjustTourModalOverlayToElement(config.element);
  46. });
  47. if (tourOverlayUpdateTicker != undefined){
  48. clearInterval(tourOverlayUpdateTicker);
  49. }
  50. tourOverlayUpdateTicker = setInterval(function(){
  51. adjustTourModalOverlayToElement(config.element);
  52. }, 300);
  53. adjustTourModalOverlayToElement(config.element);
  54. $("#tourModalOverlay").fadeIn();
  55. }, 300);
  56. }
  57. //Get the modal location of this step
  58. let showupZone = "center";
  59. if (config.pos != undefined){
  60. showupZone = config.pos
  61. }
  62. $("#tourModal").attr("position", showupZone);
  63. $("#tourModal .tourStepTitle").html(config.title);
  64. $("#tourModal .tourStepContent").html(config.desc);
  65. if (config.callback != undefined){
  66. config.callback();
  67. }
  68. //If there is a target element to scroll to
  69. console.log(config.scrollto);
  70. if (config.scrollto != undefined){
  71. $('html, body').animate({
  72. scrollTop: $(config.scrollto).offset().top - 100
  73. }, 500);
  74. }
  75. }
  76. }
  77. function startQuickStartTour(){
  78. if (currentQuickSetupClass == ""){
  79. msgbox("No selected setup service tour", false);
  80. return;
  81. }
  82. //Show the tour modal
  83. $("#tourModal").show();
  84. //Load the tour steps
  85. if (tourSteps[currentQuickSetupClass] == undefined || tourSteps[currentQuickSetupClass].length == 0){
  86. //This tour is not defined or empty
  87. let notFound = tourStepFactory({
  88. title: "😭 Tour not found",
  89. desc: "Seems you are requesting a tour that has not been developed yet. Check back on later!"
  90. });
  91. notFound();
  92. //Enable the finish button
  93. $("#tourModal .nextStepAvaible").hide();
  94. $("#tourModal .nextStepFinish").show();
  95. return;
  96. }else{
  97. tourSteps[currentQuickSetupClass][0]();
  98. }
  99. updateTourStepCount();
  100. //Disable the previous button
  101. if (tourSteps[currentQuickSetupClass].length == 1){
  102. //There are only 1 step in this tour
  103. $("#tourModal .nextStepAvaible").hide();
  104. $("#tourModal .nextStepFinish").show();
  105. }else{
  106. $("#tourModal .nextStepAvaible").show();
  107. $("#tourModal .nextStepFinish").hide();
  108. }
  109. $("#tourModal .tourStepButtonBack").addClass("disabled");
  110. //Disable body scroll and let tour steps to handle scrolling
  111. $("body").css("overflow-y","hidden");
  112. $("#mainmenu").css("pointer-events", "none");
  113. }
  114. function updateTourStepCount(){
  115. let tourlistLength = tourSteps[currentQuickSetupClass]==undefined?1:tourSteps[currentQuickSetupClass].length;
  116. $("#tourModal .tourStepCounter").text((currentQuickSetupTourStep + 1) + " / " + tourlistLength);
  117. }
  118. function nextTourStep(){
  119. //Add one to the tour steps
  120. currentQuickSetupTourStep++;
  121. if (currentQuickSetupTourStep == tourSteps[currentQuickSetupClass].length - 1){
  122. //Already the last step
  123. $("#tourModal .nextStepAvaible").hide();
  124. $("#tourModal .nextStepFinish").show();
  125. }
  126. updateTourStepCount();
  127. tourSteps[currentQuickSetupClass][currentQuickSetupTourStep]();
  128. if (currentQuickSetupTourStep > 0){
  129. $("#tourModal .tourStepButtonBack").removeClass("disabled");
  130. }
  131. }
  132. function previousTourStep(){
  133. if (currentQuickSetupTourStep > 0){
  134. currentQuickSetupTourStep--;
  135. }
  136. if (currentQuickSetupTourStep != tourSteps[currentQuickSetupClass].length - 1){
  137. //Not at the last step
  138. $("#tourModal .nextStepAvaible").show();
  139. $("#tourModal .nextStepFinish").hide();
  140. }
  141. if (currentQuickSetupTourStep == 0){
  142. //Cant go back anymore
  143. $("#tourModal .tourStepButtonBack").addClass("disabled");
  144. }
  145. updateTourStepCount();
  146. tourSteps[currentQuickSetupClass][currentQuickSetupTourStep]();
  147. }
  148. //End tour and reset everything
  149. function endTourFocus(){
  150. $(".tourFocusObject").removeClass("tourFocusObject");
  151. $(".serviceOption.active").removeClass("active");
  152. currentQuickSetupClass = "";
  153. currentQuickSetupTourStep = 0;
  154. $("#tourModal").hide();
  155. $("#tourModal .nextStepAvaible").show();
  156. $("#tourModal .nextStepFinish").hide();
  157. $("#tourModalOverlay").hide();
  158. if (tourOverlayUpdateTicker != undefined){
  159. clearInterval(tourOverlayUpdateTicker);
  160. }
  161. $("body").css("overflow-y","auto");
  162. $("#mainmenu").css("pointer-events", "auto");
  163. }
  164. var tourSteps = {
  165. //Homepage steps
  166. "homepage": [
  167. tourStepFactory({
  168. title: "🎉 Congratulation on your first site!",
  169. 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."
  170. }),
  171. tourStepFactory({
  172. title: "👉 Pointing domain DNS to Zoraxy's IP",
  173. desc: `Setup a DNS A Record that points your domain name to this Zoraxy instances public IP address. <br>
  174. Assume your public IP is 93.184.215.14, you should have an A record like this.
  175. <table class="ui celled collapsing basic striped table">
  176. <thead>
  177. <tr>
  178. <th>Name</th>
  179. <th>Type</th>
  180. <th>Value</th>
  181. </tr>
  182. </thead>
  183. <tbody>
  184. <tr>
  185. <td>yourdomain.com</td>
  186. <td>A</td>
  187. <td>93.184.215.14</td>
  188. </tr>
  189. </tbody>
  190. </table>
  191. <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.`,
  192. callback: function(){
  193. $.get("/api/acme/wizard?step=10", function(data){
  194. if (data.error == undefined){
  195. //Should return the public IP address from acme wizard
  196. //Overwrite the sample IP address
  197. let originalText = $("#tourModal .tourStepContent").html();
  198. originalText = originalText.split("93.184.215.14").join(data);
  199. $("#tourModal .tourStepContent").html(originalText);
  200. }
  201. })
  202. }
  203. }),
  204. tourStepFactory({
  205. title: "🏠 Setup Default Site",
  206. 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"`,
  207. tab: "setroot",
  208. element: "#setroot",
  209. pos: "bottomright"
  210. }),
  211. tourStepFactory({
  212. title: "🌐 Enable Static Web Server",
  213. 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.`,
  214. tab: "webserv",
  215. element: "#webserv",
  216. pos: "bottomright"
  217. }),
  218. tourStepFactory({
  219. title: "📤 Upload Static Website",
  220. 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.`,
  221. tab: "webserv",
  222. element: "#webserv",
  223. pos: "bottomright",
  224. scrollto: "#webserv_dirManager"
  225. }),
  226. tourStepFactory({
  227. title: "💡 Start Zoraxy HTTP listener",
  228. 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.`,
  229. tab: "status",
  230. element: $("#status .poweroptions"),
  231. pos: "bottomright",
  232. })
  233. ],
  234. //Subdomains tour steps
  235. "subdomain":[
  236. ],
  237. //TLS and ACME tour steps
  238. "tls":[
  239. ],
  240. }