diskmg.html 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. <html>
  2. <head>
  3. <meta charset="UTF-8">
  4. <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
  5. <script src="../../script/jquery.min.js"></script>
  6. <script type='text/javascript' src="../../semantic/semantic.min.js"></script>
  7. <script src="../../script/ao_module.js"></script>
  8. <title>Diskmg</title>
  9. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  10. <style>
  11. body{
  12. height: 100%;
  13. }
  14. .customFitted.item{
  15. padding-top:5px !important;
  16. padding-bottom:5px !important;
  17. }
  18. #diskListTable{
  19. max-height:250px !important;
  20. overflow-y: auto;
  21. }
  22. #diskVisualization{
  23. overflow-y:auto;
  24. }
  25. .diskPartTable{
  26. width:100%;
  27. border-bottom:1px solid #9c9c9c;
  28. overflow-x:hidden;
  29. }
  30. .sideblock{
  31. background-color:#f0f0f0;
  32. height:100px;
  33. width:100px;
  34. padding:8px;
  35. /*
  36. border-right:1px solid #9c9c9c;
  37. */
  38. font-size:90%;
  39. display:inline-block;
  40. }
  41. .partitionRepresentation{
  42. border:1px solid #e8e8e8;
  43. display:inline-block;
  44. height:100px;
  45. vertical-align: top;
  46. overflow:hidden;
  47. /*
  48. border-left:1px solid #6e6e6e;
  49. */
  50. cursor:pointer;
  51. }
  52. .partitionTopBar{
  53. background-color:#4287f5;
  54. width:100%;
  55. height:15px;
  56. margin-bottom:3px;
  57. }
  58. .partitionTopBar.unallocate{
  59. background-color:#1f1f1f;
  60. }
  61. .partitionTopBar.unmounted{
  62. background-color:#ab8a29;
  63. }
  64. .partitionDescription{
  65. padding-left:8px;
  66. padding:3px;
  67. }
  68. #rightClickMenu{
  69. position:absolute;
  70. }
  71. .selectable{
  72. cursor: pointer;
  73. }
  74. .selectable:hover{
  75. background-color:#f0f0f0 !important;
  76. }
  77. .focusedPart{
  78. background-color: #e3f0ff;
  79. }
  80. .disabled{
  81. background-color:#e6e6e6;
  82. color:#787878 !important;
  83. cursor:no-drop !important;
  84. }
  85. .funcmenu{
  86. position:fixed;
  87. top:10%;
  88. right:20%;
  89. left:20%;
  90. bottom:10%;
  91. overflow-y:auto;
  92. z-index:100;
  93. background-color:#f7f7f7;
  94. padding:12px;
  95. display:none;
  96. border: 1px solid #9c9c9c;
  97. }
  98. .functMenuDimmer{
  99. z-index:90;
  100. position:absolute;
  101. width:100%;
  102. height:100%;
  103. left:0px;
  104. top:0px;
  105. background:rgba(48,48,48,0.5);
  106. display:none;
  107. }
  108. .funcmenuBottom{
  109. position:absolute;
  110. width:100%;
  111. bottom:0px;
  112. left:0px;
  113. padding:12px;
  114. }
  115. </style>
  116. </head>
  117. <body>
  118. <div id="diskListTable" >
  119. <table class="ui celled striped unstackable table">
  120. <thead>
  121. <tr>
  122. <th>
  123. Volume
  124. </th>
  125. <th class="windowsonly" style="display:none;">
  126. Name
  127. </th>
  128. <th class="windowsonly" style="display:none;">
  129. Type
  130. </th>
  131. <th class="linuxonly" style="display:none;">
  132. Mount Point
  133. </th>
  134. <th>
  135. File System
  136. </th>
  137. <th>
  138. Capacity
  139. </th>
  140. <th class="windowsonly" style="display:none;">
  141. Free Space
  142. </th>
  143. <th class="windowsonly" style="display:none;">
  144. % Free
  145. </th>
  146. <th class="linuxonly" style="display:none;">
  147. Used Space
  148. </th>
  149. <th class="linuxonly" style="display:none;">
  150. % Used
  151. </th>
  152. </tr>
  153. </thead>
  154. <tbody id="diskInfoTable">
  155. <tr>
  156. <td class="collapsing">
  157. <i class="disk outline icon"></i>/dev/sda1
  158. </td>
  159. <td class="collapsing">/media/storage1</td>
  160. <td class="right aligned collapsing">NTFS</td>
  161. <td class="right aligned collapsing">64 GB</td>
  162. <td class="right aligned collapsing">12.5 GB</td>
  163. <td class="right aligned collapsing">19.7%</td>
  164. </tr>
  165. </tbody>
  166. </table>
  167. </div>
  168. <div id="diskVisualization">
  169. <div class="diskPartTable">
  170. <div class="sideblock">
  171. <i class="disk outline icon" style="margin-right:0px;font-weight: bold;"></i>
  172. <b style="font-weight: bold;">Drive 0</b><br>
  173. N/A
  174. </div><div class="partitionRepresentation" style="width:calc(100% - 150px);">
  175. <div class="partitionTopBar"></div>
  176. <div class="partitionDescription">
  177. Connecting to Virtual Disk Services
  178. </div>
  179. </div>
  180. </div>
  181. </div>
  182. <div id="rightClickMenu" class="ui vertical menu" style="display: none;">
  183. <div id="formatDisk" class="item selectable" onClick="toggleFormatInterface(this);">
  184. <i class="disk outline icon"></i> Format Disk
  185. </div>
  186. <div id="mtbtn" class="item selectable" onClick="toggleMount(this);">
  187. <i class="usb icon"></i> Mount
  188. </div>
  189. </div>
  190. <!-- Sections for functional menus-->
  191. <div id="formatOptions" class="funcmenu">
  192. <h2 class="ui header">
  193. <i class="red exclamation circle icon"></i>
  194. <div class="content">
  195. Format Disk
  196. <div class="sub header" style="font-weight:120%;color:red;">Warning! The format process will wipe all data from the selected partition.</div>
  197. </div>
  198. </h2>
  199. <div class="ui red message">
  200. <p>Format on any drive or partition will wipe all data within that drive or partition. Please make sure you have backup all necessary files and your drive / partition selection is correct.</p>
  201. </div>
  202. <div class="ui header">
  203. <i class="disk outline icon"></i>
  204. <div id="selectedDiskDisplay" class="content">
  205. /dev/sda1 (120 GB)
  206. </div>
  207. </div>
  208. <div class="ui form">
  209. <div class="field">
  210. <label>Target File System Format</label>
  211. <div class="ui checkboxes">
  212. <div class="ui radio checkbox">
  213. <input id="ext4" type="radio" name="format" checked>
  214. <label for="ext4">EXT4</label>
  215. </div>
  216. <div class="ui radio checkbox">
  217. <input id="ntfs" type="radio" name="format">
  218. <label for="ntfs">NTFS</label>
  219. </div>
  220. <div class="ui radio checkbox">
  221. <input id="vfat" type="radio" name="format">
  222. <label for="vfat">VFAT</label>
  223. </div>
  224. </div>
  225. </div>
  226. </div>
  227. <div class="funcmenuBottom" align="right">
  228. <button class="ui tiny negative button" onClick="formatThisDev();">Format</button>
  229. <button class="ui tiny button" onClick="hideAllFuncMenu();">Close</button>
  230. </div>
  231. </div>
  232. <div id="mountOptions" class="funcmenu">
  233. <div class="ui header">
  234. Disk Mount
  235. <div class="sub header">Select a mount point for this device</div>
  236. </div>
  237. <div id="mtptlist" class="ui segmented list" style="max-height:300px;overflow-y:auto;">
  238. <div class="mountpt item selectable userdefine" onclick="selectThis(this);">
  239. <p>User defined mount point</p>
  240. <div class="ui fluid mini input">
  241. <input id="userDefinedMountPoint" type="text" placeholder="/">
  242. </div>
  243. </div>
  244. </div>
  245. <div class="funcmenuBottom" align="right">
  246. <button class="ui tiny primary button" onClick="mountThisDev();">Mount</button>
  247. <button class="ui tiny button" onClick="hideAllFuncMenu();">Close</button>
  248. </div>
  249. </div>
  250. <!-- dimmers-->
  251. <div id="loaderUI" class="ui active dimmer" style="display:none;">
  252. <div class="ui text loader">Waiting for System Response<br>Do Not Close This Tab</div>
  253. </div>
  254. <div class="functMenuDimmer" onClick="hideAllFuncMenu();">
  255. </div>
  256. <script>
  257. var mode = "linux";
  258. var viewMode = "human"; //Accept {human / raw}
  259. var diskInformation; //Tmp variable for holding disk return results
  260. var displayScaleRatio = 0.1; //Maxium differential ratio, default 0.3, it means the minium disk will show as 70% screen width
  261. var fwmode = false;
  262. var formatPendingDevInfo;
  263. //Updates Nov 2020, added platform detection
  264. $.get(ao_root + "system/disk/diskmg/platform", function(data){
  265. if (data == "windows"){
  266. mode = "windows";
  267. }else{
  268. mode = "linux"
  269. }
  270. //Init data loading process
  271. initView();
  272. initPartitionTable();
  273. initMountPointList();
  274. })
  275. //Mount pt selection interface
  276. $(".mountpt").on('click',function(e){
  277. $(".selected").removeClass("selected");
  278. $(this).addClass("selected");
  279. });
  280. function hideAllFuncMenu(){
  281. $(".funcmenu").fadeOut('fast');
  282. $(".functMenuDimmer").fadeOut('fast');
  283. }
  284. function initMountPointList(){
  285. $.get(ao_root + "system/disk/diskmg/mpt", function(data){
  286. if (data == null){
  287. //On Windows
  288. return
  289. }
  290. data.forEach(mpt => {
  291. $("#mtptlist").prepend(`<div class="mountpt selectable item" style="cursor:pointer;" onclick="selectThis(this);" ondblclick="mountThisDev(this)">${mpt}</div>`)
  292. });
  293. });
  294. }
  295. function selectThis(object){
  296. $(".selected.selectable.item").removeClass('selected');
  297. $(object).addClass("selected");
  298. }
  299. function formatThisDev(){
  300. var targetFormat = $("input[name='format']:checked").attr("id");
  301. var targetDisk = formatPendingDevInfo;
  302. console.log("Formating Disk: " + targetDisk + " to " + targetFormat);
  303. if(targetFormat){
  304. $("#loaderUI").show();
  305. if (confirm("THIS OPERATION WILL WIPE ALL DATA ON /dev/" + targetDisk[0] + ". ARE YOU SURE?")){
  306. $("#formatOptions").fadeOut('fast');
  307. $(".functMenuDimmer").fadeOut('fast');
  308. console.log(ao_root + "system/disk/diskmg/format?dev=" + targetDisk[0] + "&format=" + targetFormat);
  309. $.ajax({
  310. url: ao_root + "system/disk/diskmg/format",
  311. data: {"dev": targetDisk[0], "format": targetFormat},
  312. method: "POST",
  313. success: function(data){
  314. if (data.error !== undefined){
  315. alert(data.error);
  316. }
  317. initView();
  318. initPartitionTable();
  319. $("#loaderUI").hide();
  320. }
  321. });
  322. }else{
  323. $("#loaderUI").hide();
  324. }
  325. }
  326. }
  327. function toggleFormatInterface(btnObject){
  328. if ($(btnObject).hasClass("disabled") == true){
  329. return;
  330. }
  331. $("#formatOptions").fadeIn('fast');
  332. $(".functMenuDimmer").fadeIn('fast');
  333. hideRightclickMenu();
  334. var diskInfo = $(".focusedPart").attr("metadata");
  335. diskInfo = ao_module_utils.attrToObject(diskInfo);
  336. formatPendingDevInfo = diskInfo;
  337. $("#selectedDiskDisplay").text(diskInfo[0] + " (" + bytesToSize(parseInt(diskInfo[5])) + ") ");
  338. }
  339. function mountThisDev(object=null){
  340. if (object !== null && !$(object).hasClass(".selected.item")){
  341. $(".selected").removeClass("selected");
  342. $(object).addClass("selected");
  343. }
  344. var selectedMpt = $(".selected.item");
  345. var mountPoint = $(selectedMpt).text().trim();
  346. if (selectedMpt.hasClass("userdefine")){
  347. var mountPoint = $("#userDefinedMountPoint").val();
  348. }
  349. $("#loaderUI").show();
  350. $("#mountOptions").fadeOut('fast');
  351. $(".functMenuDimmer").fadeOut('fast');
  352. var diskInfo = $(".focusedPart").attr("metadata");
  353. diskInfo = ao_module_utils.attrToObject(diskInfo);
  354. $.get(ao_root + "system/disk/diskmg/mount?dev=" + diskInfo[0] + "&format=" + diskInfo[2] + "&mnt=" + mountPoint,function(data){
  355. if (data.error != undefined){
  356. $("#loaderUI").hide();
  357. alert(data.error);
  358. return;
  359. }
  360. //Reload the UI
  361. initView();
  362. initPartitionTable();
  363. $("#loaderUI").hide();
  364. });
  365. }
  366. function toggleMount(btnObject){
  367. if ($(btnObject).hasClass("disabled") == true){
  368. return;
  369. }
  370. var diskInfo = $(".focusedPart").attr("metadata");
  371. diskInfo = ao_module_utils.attrToObject(diskInfo);
  372. if (diskInfo[3] == false){
  373. //Mount disk
  374. $("#mountOptions").fadeIn('fast');
  375. $(".functMenuDimmer").fadeIn('fast');
  376. }else{
  377. //Unmount disk
  378. var dev = diskInfo[0];
  379. var mnt = diskInfo[1];
  380. var format = diskInfo[2];
  381. hideRightclickMenu();
  382. $("#loaderUI").show();
  383. $.get(ao_root + "system/disk/diskmg/mount?dev=" + dev + "&format=" + format + "&mnt=" + mnt + "&umount=true",function(data){
  384. console.log(data);
  385. //Reload the UI
  386. initView();
  387. initPartitionTable();
  388. $("#loaderUI").hide();
  389. });
  390. }
  391. hideRightclickMenu();
  392. }
  393. function hideRightclickMenu(){
  394. $("#rightClickMenu").hide();
  395. }
  396. /*
  397. function openInFileExplorer(btnObject){
  398. if ($(btnObject).hasClass('disabled')){
  399. return;
  400. }
  401. var diskInfo = $(".focusedPart").attr("metadata");
  402. diskInfo = ao_module_utils.attrToObject(diskInfo);
  403. if (diskInfo[3] == true){
  404. //This disk is mounted
  405. var uid = Date.now();
  406. if (fwmode){
  407. ao_module_newfw("SystemAOB/functions/file_system/index.php?controlLv=2&dir=" + diskInfo[1],"Loading", "folder open outline",uid,1080,580,undefined,undefined,true,true);
  408. }else{
  409. window.open("../../functions/file_system/index.php?controlLv=2&dir=" + diskInfo[1]);
  410. }
  411. }
  412. hideRightclickMenu();
  413. }
  414. */
  415. function createEventHooks(){
  416. $(".partitionRepresentation").contextmenu(function(e){
  417. if (mode == "windows"){
  418. //Switch back to normal menu when under window mode
  419. return true;
  420. }
  421. var px = e.clientX;
  422. var py = e.clientY;
  423. var top = py - $("#rightClickMenu").height();
  424. if (ao_module_virtualDesktop){
  425. top -= 50;
  426. }
  427. $("#rightClickMenu").css({"left": px + "px", "top": top + "px"});
  428. $("#rightClickMenu").show();
  429. console.log(e.target);
  430. $(".focusedPart").removeClass("focusedPart");
  431. var partbody = $(e.target);
  432. if ($(e.target).parent().hasClass("partitionRepresentation")){
  433. //Clicked on the child instead.
  434. $(e.target).parent().addClass("focusedPart");
  435. partbody = $(e.target).parent();
  436. }else{
  437. //Click on the representation body.
  438. $(e.target).addClass("focusedPart");
  439. }
  440. //Create a custom context menu for the operation
  441. var partInfo = ao_module_utils.attrToObject(partbody.attr("metadata"));
  442. console.log(partInfo);
  443. if (partInfo[3] == true){
  444. //This disk is mounted. Provide unmount btn
  445. if (partInfo[1] == "/" || partInfo[1] == "/boot"){
  446. //No, you can't unmount root nor format it
  447. $("#mtbtn").addClass("disabled");
  448. $("#formatDisk").addClass("disabled");
  449. }else{
  450. $("#mtbtn").removeClass("disabled");
  451. $("#formatDisk").removeClass("disabled");
  452. }
  453. $("#mtbtn").html('<i class="usb icon"></i> Unmount');
  454. if (partInfo[1].substring(0,6) == "/media"){
  455. //This can be opened
  456. $("#openbtn").removeClass("disabled");
  457. }else{
  458. $("#openbtn").addClass("disabled");
  459. }
  460. }else{
  461. //This disk is not mounted. Provide mount btn
  462. $("#mtbtn").html('<i class="usb icon"></i> Mount Drive');
  463. $("#openbtn").addClass("disabled");
  464. $("#mtbtn").removeClass("disabled");
  465. $("#formatDisk").removeClass("disabled");
  466. }
  467. //Prevent browser menu from showing
  468. return false;
  469. });
  470. }
  471. function adjustPartitionViewHeight(){
  472. $("#diskVisualization").css("height",window.innerHeight - $("#diskListTable").height() - 120 + "px");
  473. }
  474. function initView(){
  475. if (mode == "windows"){
  476. $(".windowsonly").show();
  477. //Runing on top of Window Host
  478. $.get(ao_root + "system/disk/diskmg/view",function(data){
  479. $("#diskInfoTable").html("");
  480. if (data.error == undefined){
  481. for (var i = 0; i < data.length; i++){
  482. var thisDisk = data[i];
  483. var driveName = thisDisk[2];
  484. if (thisDisk[2] == "" && thisDisk[0] == "C:\\"){
  485. driveName = "Primary Drive";
  486. }else if (thisDisk[2] == ""){
  487. driveName = "Local Disk";
  488. }else if (driveName == undefined){
  489. driveName = "No Media"
  490. }
  491. if (thisDisk[3] == undefined){
  492. //Unknown File System
  493. thisDisk[3] = "N/A"
  494. }
  495. var cap = bytesToSize(thisDisk[6]);
  496. if (thisDisk[6] == undefined){
  497. cap = "N/A";
  498. }
  499. var free = bytesToSize(thisDisk[5]);
  500. if (thisDisk[5] == undefined){
  501. free = "N/A";
  502. }
  503. var perc = Math.round(thisDisk[5] / thisDisk[6] * 100);
  504. if (isNaN(perc)){
  505. perc = "0";
  506. }
  507. $("#diskInfoTable").append('<tr>\
  508. <td class="collapsing">\
  509. <i class="disk outline icon"></i>' + thisDisk[0] + '\
  510. </td>\
  511. <td class="">' + driveName + '</td>\
  512. <td class="collapsing">' + thisDisk[1] + '</td>\
  513. <td class="right aligned collapsing">' + thisDisk[3] + '</td>\
  514. <td class="right aligned collapsing">' + cap + '</td>\
  515. <td class="right aligned collapsing">' + free + '</td>\
  516. <td class="right aligned collapsing">' + perc + '%</td>\
  517. </tr>');
  518. }
  519. }
  520. });
  521. }else{
  522. //Runing on top of Linux Host
  523. $(".linuxonly").show();
  524. $.get(ao_root + "system/disk/diskmg/view",function(data){
  525. $("#diskInfoTable").html("");
  526. if (data.error == undefined){
  527. var disks = data[0]["blockdevices"];
  528. var partitions = data[1];
  529. for (var i = 0; i < disks.length; i++){
  530. var thisDisk = disks[i]["children"];
  531. if (thisDisk === undefined || thisDisk === null){
  532. let thisSize = disks[i]["size"] || 0;
  533. let thisPartitionID = disks[i]["name"] || "✖";
  534. let mountPoint = disks[i]["mountpoint"] || "[NO PARTITION]";
  535. $("#diskInfoTable").append('<tr>\
  536. <td class="collapsing">\
  537. <i class="disk outline icon"></i>' + thisPartitionID + '\
  538. </td>\
  539. <td class="">' + mountPoint + '</td>\
  540. <td class="right aligned collapsing"></td>\
  541. <td class="right aligned collapsing">' + bytesToSize(thisSize) + '</td>\
  542. <td class="right aligned collapsing">' + bytesToSize(0) + '</td>\
  543. <td class="right aligned collapsing"></td>\
  544. </tr>');
  545. continue;
  546. }
  547. for (var j =0; j < thisDisk.length; j++){
  548. var thisPartition = thisDisk[j];
  549. var mtPoint = thisPartition["mountpoint"];
  550. if (mtPoint === null){
  551. mtPoint = "Not Mounted";
  552. }
  553. //Get the filesystem from another command return results
  554. var disksFormats = data[1]["blockdevices"][i]["children"][j];
  555. var fstype = disksFormats["fstype"];
  556. if (fstype === null){
  557. fstype = "raw";
  558. }
  559. //console.log(disksFormats);
  560. //Read freesapce from the last command return results
  561. var freeSpacesRatio = "0%";
  562. for (var k =0; k < data[2].length; k++){
  563. if (data[2][k][5] == thisPartition["mountpoint"]){
  564. //This device is mounted at the same path as current partition. It should be this volume
  565. freeSpacesRatio = data[2][k][4];
  566. }
  567. }
  568. if (freeSpacesRatio === undefined){
  569. freeSpacesRatio = "0%";
  570. }
  571. var numericalFreeSpace = parseInt(freeSpacesRatio.replace("%","")) * thisPartition["size"] / 100;
  572. //Print the results to the interface
  573. //console.log(thisPartition);
  574. $("#diskInfoTable").append('<tr>\
  575. <td class="collapsing">\
  576. <i class="disk outline icon"></i>' + thisPartition["name"] + '\
  577. </td>\
  578. <td class="">' + mtPoint + '</td>\
  579. <td class="right aligned collapsing">' + fstype + '</td>\
  580. <td class="right aligned collapsing">' + bytesToSize(thisPartition["size"]) + '</td>\
  581. <td class="right aligned collapsing">' + bytesToSize(numericalFreeSpace) + '</td>\
  582. <td class="right aligned collapsing">' + freeSpacesRatio + '</td>\
  583. </tr>');
  584. }
  585. }
  586. }
  587. });
  588. }
  589. }
  590. function initPartitionTable(){
  591. if (mode == "windows"){
  592. $.get(ao_root + "system/disk/diskmg/view?partition=true",function(data){
  593. var disks = {};
  594. for(var i =0; i < data.length; i++){
  595. var thisPart = data[i];
  596. //var diskID = thisPart[9].replace(":","");
  597. var diskID = thisPart[0].replace(/\\+.+\\/,"");
  598. if (disks == undefined || disks[diskID] == undefined){
  599. disks[diskID] = {"partitionsTotalSize":thisPart[14],"partitionNames":[thisPart[16]],"partitionID":[ thisPart[9]],"partitionVolume":[thisPart[14]],"Type":[thisPart[5]],"Mounted":[thisPart[4]=="True"],"Format":[thisPart[12]]};
  600. }else{
  601. disks[diskID]["partitionsTotalSize"] = parseInt(disks[diskID]["partitionsTotalSize"]) + parseInt(thisPart[14]);
  602. disks[diskID]["partitionVolume"].push(thisPart[14]);
  603. disks[diskID]["partitionNames"].push(thisPart[16]);
  604. disks[diskID]["partitionID"].push(thisPart[9]);
  605. disks[diskID]["Type"].push(thisPart[5]);
  606. disks[diskID]["Format"].push(thisPart[12]);
  607. disks[diskID]["Mounted"].push(thisPart[4]=="True");
  608. }
  609. }
  610. diskInformation = JSON.parse(JSON.stringify(disks));
  611. drawDartitionTable();
  612. });
  613. }else{
  614. //This is a Linux Host
  615. $.get(ao_root + "system/disk/diskmg/view?partition=true",function(data){
  616. var disks = {};
  617. var diskInfo = data[0]["blockdevices"];
  618. for (var i =0; i < diskInfo.length; i++){
  619. let thisDisk = diskInfo[i];
  620. let diskID = thisDisk["name"];
  621. if (thisDisk["children"] === undefined || thisDisk["children"] === null){
  622. //This disk do not have any child. Assume a large read-only raw partition.
  623. let thisSize = thisDisk["size"] || 0;
  624. let thisPartitionID = thisDisk["name"] || "✖";
  625. disks[diskID] = {
  626. "partitionsTotalSize":thisSize,
  627. "partitionNames":[""],
  628. "partitionID":[thisPartitionID],
  629. "partitionVolume":[thisSize],
  630. "Type":[thisDisk["type"]],
  631. "Mounted":[thisDisk["mountpoint"] !== null],
  632. "Format":["raw"]
  633. };
  634. continue;
  635. }
  636. for (var j =0; j < thisDisk["children"].length;j++){
  637. var thisPart = thisDisk["children"][j];
  638. var disksFormats = data[1]["blockdevices"][i]["children"][j];
  639. if (disks == undefined || disks[diskID] == undefined){
  640. disks[diskID] = {
  641. "partitionsTotalSize":thisPart["size"],
  642. "partitionNames":[thisPart["mountpoint"]],
  643. "partitionID":[thisPart["name"]],
  644. "partitionVolume":[thisPart["size"]],
  645. "Type":[thisPart["type"]],
  646. "Mounted":[thisPart["mountpoint"] != ""],
  647. "Format":[disksFormats["fstype"]]
  648. };
  649. }else{
  650. disks[diskID]["partitionsTotalSize"] = parseInt(disks[diskID]["partitionsTotalSize"]) + parseInt(thisPart["size"]);
  651. disks[diskID]["partitionVolume"].push(thisPart["size"]);
  652. disks[diskID]["partitionNames"].push(thisPart["mountpoint"]);
  653. disks[diskID]["partitionID"].push(thisPart["name"]);
  654. disks[diskID]["Type"].push(thisPart["type"]);
  655. disks[diskID]["Format"].push(disksFormats["fstype"]);
  656. console.log(thisPart["name"], thisPart["mountpoint"]);
  657. disks[diskID]["Mounted"].push(thisPart["mountpoint"] !== "");
  658. }
  659. }
  660. }
  661. diskInformation = JSON.parse(JSON.stringify(disks));
  662. drawDartitionTable();
  663. });
  664. }
  665. }
  666. function drawDartitionTable(){
  667. var disks = JSON.parse(JSON.stringify(diskInformation));
  668. console.log(diskInformation);
  669. //Clear the old diskpart table
  670. $("#diskVisualization").html("");
  671. //Render the partition table
  672. var maxWidth = window.innerWidth * 0.96 - 200;
  673. var maxCapDisk = -1;
  674. var keys = [];
  675. for (key in disks){
  676. keys.push(key);
  677. var thisDiskSize = disks[key]["partitionsTotalSize"];
  678. if (thisDiskSize > maxCapDisk){
  679. maxCapDisk = parseInt(thisDiskSize);
  680. }
  681. }
  682. keys.sort();
  683. for (var i =0; i < keys.length; i++){
  684. var diskInfo = disks[keys[i]];
  685. var diskID = keys[i];
  686. var mountState = "Mounted";
  687. var shortenType = diskInfo["Type"][0].split(" ").shift();
  688. var thisMaxWidth = maxWidth - (1- (diskInfo["partitionsTotalSize"] / maxCapDisk)) * (window.innerWidth * displayScaleRatio);
  689. if (diskInfo["Mounted"].length == 1 && diskInfo["Mounted"][0] == false){
  690. mountState = "Unmounted";
  691. }else if(diskInfo["Mounted"].length > 1){
  692. mountState = "Mixed";
  693. }
  694. console.log(diskID,diskInfo["Mounted"]);
  695. //Append the disk info block
  696. $("#diskVisualization").append('<div class="diskPartTable">');
  697. $("#diskVisualization").append('<div class="sideblock">\
  698. <i class="disk outline icon" style="margin-right:0px;font-weight: bold;"></i>\
  699. <b style="font-weight: bold;">Drive ' + i + '</b><br>\
  700. ' + shortenType + '<br>\
  701. ' + bytesToSize(diskInfo["partitionsTotalSize"]) + '<br>\
  702. ' + mountState + '\
  703. </div>');
  704. var partitionIDs = diskInfo["partitionID"];
  705. for (var k =0; k < partitionIDs.length; k++){
  706. var thisWidth = thisMaxWidth * (parseInt(diskInfo["partitionVolume"][k]) / diskInfo["partitionsTotalSize"]);
  707. var topbarExtraClass = "";
  708. if (diskInfo["partitionVolume"][k] == 0){
  709. topbarExtraClass = " unallocate";
  710. }else if (diskInfo["partitionNames"][k] == "" && mode == "linux"){
  711. topbarExtraClass = " unmounted";
  712. diskInfo["partitionNames"][k] = "Not Mounted";
  713. if (diskInfo.Format.length == 1 && diskInfo.Format[0] == "raw"){
  714. topbarExtraClass = " unallocate"
  715. diskInfo["partitionNames"][k] = "Unallocated / Unpartitioned";
  716. }
  717. }else if (diskInfo["partitionNames"][k] == "" && mode == "windows"){
  718. //All viewable disks on Windows must be mounted
  719. if (diskInfo["partitionID"][0] == "C:"){
  720. diskInfo["partitionNames"][k] = "Primary Disk";
  721. }else{
  722. diskInfo["partitionNames"][k] = "Local Disk";
  723. }
  724. }
  725. $("#diskVisualization").append('<div class="partitionRepresentation" style="width:' + thisWidth + 'px;" metaData="\
  726. ' + ao_module_utils.objectToAttr([diskInfo["partitionID"][k],diskInfo["partitionNames"][k],diskInfo["Format"][k],diskInfo["Mounted"][k],diskInfo["Type"][k],diskInfo["partitionVolume"][k]]) + '">\
  727. <div class="partitionTopBar' + topbarExtraClass + '"></div>\
  728. <div class="partitionDescription">\
  729. ' + diskInfo["partitionNames"][k] +" (" + diskInfo["partitionID"][k] + ')<br>\
  730. ' + bytesToSize(parseInt(diskInfo["partitionVolume"][k])) + ' ' + diskInfo["Format"][k] + '<br>\
  731. </div>\
  732. </div>');
  733. }
  734. $("#diskVisualization").append('</div>');
  735. }
  736. setTimeout(function(){
  737. adjustPartitionViewHeight();
  738. },500);
  739. createEventHooks();
  740. }
  741. $(window).on("resize",function(){
  742. adjustPartitionViewHeight();
  743. drawDartitionTable();
  744. });
  745. $("#diskVisualization").on('click',function(e){
  746. var target = e.target;
  747. //console.log($(target).parents(".partitionRepresentation"));
  748. if ($(target).parents(".partitionRepresentation").length == 0 && !$(target).hasClass("partitionRepresentation")){
  749. $("#rightClickMenu").hide();
  750. }else if (e.button == 0){
  751. if ($(target).parents(".partitionRepresentation").length > 0 || $(target).hasClass("partitionRepresentation")){
  752. $(".focusedPart").removeClass("focusedPart");
  753. if ($(target).parent().hasClass("partitionRepresentation")){
  754. $(target).parent().addClass("focusedPart");
  755. }else{
  756. $(target).addClass("focusedPart");
  757. }
  758. }
  759. $("#rightClickMenu").hide();
  760. }
  761. });
  762. function bytesToSize(bytes) {
  763. if (viewMode == "human"){
  764. var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  765. if (bytes == 0) return '0 Byte';
  766. var i = parseFloat(Math.floor(Math.log(bytes) / Math.log(1024)));
  767. return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
  768. }else if (viewMode == "raw"){
  769. return bytes + " B";
  770. }
  771. }
  772. </script>
  773. </body>
  774. </html>