disk_restore.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>File Properties</title>
  5. <meta name="mobile-web-app-capable" content="yes">
  6. <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"/>
  7. <meta charset="UTF-8">
  8. <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
  9. <script src="../../script/jquery.min.js"></script>
  10. <script src="../../script/semantic/semantic.min.js"></script>
  11. <script type="text/javascript" src="../../script/ao_module.js"></script>
  12. <style>
  13. .hidden{
  14. display:none;
  15. }
  16. .disabled{
  17. opacity: 0.5;
  18. pointer-events: none;
  19. }
  20. .colorblock{
  21. width: 20px;
  22. height: 20px;
  23. display: inline-block;
  24. vertical-align: bottom;
  25. margin-right: 12px;
  26. }
  27. .blue.colorblock{
  28. background-color: #52bdf2;
  29. }
  30. .grey.colorblock{
  31. background-color: #b9b9b9;
  32. }
  33. .yellow.colorblock{
  34. background-color: #e5e75c;
  35. }
  36. .ui.table tr td{
  37. border-top: 0px solid transparent !important;
  38. }
  39. .overlap.bar{
  40. position: absolute !important;
  41. top:0px;
  42. left: 0px;
  43. }
  44. .nointeract{
  45. pointer-events: none;
  46. user-select: none;
  47. }
  48. #restorableList{
  49. max-height: 300px;
  50. overflow-y: scroll;
  51. padding-right: 4px;
  52. }
  53. .timeleft{
  54. width: 30px;
  55. height: 30px;
  56. display: inline-block;
  57. user-select: none;
  58. vertical-align: baseline;
  59. margin-bottom: -10px;
  60. margin-right: 4px;
  61. }
  62. .closebtn{
  63. position: absolute;
  64. right: 4px;
  65. top: 4px;
  66. }
  67. </style>
  68. </head>
  69. <body>
  70. <br>
  71. <div class="ui container">
  72. <h3 class="ui header">
  73. Backup & Restore
  74. <div class="sub header">Show restore points for the selected virtual disk</div>
  75. </h3>
  76. <div class="ui divider"></div>
  77. <div id="error" class="ui red inverted segment hidden">
  78. <h4 class="ui header">
  79. <i class="remove icon"></i>
  80. <div class="content">
  81. List Restore Failed
  82. <div class="sub reason header" style="color: white;">Unknown Vroot paramter given</div>
  83. </div>
  84. </h4>
  85. </div>
  86. <div id="fileinfo" class="ui segment" style="display:none;">
  87. <h4 class="ui header">
  88. <div class="content">
  89. <span class="filename">No File Selected</span>
  90. <div class="sub header relpath">N/A</div>
  91. </div>
  92. </h4>
  93. <div class="ui divider"></div>
  94. <span class="restorePoint">N/A</span><br>
  95. <span class="deleteTime">N/A</span><br>
  96. <span class="deleteRemainingTime">N/A</span><br>
  97. <button class="circular ui icon basic small button closebtn" onclick='$("#fileinfo").slideUp("fast");'>
  98. <i class="icon remove"></i>
  99. </button>
  100. </div>
  101. <div id="restorableList" class="ui middle aligned divided list">
  102. <div class="item">
  103. <img class="ui mini image nointeract" src="../../img/system/file-notfound.svg">
  104. <div class="content">
  105. No Restorable File(s) for this virtual disk.
  106. </div>
  107. </div>
  108. </div>
  109. <div class="ui checkbox">
  110. <input type="checkbox" name="showhidden" autocomplete="false" onchange="toggleHiddenFiles(this.checked);">
  111. <label>Show hidden / cache files</label>
  112. </div>
  113. <div class="ui divider" style="margin-top: 8px; margin-bottom: 8px;"></div>
  114. <br>
  115. <button class="ui right floated button" onclick="ao_module_close();">Close</button>
  116. <br>
  117. </div>
  118. <br><br>
  119. <script>
  120. var vrootID = "";
  121. $(".ui.checkbox").checkbox();
  122. //Extract vroot id from the window hash
  123. if (window.location.hash.length > 1){
  124. vrootID = JSON.parse(decodeURIComponent(window.location.hash.substr(1)));
  125. if (vrootID.length >= 1){
  126. //At least 1 vroot is passed in
  127. listRestorableFiles(vrootID[0]);
  128. }else{
  129. $("#error").removeClass("hidden");
  130. }
  131. }else{
  132. $("#error").removeClass("hidden");
  133. }
  134. function showFileInfo(object){
  135. var filedata = $(object).attr("filedata");
  136. filedata = JSON.parse(decodeURIComponent(filedata));
  137. console.log(filedata);
  138. //Show information on page
  139. $("#fileinfo").find(".filename").text(filedata.Filename + ` (${ao_module_utils.formatBytes(filedata.Filesize, 2)})`);
  140. //Hide the filename in relpath
  141. var shortenRelpath = filedata.RelpathOnDisk.split("/");
  142. shortenRelpath.pop();
  143. shortenRelpath = shortenRelpath.join("/") + "/";
  144. $("#fileinfo").find(".relpath").text(shortenRelpath);
  145. $("#fileinfo").find(".deleteTime").text("Delete Time: " + timeConverter(filedata.DeleteTime));
  146. $("#fileinfo").find(".restorePoint").text("Restore Location: " + (filedata.RestorePoint));
  147. $("#fileinfo").find(".deleteRemainingTime").text("Complete Delete in: " + secondsToHms(filedata.RemainingTime));
  148. $("#fileinfo").slideDown('fast');
  149. }
  150. function secondsToHms(d) {
  151. d = Number(d);
  152. var h = Math.floor(d / 3600);
  153. var m = Math.floor(d % 3600 / 60);
  154. var s = Math.floor(d % 3600 % 60);
  155. var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
  156. var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes") : "";
  157. return hDisplay + mDisplay;
  158. }
  159. function timeConverter(UNIX_timestamp){
  160. var a = new Date(UNIX_timestamp * 1000);
  161. var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  162. var year = a.getFullYear();
  163. var month = months[a.getMonth()];
  164. var date = a.getDate();
  165. var hour = a.getHours();
  166. var min = a.getMinutes();
  167. var sec = a.getSeconds();
  168. var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ;
  169. return time;
  170. }
  171. function toggleHiddenFiles(status=undefined){
  172. if (status == undefined){
  173. $(".hiddenfile").slideToggle("fast");
  174. }else if (status == true){
  175. $(".hiddenfile").slideDown("fast");
  176. }else if (status == false){
  177. $(".hiddenfile").slideUp("fast");
  178. }
  179. }
  180. function listRestorableFiles(rootID){
  181. $.ajax({
  182. url: "/system/backup/listRestorable",
  183. data: {vroot: rootID},
  184. success: function(data){
  185. if (data.error !== undefined){
  186. $("#error").find(".reason").texxt(data.error);
  187. }else{
  188. //Sort the result by latest first
  189. data.RestorableFiles.sort(function(a, b) {
  190. return b.DeleteTime - a.DeleteTime;
  191. });
  192. //Display the result
  193. $("#restorableList").html("");
  194. data.RestorableFiles.forEach(fileObject => {
  195. let thisFileData = encodeURIComponent(JSON.stringify(fileObject));
  196. var timerIcon = "100.svg";
  197. if (fileObject.RemainingTime < 75600){
  198. timerIcon = "87_5.svg"
  199. }else if (fileObject.RemainingTime < 64800){
  200. timerIcon = "75.svg"
  201. }else if (fileObject.RemainingTime < 54000){
  202. timerIcon = "62_5.svg"
  203. }else if (fileObject.RemainingTime < 43200){
  204. timerIcon = "50.svg"
  205. }else if (fileObject.RemainingTime < 32400){
  206. timerIcon = "37_5.svg"
  207. }else if (fileObject.RemainingTime < 21600){
  208. timerIcon = "25.svg"
  209. }else if (fileObject.RemainingTime < 10800){
  210. timerIcon = "12_5.svg"
  211. }else if (fileObject.RemainingTime < 7200){
  212. timerIcon = "0.svg"
  213. }
  214. var deleteTimeLeftHumanReadable = secondsToHms(fileObject.RemainingTime);
  215. var fileIcon = "../../img/system/file-restore.svg";
  216. var isHidden = "";
  217. if (fileObject.IsHidden == true){
  218. fileIcon = "../../img/system/file-restore-hidden.svg";
  219. isHidden = "hiddenfile";
  220. }
  221. $("#restorableList").append(`<div class="item restorableFile ${isHidden}" filedata="${thisFileData}">
  222. <div class="right floated content">
  223. <div class="timeleft" title="Will be deleted in ${deleteTimeLeftHumanReadable}">
  224. <img class="ui fluid image" src="../../img/icons/backup/${timerIcon}"/>
  225. </div>
  226. <div class="ui tiny button" onclick="showFileInfo(this.parentNode.parentNode)">Info</div>
  227. <div class="ui tiny green button">Restore</div>
  228. </div>
  229. <div class="content">
  230. <p style="word-break: break-all;"><img class="ui mini spaced image nointeract" src="${fileIcon}">
  231. ${fileObject.Filename}
  232. </p>
  233. </div>
  234. </div>`);
  235. });
  236. $(".hiddenfile").hide();
  237. }
  238. }
  239. })
  240. }
  241. </script>
  242. </body>
  243. </html>