Serghey Rodin 10 anni fa
parent
commit
9db728e1ad

BIN
web/autoescape.gif


+ 199 - 36
web/css/file_manager.css

@@ -3,7 +3,7 @@ body { margin: 0; padding: 0; }
 
 .l-logo {
     background-image: url("/images/sprite.png");
-    background-position: -117px -34px;
+    background-position: -118px -59px;
     background-repeat: no-repeat;
     display: inline-block;
     float: left;
@@ -18,36 +18,57 @@ body { margin: 0; padding: 0; }
 .window { display: inline-block; float: left; /*border: 1px solid #eee;*/ width: 50%; height: 100%; background-color: #ececec; /*background: url(/images/background-dots.png) #ececec;*/ }
 .window.active { background: #fff; }
 
-.pwd { background-color: #7b7b7b; height: 31px; padding: 12px 0 0 17px; color: #eee; font-size: 14px; }
+.pwd { background-color: #7b7b7b; height: 28px; padding: 12px 0 0 17px; color: #eee; font-size: 14px; }
 .window.active .pwd { background-color: #333; }
 .window.active .pwd a { color: #FFF; }
 .pwd a { color: #CFCFCF; margin-right: 6px; padding: 0 7px; cursor: pointer; text-decoration: none; }
 .window.active .pwd a:hover, .pwd a:hover { color: #FFCC00; }
 
 
-.menu { background-color: #E2E2E0; display: inline-block; color: #999999; width: 100%; padding: 8px 0 7px 0; border-bottom: 1px solid #CFCFCD; border-left: 1px solid #CFCFCD; margin-left: -1px; }
+.active .menu { box-shadow: 0 1px 11px -5px rgba(0, 0, 0, 0.5); }
+.menu { /*background-color: #EEE;*/ display: inline-block; color: #999999; width: 100%; padding: 8px 0 7px 0; border-bottom: 1px solid #CFCFCD; border-left: 1px solid #CFCFCD; margin-left: -1px; }
 
-.menu div { display: inline-block; float: left; padding: 5px 9px; font-size: 11px; margin: 0 3px; line-height: 14px; }
 
-.menu div.button.disabled:hover, 
-.menu div.button { cursor: pointer; border: 1px solid #E2E2E0; border-radius: 3px; text-decoration: underline; background-color: #E2E2E0; 
-    transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s;
-    -webkit-transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s;
-    box-shadow: none; color: #999;
-}
-.menu div.button:hover { border: 1px solid #B7B7B7; text-decoration: none; background-color: #FFF; /*#EAEAE8;*/ color: #333;     
-/*    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.64); */
-    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.29);
-/*    box-shadow: 0 6px 15px rgba( 0, 0, 0, 0.23), 0 10px 18px rgba( 0, 0, 0, 0.16);*/
-/*    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.23), 0 3px 10px rgba(0, 0, 0, 0.16);*/
+.menu div { display: inline-block; float: left; padding: 6px 5px 5px; font-size: 11px; margin: 0 3px; line-height: 14px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; }
+.window.active .menu div.button { color: #777; }
+
+.menu div.button.small { display: none; width: 19px; height: 12px; }
+.menu div.button.small.mkfile { background: url("/images/flat_icons.png") no-repeat scroll -176px -97px; margin-left: 10px; }
+.menu div.button.small.mkdir { background: url("/images/flat_icons.png") no-repeat scroll -176px -123px; }
+.menu div.button.small.del { background: url("/images/flat_icons.png") no-repeat scroll -176px -149px; }
+.menu div.button.small.rename { background: url("/images/flat_icons.png") no-repeat scroll -180px -180px; width: 12px; }
+.menu div.button.small.copy { background: url("/images/flat_icons.png") no-repeat scroll -177px -210px; }
+.menu div.button.small.download { background: url("/images/flat_icons.png") no-repeat scroll -176px -243px; }
+.menu div.button.small.extract { background: url("/images/flat_icons.png") no-repeat scroll -232px -35px; }
+.menu div.button.small.archive { background: url("/images/flat_icons.png") no-repeat scroll -175px -58px; }
+
+
+.menu div.button.small.mkfile:hover { background-position: -203px -97px; }
+.menu div.button.small.mkdir:hover { background-position: -203px -123px; }
+.menu div.button.small.del:hover { background-position: -203px -149px; }
+.menu div.button.small.rename:hover { background-position: -207px -180px; }
+.menu div.button.small.copy:hover { background-position: -204px -210px; }
+.menu div.button.small.download:hover { background-position: -204px -243px; }
+.menu div.button.small.extract:hover { background: url("/images/flat_icons.png") no-repeat scroll -255px -35px; }
+.menu div.button.small.archive:hover { background: url("/images/flat_icons.png") no-repeat scroll -201px -35px; }
+
+
+
+
+
+.menu div.button.disabled:hover,
+.menu div.button { cursor: pointer; transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; -webkit-transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; box-shadow: none; color: #999 
 }
+.window.active .menu div.button:hover,
+.menu div.button:hover { text-decoration: none; color: #1FB9CA; border-radius: 0; }
+
 .menu div.button.disabled:hover, 
 .menu div.button.disabled { opacity: 0.5; cursor: default; text-decoration: none; }
 
 
 
 .menu .upload.button { color: #777; border: 1px solid #B7B7B7; background-color: #EAEAE8; text-transform: uppercase; font-size: 12px; text-decoration: none; margin-left: 8px; padding: 5px 12px; margin-right: 10px; border-radius: 3px; float: left; transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; -webkit-transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; font-size: 11px; line-height: 14px; }
-.window.active .menu .upload { border: 1px solid #F79B44; background-color: #F79B44; color: #FFF; }
+.window.active .menu .upload { border: 1px solid #AACC0D; background-color: #AACC0D; color: #FFF; }
 
 .menu .upload.button.progress { background: url(/images/progress.gif) no-repeat /*-98px*/ -60px 0px #EBEBEB; border-color: #8A9079; color: transparent; padding: 3px 12px; height: 0; margin-top: 9px;     transition: background 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s;
     -webkit-transition: background 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s;
@@ -55,22 +76,22 @@ body { margin: 0; padding: 0; }
 
 .menu .upload.button.progress.done { background-color: #d1ff66; border-color: #8a9079; box-shadow: 0 0 9px 0 #d1ff38; color: transparent; height: 0; margin-top: 9px; padding: 3px 12px; transition: background 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; -webkit-transition: background 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; transition: height 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; -webkit-transition: height 0.28s cubic-bezier(0.4, 0, 0.2, 1) 0s; }
 
-.menu .upload.button:hover, .window.active .menu .upload:hover { border: 1px solid #469D8D; background-color: #54bdaa; /*border: 1px solid #6DB8D3; background-color: #6DB8D3;*/  color: #fff; box-shadow: 0 2px 5px 0 rgba( 47, 106, 95, 0.8); }
+.menu .upload.button:hover, .window.active .menu .upload:hover { border: 1px solid #C0E60F; background-color: #C0E60F; color: #fff; }
 .menu .upload.button:active, .window.active .menu .upload:active { border: 1px solid #FFCC00; background-color: #FFCC00; color: #FFF; }
 
 .menu .not-writable { color: #BD846A; font-size: 12px; text-decoration: none; margin-left: 10px; padding: 5px 12px; margin-right: 20px; }
 
-.menu .sort-by { border-bottom: 1px solid #b7b7b7; border-radius: 0; cursor: pointer; float: right; height: 17px; line-height: 10px; margin-right: 8px; padding: 8px 10px 0; text-decoration: none; width: 100px; }
-.menu .sort-by .direction {  background: url("/images/flat_icons.png") repeat scroll -245px -76px; display: inline-block; float:right; width: 12px; height: 20px; margin-top: -10px; }
-.menu .sort-by.desc .direction { background-position: -270px -76px; } 
+.menu .sort-by { border-radius: 0; cursor: pointer; float: right; height: 17px; line-height: 10px; margin-right: 8px; padding: 8px 10px 0; text-decoration: none; }
+.menu .sort-by .direction {  background: url("/images/flat_icons.png") repeat scroll -390px -76px; display: inline-block; float:right; width: 12px; height: 20px; margin-top: -10px; }
+.menu .sort-by.desc .direction { background-position: -415px -76px; }
 .menu .sort-by span { font-size: 12px; color: #555; text-decoration: none; border: none; }
 .menu .sort-by span.entity { color: #555; text-decoration: none; border: none; float: right; display: inline-block; }
-.menu .sort-by:hover span { color: #429586; }
+.menu .sort-by:hover span { color: #43B2BE; }
 .menu .total-size { padding: 7px 0 0 0; }
 
 .menu .not-writable:hover { border: 1px solid #E2E2E0; }
 
-ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left: 1px solid #DDDDDD; margin-left: -1px; overflow: auto;  }
+ul.listing { list-style-type: none; padding: 18px 0 0; margin: -4px 0 0 -1px;  border-left: 1px solid #DDDDDD; overflow: auto; }
 .listing li { color: #999999; display: block; height: 32px; margin: 1px 0 0; line-height: 30px; border: 1px solid transparent; }
 .listing li span { display: inline-block; float: right; }
 .listing li .marker { width: 4px; float: left; height: 100%; margin-right: 31px; }
@@ -170,29 +191,35 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
 .listing li .icon.filetype-xhtml { background: url("/images/flat_icons.png") no-repeat scroll -138px -228px; }
 
 
-.listing li .filename { color: #555; cursor: pointer; height: 32px; float: left; padding: 0 7px 0 7px; border-radius: 3px; transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1) 0s; -webkit-transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1) 0s; }
+.listing li .filename { color: #555; cursor: pointer; height: 32px; max-width: 40%; overflow: hidden; float: left; padding: 0 7px 0 7px; border-radius: 3px; transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1) 0s; -webkit-transition: all 0.18s cubic-bezier(0.4, 0, 0.2, 1) 0s; }
 /* .listing li .filename { background: url("/images/folder_.png") no-repeat scroll -2px 6px; color: #555; cursor: pointer; float: left; margin-left: -27px; padding-left: 19px; }*/
 
-
+.listing li .filename:hover { color: #333; background-color: #D1D0CF; }
+/*
 .listing li .filename:hover { color: #FFF; background-color: #6CB6B9; }
 .listing li.selected .filename:hover { color: #FFF; }
 .listing li.active .filename:hover { color: #FFF; background-color: #CAA335; }
 .listing li.active.selected .filename:hover { color: #FFF; background-color: #60A885; }
-
+*/
 .listing li .filename a { color: #7D7D7D; text-decoration: none; }
 .listing li .mode { width: 51px; font-size: 11px; }
 .listing li .owner { width: 11%; font-style: italic; color: #81A64F; font-size: 12px; }
-.listing li .size { width: 8%; color: #44a8b3; font-size: 12px; padding-right: 7px; text-align: right; }
-.listing li .size-unit { width: 5%; font-size: 11px; font-weight: bold; color: #A7A7A7; padding-top: 1px; }
-.listing li .date { width: 11%; font-size: 11px; }
-.listing li .time { width: 8%; font-size: 11px; }
+.listing li .size-value { width: 70px; color: #44a8b3; font-size: 12px; padding-right: 7px; text-align: right; }
+.listing li .size-unit { width: 30px; font-size: 11px; font-weight: bold; color: #A7A7A7; text-align: left; }
+.listing li .date { width: 50px; font-size: 11px; }
+.listing li .time { width: 50px; font-size: 11px; }
 
 .listing li.selected-inactive.selected { background-color: #e9e9e9; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; }
 .listing li.selected-inactive .mode,
 .listing li.selected-inactive .time,
 .listing li.selected-inactive .date { color: #999 !important; }
 .window.active .listing li.selected.active { background-color: #73CAA0; }
-.listing li.selected { background-color: #7FD5D9; }
+
+.listing li.selected { background-color: #777 /*#7FD5D9*/; }
+.listing.active li.selected { background-color: #ffd437 /*#7FD5D9*/; }
+.listing li.selected .filename:hover { color: #333; background-color: #F0B607; }
+
+
 
 
 .listing li.selected-inactive.selected.active { background-color: #dfc891;  border-top: 1px solid #cdb885; border-bottom: 1px solid #cdb885; }
@@ -202,7 +229,7 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
 .listing li.selected .filename { color: #333; }
 .listing li.selected .date,
 .listing li.selected .mode,
-.listing li.selected .time { color: #FFF; }
+.listing li.selected .time { color: #777; }
 .listing li.selected .owner { color: #31775A; }
 .listing li.selected .size { color: #31775A; }
 
@@ -213,9 +240,9 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
 
 
 .listing li .filename a:hover { color: #3399FF; }
-.listing li:hover { background-color: #F4F4F2; }
+.listing li:hover { background-color: #E5E5E5; cursor: pointer; }
 .listing li.active:hover { background-color: #FFD63F; }
-.listing li.selected:hover { background-color: #89E6EA; }
+.listing li.selected:hover { background-color: /*#89E6EA*/#FFE570; }
 .listing li.selected.active:hover { background-color: #77D1A6; }
 
 
@@ -238,12 +265,12 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
 .context-menu.sort-order li.last { border: none; }
 .context-menu.sort-order li:hover { background-color: #333; }
 .context-menu.sort-order span { padding: 12px 12px 12px 12px; background: ulr(/images/flat_icons.png) }
-.context-menu.sort-order span.up { background: url(/images/flat_icons.png) -255px -141px; padding: 12px 14px; display: inline-block; width: 16px; }
+.context-menu.sort-order span.up { background: url(/images/flat_icons.png) -399px -141px; padding: 12px 14px; display: inline-block; width: 16px; }
 .context-menu.sort-order span.name,
 .context-menu.sort-order span.date,
 .context-menu.sort-order span.size,
 .context-menu.sort-order span.type
- { background: url("/images/flat_icons.png") repeat scroll -162px -105px; display: inline-block; padding: 12px 28px 12px 12px; width: 64px; }
+ { background: url("/images/flat_icons.png") repeat scroll -308px -105px; display: inline-block; padding: 12px 28px 12px 12px; width: 64px; }
 
 
 
@@ -281,7 +308,7 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
 
 /*.confirm-box.delete { height: 183px; }*/
 
-.confirm-box .new-title { background-color: #292929; border: 1px solid #111; color: #fff; font-family: Arial; font-size: 16px; margin-bottom: 73px; margin-left: 27px; padding: 10px 14px; width: 396px; }
+.confirm-box .new-title { background-color: #292929; border: 1px solid #111; color: #eee; font-family: Arial; font-size: 16px; margin-bottom: 73px; margin-left: 27px; padding: 10px 14px; width: 396px; }
 .confirm-box .new-title:focus { border: 1px solid #FFCC00; box-shadow: 0 0 5px 0 rgba(255, 204, 0 , 0.3); }
 
 /*.confirm-box.rename { height: 209px; } */
@@ -303,6 +330,11 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
 .confirm-box.archive.warning .warning { display: inline-block; }
 .confirm-box.archive.warning .message { margin-bottom: -31px; }
 
+.confirm-box.copy .message { margin-bottom: 0; }
+.confirm-box.unpack .message { margin-bottom: 0; }
+.confirm-box.pack .message { margin-bottom: 0; }
+
+
 .confirm-box .actions select { background-color: #333333; border: 1px solid #ccc; color: #fff; font-family: Arial; font-size: 16px; margin-bottom: 27px; margin-left: 27px; padding: 10px 14px; }
 .confirm-box .actions .title { color: #ccc; font-family: Arial; line-height: 33px; padding-left: 27px; text-transform: capitalize; }
 .confirm-box .actions label { cursor: pointer; padding-left: 27px; color: #ebe697; }
@@ -436,3 +468,134 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: 0;  border-left:
     background-color: #FFCC00;
 }
 
+
+
+
+
+.checkbox-toolbar {
+    float: left !important;
+}
+/*W
+.check-label::before {
+    background-image: url("/images/sprite.png");
+    background-position: -232px -9px;
+    background-repeat: no-repeat;
+    background-size: 450px auto;
+    content: "";
+    display: inline-block;
+    height: 16px;
+    width: 16px;
+    margin-top: -25px;
+
+    border: 1px solid red;
+}
+input[type="checkbox"] {
+    display: none;
+}
+
+.clicked-on.check-label::before, .checkbox-selected .check-label {
+    background-position: -225px -42px;
+    content: "";
+    display: inline-block;
+    height: 27px;
+    left: -6px;
+    top: -6px;
+    width: 27px;
+}
+*/
+
+@media (max-width: 1400px) {
+  .listing li .filename { width: 35%; }
+}
+
+
+@media (max-width: 1320px) {
+  .menu div.button.mkfile,
+  .menu div.button.mkdir { display: none; }
+  .menu div.button.mkfile.small,
+  .menu div.button.mkdir.small { display: inline-block; }
+  .listing li .filename { max-width: 30%; }
+}
+
+@media (max-width: 1210px) {
+  .menu div.button.del { display: none; }
+  .menu div.button.del.small { display: inline-block; }
+  .listing li .filename { max-width: 25%; }
+}
+
+
+@media (max-width: 1180px) {
+  .menu div.button { display: none; }
+  .menu div.button.medium,
+  .menu div.button.small { display: inline-block; }
+  .listing li .filename { max-width: 20%; }
+}
+
+@media (max-width: 1080px) {
+  .listing li .owner { display: none; }
+}
+
+@media (max-width: 890px) {
+  .window { width: 100%; }
+  .window:nth-of-type(2){ display: none; }
+  .listing li .owner { display: inline-block; }
+
+  .menu div.button { display: inline-block; }
+  .menu div.button.small { display: none; }
+  .menu div.copy.button { display: none; }
+  .listing li .filename { max-width: 40%; }
+}
+
+@media (max-width: 720px) {
+  .listing li .filename { max-width: 30%; }
+}
+
+@media (max-width: 600px) {
+  .menu div.button { display: none; }
+  .menu div.button.medium,
+  .menu div.button.small { display: inline-block; }
+  .menu div.copy.button.small { display: none; }
+  .listing li .filename { max-width: 20%; }
+}
+
+@media (max-width: 520px) {
+  .listing li .owner { display: none; }
+  .listing li .filename { max-width: 15%; }
+}
+
+@media (max-width: 400px) {
+  .listing li .mode { display: none; }
+  .listing li .time { display: none; }
+  .listing li .filename { max-width: 30%; }
+}
+
+@media (max-width: 360px) {
+  .listing li .date { display: none; }
+}
+
+@media (max-width: 310px) {
+  .listing li .size { display: none; }
+}
+
+
+.subcontext-control.hidden {
+    display: none !important;
+}
+
+.subcontext-control {
+    color: red;
+}
+.subcontext-menu-hidden {
+    display: none;
+}
+
+.subcontext-menu {
+    position: absolute;
+    background-color: yellow;
+    padding: 10px;
+    border: 1px solid red;
+}
+
+.subcontext-menu li {
+    /*float: left;*/
+}

+ 15 - 0
web/download/file/index.php

@@ -0,0 +1,15 @@
+<?php
+if (!empty($_REQUEST['path'])) {
+    $path = $_REQUEST['path'];
+    if (is_readable($path)) {
+        header("Content-disposition: attachment;filename=".basename($path));
+        readfile($path);
+        exit;
+    }
+}
+else {
+    die('File not found');
+}
+
+
+?>

+ 76 - 0
web/edit/file/index.php

@@ -0,0 +1,76 @@
+<?php
+session_start();
+
+include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
+/*
+// Check user session
+if ((!isset($_SESSION['user'])) && (!defined('NO_AUTH_REQUIRED'))) {
+    $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
+    header("Location: /login/");
+    exit;
+}
+*/
+
+?>
+
+<title>Edit file <?= htmlspecialchars($_REQUEST['path']) ?></title>
+<meta charset="utf-8" /> 
+
+<link href="/css/file_manager_editor.css" type="text/css" rel="stylesheet">
+<script src="/js/cheef-editor/jquery/jquery-1.8.3.min.js"></script>
+<script src="/js/cheef-editor/ace/ace.js"></script>
+<script src="/js/cheef-editor/ace/theme-twilight.js"></script>
+<script src="/js/cheef-editor/ace/mode-ruby.js"></script>
+<script src="/js/cheef-editor/jquery-ace.min.js"></script>
+
+<?php 
+
+    if (!empty($_REQUEST['path'])) {
+        $content = '';
+        $path = $_REQUEST['path'];
+        if (is_readable($path)) {
+            
+            $image = getimagesize($path) ? true : false;
+            
+            if ($image) {
+                header('Location: /view/file/?path='.$path);
+                exit;
+            }
+            
+            if (!empty($_POST['save'])) {
+                $fn = tempnam ('/tmp', 'vst-save-file-');
+                if ($fn) {
+                    $f = fopen ($fn, 'w+');
+                    fwrite($f, $_POST['contents']);
+                    if ($f) {
+                        copy($fn, $path);
+                    }
+                    unlink($fn);
+                  }
+            }
+            
+            $content = file_get_contents($path);
+            $content = $content;
+        }
+    }
+    else {
+        $content = '';
+    }
+
+?>
+
+<form method="post">
+<input type="submit" name="save" value="Save" class="save" />
+
+
+<textarea name="contents" class="editor" id="editor" rows="4" style="display:none;width: 100%; height: 100%;"><?php echo $content ?></textarea>
+
+</form>
+<script>
+  $('.editor').ace({ theme: 'twilight', lang: 'ruby' });
+
+  var dcrt = $('#editor').data('ace');
+  var editor = dcrt.editor.ace;
+  editor.gotoLine(0);
+  editor.focus();
+</script>

+ 38 - 8
web/file_manager/fm_api.php

@@ -27,18 +27,29 @@ $fm->setRootDir($panel[$user]['HOME']);
 $_REQUEST['action'] = empty($_REQUEST['action']) ? '' : $_REQUEST['action'];
 
 switch ($_REQUEST['action']) {
+    case 'cd':
+        $dir = $_REQUEST['dir'];
+        print json_encode($fm->ls($dir));
+        break;
     case 'rename_file':
         $dir = $_REQUEST['dir'];
         $item = $_REQUEST['item'];
         $target_name = $_REQUEST['target_name'];
 
-        print json_encode($fm->renameItem($dir, $item, $target_name));
+        print json_encode($fm->renameFile($dir, $item, $target_name));
+        break;
+    case 'rename_directory':
+        $dir = $_REQUEST['dir'];
+        $item = $_REQUEST['item'];
+        $target_name = $_REQUEST['target_name'];
+
+        print json_encode($fm->renameDirectory($dir, $item, $target_name));
         break;
     case 'delete_files':
         $dir = $_REQUEST['dir'];
         $item = $_REQUEST['item'];
 
-        print json_encode($fm->deleteItems($dir, $item));
+        print json_encode($fm->deleteItem($dir, $item));
         break;
     case 'create_file':
         $dir = $_REQUEST['dir'];
@@ -50,19 +61,38 @@ switch ($_REQUEST['action']) {
         $dirname = $_REQUEST['dirname'];
         print json_encode($fm->createDir($dir, $dirname));
         break;
-    case 'cd':
-        $dir = $_REQUEST['dir'];
-        print json_encode($fm->ls($dir));
-        break;
+    
     case 'open_file':
         $dir = $_REQUEST['dir'];
         print json_encode($fm->open_file($dir));
         break;
-    case 'copy_files':
+    case 'copy_file':
+        $dir = $_REQUEST['dir'];
+        $target_dir = $_REQUEST['dir_target'];
+        $filename   = $_REQUEST['filename'];
+        $item       = $_REQUEST['item'];
+        print json_encode($fm->copyFile($item, $dir, $target_dir, $filename));
+        break;
+    case 'copy_directory':
+        $dir = $_REQUEST['dir'];
+        $target_dir = $_REQUEST['dir_target'];
+        $filename   = $_REQUEST['filename'];
+        $item       = $_REQUEST['item'];
+        print json_encode($fm->copyDirectory($item, $dir, $target_dir, $filename));
+        break;
+    case 'unpack_item':
+        $dir = $_REQUEST['dir'];
+        $target_dir = $_REQUEST['dir_target'];
+        $filename   = $_REQUEST['filename'];
+        $item       = $_REQUEST['item'];
+        print json_encode($fm->unpackItem($item, $dir, $target_dir, $filename));
+        break;
+    case 'pack_item':
         $dir = $_REQUEST['dir'];
         $target_dir = $_REQUEST['dir_target'];
         $filename   = $_REQUEST['filename'];
-        print json_encode($fm->copyFile($dir, $target_dir, $filename));
+        $item       = $_REQUEST['item'];
+        print json_encode($fm->packItem($item, $dir, $target_dir, $filename));
         break;
     default:
         //print json_encode($fm->init());

+ 180 - 56
web/file_manager/fm_core.php

@@ -32,7 +32,7 @@ class FileManager {
         $path = !empty($_REQUEST['dir']) ? $_REQUEST['dir'] : '';
         $start_url = !empty($path) ? $this->ROOT_DIR . '/' . $path : $this->ROOT_DIR;
         $listing = $this->getDirectoryListing($path);
-        
+         
         return $data = array(
             'result'     => true,
             'ROOT_DIR'   => $this->ROOT_DIR,
@@ -50,11 +50,34 @@ class FileManager {
             $path = $this->ROOT_DIR . '/' . $path_part;
         }
         //var_dump($path);die();
+        //$path = str_replace(' ', '\ ', $path);
         return escapeshellarg($path);
     }
     
-    function deleteItems($dir, $item) {
-        if (is_readable($item)) {
+    function deleteItem($dir, $item) {
+        $dir = $this->formatFullPath($item);
+        if (is_dir($item)) {
+            exec (VESTA_CMD . "v-delete-fs-directory {$this->user} {$dir}", $output, $return_var);
+        }
+        else {
+            exec (VESTA_CMD . "v-delete-fs-file {$this->user} {$dir}", $output, $return_var);
+        }
+
+        $error = self::check_return_code($return_var, $output);
+        
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
+        }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
+        
+        /*if (is_readable($item)) {
             unlink($item);
         }
         if (is_readable($item)) {
@@ -65,93 +88,194 @@ class FileManager {
         }
         return array(
             'result' => true
-        );
+        );*/
     }
     
-    function copyFile($dir, $target_dir, $filename) {
-        // todo: checks
-        // todo: vesta method "create file"
-        if (empty($dir)) {
-            $dir = $this->ROOT_DIR;
-        }
+    function copyFile($item, $dir, $target_dir, $filename) {
+        $src = $this->formatFullPath($item);
+        $dst = $this->formatFullPath($target_dir);
+    
+        exec (VESTA_CMD . "v-copy-fs-file {$this->user} {$src} {$dst}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
         
-        if (empty($target_dir)) {
-            $target_dir = $this->ROOT_DIR;
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
         }
-        copy($dir . '/' . $filename, $target_dir.'/'.$filename);
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
+    }
+    
+    
+    function copyDirectory($item, $dir, $target_dir, $filename) {
+        $src = $this->formatFullPath($item);
+        $dst = $this->formatFullPath($target_dir);
+    
+        exec (VESTA_CMD . "v-copy-fs-directory {$this->user} {$src} {$dst}", $output, $return_var);
+
+
+        $error = self::check_return_code($return_var, $output);
         
-        if (!is_readable($target_dir . '/' .$filename)) {
+        if (empty($error)) {
             return array(
-                'result'  => false,
-                'message' => 'item was not created'
+                'result' => true
+            );
+        }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
             );
         }
+    }
+    
+    static function check_return_code($return_var, $output) {
+        if ($return_var != 0) {
+            $error = implode('<br>', $output);
+            return $error;
+            //if (empty($error)) $error = __('Error code:',$return_var);
+            //$_SESSION['error_msg'] = $error;
+        }
         
-        return array(
-            'result' => true,
-            'bla' => $target_dir.'/'.$filename,
-            'bla2' => $dir . '/' . $filename
-        );
+        return null;
     }
     
     function createFile($dir, $filename) {
-        // todo: checks
-        // todo: vesta method "create file"
-        if (empty($dir)) {
-            $dir = $this->ROOT_DIR;
+        $dir = $this->formatFullPath($dir . '/' . $filename);
+
+        exec (VESTA_CMD . "v-add-fs-file {$this->user} {$dir}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
+        
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
         }
-        file_put_contents($dir . '/' . $filename, '');
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
+    }
+    
+    function packItem($item, $dir, $target_dir, $filename) {
+        $item     = $this->formatFullPath($item);
+        $dst_item = $this->formatFullPath($target_dir);
+//print VESTA_CMD . "v-add-fs-archive {$this->user} {$item} {$dst_item}";die();
+        exec (VESTA_CMD . "v-add-fs-archive {$this->user} {$item} {$dst_item}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
         
-        if (!is_readable($dir . '/' .$filename)) {
+        if (empty($error)) {
             return array(
-                'result'  => false,
-                'message' => 'item was not created'
+                'result' => true
             );
         }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
+    }
+    
+    function unpackItem($item, $dir, $target_dir, $filename) {
+        $item     = $this->formatFullPath($item);
+        $dst_item = $this->formatFullPath($target_dir);
+
+        exec (VESTA_CMD . "v-extract-fs-archive {$this->user} {$item} {$dst_item}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
         
-        return array(
-            'result' => true
-        );
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
+        }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
     }
     
-    function renameItem($dir, $item, $target_name) {
-        if (empty($dir)) {
-            $dir = $this->ROOT_DIR;
+    function renameFile($dir, $item, $target_name) {
+        $item     = $this->formatFullPath($dir . '/' . $item);
+        $dst_item = $this->formatFullPath($dir . '/' . $target_name);
+        
+//        var_dump(VESTA_CMD . "v-move-fs-file {$this->user} {$item} {$dst_item}");die();
+
+        exec (VESTA_CMD . "v-move-fs-file {$this->user} {$item} {$dst_item}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
+        
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
         }
-        if (is_readable($dir . '/' . $item)) {
-            rename($dir . '/' . $item, $dir . '/' . $target_name);
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
         }
-        if (!is_readable($dir . '/' .$target_name)) {
+    }
+    function renameDirectory($dir, $item, $target_name) {
+        $item     = $this->formatFullPath($dir . $item);
+        $dst_item = $this->formatFullPath($dir . $target_name);
+
+        if ($item == $dst_item) {
             return array(
-                'result'  => false,
-                'message' => 'item was not renamed'
+                'result' => true
             );
         }
+
+
+        exec (VESTA_CMD . "v-move-fs-directory {$this->user} {$item} {$dst_item}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
         
-        return array(
-            'result' => true
-        );
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
+        }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
     }
     
     function createDir($dir, $dirname) {
-        // todo: checks
-        // todo: vesta method "create file"
-        if (empty($dir)) {
-            $dir = $this->ROOT_DIR;
-        }
+        $dir = $this->formatFullPath($dir . '/' . $dirname);
+
+        exec (VESTA_CMD . "v-add-fs-directory {$this->user} {$dir}", $output, $return_var);
 
-        mkdir($dir . '/' . $dirname);
+        $error = self::check_return_code($return_var, $output);
         
-        if (!is_readable($dir . '/' .$dirname)) {
+        if (empty($error)) {
             return array(
-                'result'  => false,
-                'message' => 'item was not created'
+                'result' => true
+            );
+        }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
             );
         }
-        
-        return array(
-            'result' => true
-        );
     }
     
     function getDirectoryListing($dir = '') {

BIN
web/images/flat_icons.png


BIN
web/images/in_progress.gif


+ 35 - 0
web/js/app.js

@@ -800,6 +800,38 @@ App.Ajax.request = function(method, data, callback, onError){
     }*/
     //App.Helpers.setAjaxBusy(method, data);
     data = data || {};
+    
+    var prgs = $('.progress-container');
+    
+    switch (method) {
+        case 'cd':
+            prgs.find('title').text('Opening dir');
+            prgs.show();
+            break;
+        case 'delete_files':
+            prgs.find('title').text('Deleting');
+            prgs.show();
+            break;
+        case 'unpack_item':
+            prgs.find('title').text('Unpacking');
+            prgs.show();
+            break;
+        case 'create_file':
+            prgs.find('title').text('Creating file');
+            prgs.show();
+            break;
+        case 'create_dir':
+            prgs.find('title').text('Creating directory');
+            prgs.show();
+            break;
+        case 'rename_file':
+            prgs.find('title').text('Renaming file');
+            prgs.show();
+            break;
+        default:
+        
+            break;
+    }
 
     jQuery.ajax({
         url: GLOBAL.ajax_url,
@@ -816,6 +848,7 @@ App.Ajax.request = function(method, data, callback, onError){
         cache: false,
         error: function(jqXHR, textStatus, errorThrown)
         {
+            prgs.hide();
             onError && onError();
             if ('undefined' != typeof onError) {
                 fb.error(textStatus);
@@ -824,9 +857,11 @@ App.Ajax.request = function(method, data, callback, onError){
         complete: function()
         {
             //App.Helpers.setAjaxFree(method, data);
+            prgs.hide();
         },
         success: function(reply)
         {
+            prgs.hide();
             //App.Helpers.setAjaxFree(method, data);
             try {
                 callback && callback(reply);

File diff suppressed because it is too large
+ 730 - 62
web/js/file_manager.js


+ 10 - 3
web/js/floating_layer.js

@@ -2,7 +2,12 @@
 {
     jQuery.fn.flayer_close = function()
     {
-        jQuery(this).flayer.close();
+        try {
+            jQuery(this).flayer.close();
+        }
+        catch (e) {
+            fb.error(e);
+        }
     }
     jQuery.fn.flayer = function(params)
     {  
@@ -15,8 +20,9 @@
             id : 'floating-box',
             className : 'floating-box-class',
             zIndex : 5000,
-            beforeStart : function(){},
-            beforeEnd : function(){},
+            beforeStart : function() {},
+            beforeEnd : function() {},
+            afterStart: function() {},
             close : null,
             closeClass : 'close-floating-layer',
             outerClose : false,
@@ -207,6 +213,7 @@
             jQuery(ref.content).append(jQuery(elm).removeClass('hidden'));
             start_ovservers();
             jQuery(ref.container).removeClass('hidden').css({'display':'block'});
+            config.afterStart(elm);
 
         }
         //

+ 7 - 0
web/js/i18n.js.php

@@ -46,3 +46,10 @@ if (!function_exists('__')) {
 
 App.i18n.ARE_YOU_SURE     = '<?php echo __('Are you sure?') ?>';
 App.Constants.UNLIM_TRANSLATED_VALUE = '<?php echo __('unlimited') ?>';
+
+App.Constants.FM_DIRECTORY_NAME_CANNOT_BE_EMPTY = '<?php echo __('Directory name cannot be empty') ?>';
+App.Constants.FM_FILE_NAME_CANNOT_BE_EMPTY      = '<?php echo __('File name cannot be empty') ?>';
+App.Constants.FM_NO_FILE_SELECTED               = '<?php echo __('No file selected') ?>';
+App.Constants.FM_NO_FILE_OR_DIRECTORY_SELECTED  = '<?php echo __('No file or folder selected') ?>';
+App.Constants.FM_FILE_TYPE_NOT_SUPPORTED        = '<?php echo __('File type not supported') ?>';
+

+ 71 - 13
web/js/templates.js

@@ -7,31 +7,65 @@ App.Templates.html = {
         hint: ['']
     },
     // file manager
+    //
+
+//<input id="check~!:index~!" class="ch-toggle2" type="checkbox" name="domain[]" value="~!:index3~!">\    
+    
     FM: {
         entry_line: ['<li class="dir">\
-                        <span class="marker"></span>\
+                        <span class="marker">\
+                        </span>\
                         <span class="icon ~!:ITEM_TYPE~!" ></span>\
                         <input type="hidden" class="source" value=\'~!:SOURCE~!\'/>\
                         <span class="filename ripple" ~!:CL_ACTION_1~!>~!:NAME~!</span>\
                         <span class="mode">~!:PERMISSIONS~!</span>\
                         <span class="owner">~!:OWNER~!</span>\
-                        <span class="size">~!:SIZE~!</span>\
+                        <span class="size-unit">~!:SIZE_UNIT~!</span>\
+                        <span class="size-value">~!:SIZE_VALUE~!</span>\
                         <span class="date">~!:DATE~!</span>\
                         <span class="time">~!:TIME~!</span>\
+                        <span class="subcontext-control ~!:SUBMENU_CLASS~!" onClick="FM.toggleSubContextMenu(this)">&#8226;&#8226;&#8226;&nbsp;\
+                        <ul class="subcontext-menu subcontext-menu-hidden"><li onClick="FM.downloadFileFromSubcontext(this);">Download</li><li onClick="FM.editFileFromSubcontext(this);">Edit</li></ul>\
+                        </span>\
                     </li>'],
+        popup_alert: ['<div class="confirm-box alarm popup-box">\
+                            <div class="message">~!:TEXT~!</div>\
+                                <div class="controls">\
+                            <p class="ok" onClick="FM.popupClose();">close</p>\
+                            </div>\
+                        </div>'],
+        popup_bulk: ['<div class="confirm-box alarm popup-box">\
+                            <div class="message">~!:ACTION~!: <br />~!:TEXT~!</div>\
+                            <div class="results"></div>\
+                                <div class="controls">\
+                            <!-- p class="ok" onClick="FM.popupClose();">close</p -->\
+                            <p><img src="/images/in_progress.gif"></p>\
+                            </div>\
+                        </div>'],
         popup_delete: ['<div class="confirm-box delete popup-box">\
-                            <div class="message">Are you sure you want to delete file <span class="title">"~!:FILENAME~!"</span>?</div>\
+                            <div class="message">Are you sure you want to delete <span class="title">"~!:FILENAME~!"</span>?</div>\
                                 <div class="controls">\
                             <p class="cancel" onClick="FM.popupClose();">cancel</p>\
                             <p class="ok" onClick="FM.confirmDelete();">delete</p>\
                             </div>\
                         </div>'],
-        popup_rename_: ['<div class="confirm-box rename warning">\
-                            <div class="message">Rename file <span class="title">"~!:FILENAME~!"</span></div>\
+        popup_copy: ['<div class="confirm-box copy popup-box">\
+                            <div class="message">Are you sure you want to copy <span class="title">"~!:SRC_FILENAME~!"</span> into:</div>\
+                            <div class="actions">\
+                                <input type="text" id="copy_dest" value="~!:DST_FILENAME~!" class="new-title">\
+                            </div>\
+                            <div class="message">existing files will be replaced</div>\
+                                <div class="controls">\
+                            <p class="cancel" onClick="FM.popupClose();">cancel</p>\
+                            <p class="ok" onClick="FM.confirmCopyItems();">copy</p>\
+                            </div>\
+                        </div>'],
+        popup_rename: ['<div class="confirm-box rename warning">\
+                            <div class="message">Original name: <span class="title">"~!:FILENAME~!"</span></div>\
                             <!-- div class="warning">File <span class="title">"reading.txt"</span> already exists</div -->\
-                            <div class="warning"></div>\
+                            <div class="warning warning-message"></div>\
                             <div class="actions">\
-                                <input type="text" id="rename-title" class="new-title" />\
+                                <input type="text" id="rename-title" class="new-title"  value="~!:NEW_NAME~!" />\
                             </div>\
                             <div class="controls">\
                                 <p class="cancel" onClick="FM.popupClose();">cancel</p>\
@@ -43,15 +77,33 @@ App.Templates.html = {
                             </div>\
                         </div>'],
 
-        popup_rename: ['<div class="confirm-box unpack warning">\
-                            <div class="message">Extract archive <span class="title">"~!:FILENAME~!"</span> to <span class="title">"~!:DIRNAME~!"</span></div>\
-                            <div class="warning"></div>\
+        popup_pack: ['<div class="confirm-box pack warning">\
+                            <div class="message">Pack <span class="title">"~!:FILENAME~!"</span> into:</div>\
                             <div class="actions">\
+                                <input type="text" id="pack-destination" class="new-title" value="~!:DST_DIRNAME~!">\
+                            </div>\
+                            <div class="warning warning-message"></div>\
+                            <!-- div class="actions">\
                                 <label><input type="checkbox" name="overwrite" class="title" />Overwrite exising files</label>\
+                            </div -->\
+                            <div class="controls">\
+                                <p class="cancel" onClick="FM.popupClose();">cancel</p>\
+                                <p class="ok" onClick="FM.confirmPackItem();">Pack</p>\
+                            </div>\
+                        </div>'],
+
+        popup_unpack: ['<div class="confirm-box unpack warning">\
+                            <div class="message">Extract archive <span class="title">"~!:FILENAME~!"</span> to:</div>\
+                            <div class="actions">\
+                                <input type="text" id="unpack-destination" class="new-title" value="~!:DST_DIRNAME~!">\
                             </div>\
+                            <div class="warning warning-message"></div>\
+                            <!-- div class="actions">\
+                                <label><input type="checkbox" name="overwrite" class="title" />Overwrite exising files</label>\
+                            </div -->\
                             <div class="controls">\
                                 <p class="cancel" onClick="FM.popupClose();">cancel</p>\
-                                <p class="ok" onClick="FM.confirmRename();">Extract</p>\
+                                <p class="ok" onClick="FM.confirmUnpackItem();">Extract</p>\
                             </div>\
                         </div>'],
 
@@ -59,7 +111,7 @@ App.Templates.html = {
         popup_create_file: ['<div class="confirm-box rename warning">\
                             <div class="message">Create file</div>\
                             <!-- div class="warning">File <span class="title">"reading.txt"</span> already exists</div -->\
-                            <div class="warning"></div>\
+                            <div class="warning warning-message"></div>\
                             <div class="actions">\
                                 <input type="text" id="rename-title" class="new-title" />\
                             </div>\
@@ -71,7 +123,7 @@ App.Templates.html = {
         popup_create_dir: ['<div class="confirm-box rename warning">\
                             <div class="message">Create directory</div>\
                             <!-- div class="warning">File <span class="title">"reading.txt"</span> already exists</div -->\
-                            <div class="warning"></div>\
+                            <div class="warning warning-message"></div>\
                             <div class="actions">\
                                 <input type="text" id="rename-title" class="new-title" />\
                             </div>\
@@ -79,6 +131,12 @@ App.Templates.html = {
                                 <p class="cancel" onClick="FM.popupClose();">cancel</p>\
                                 <p class="ok" onClick="FM.confirmCreateDir();">create</p>\
                             </div>\
+                        </div>'],
+        popup_no_file_selected: ['<div class="confirm-box no-file-selected">\
+                            <div class="message">Please select a file</div>\
+                            <div class="controls">\
+                                <p class="ok" onClick="FM.confirmCreateDir();">ok</p>\
+                            </div>\
                         </div>']
     }
 };

+ 313 - 195
web/templates/file_manager/main.php

@@ -16,19 +16,19 @@
 <body>
     <div id="main">
         <div class="window active">
-            <div class="pwd">
+            <a href="/" class="l-logo"></a>
+            <div class="pwd pwd-tab-A">
            <? /* <? foreach($pwd as $dir ){ 
                 $path .= '/'.$dir;
                 echo '<a href="/admin.php?page=tor/index.php&files=1&path='.$path.'">'.$dir.'</a>';
             } ?> */ ?>
             </div>
-            <div class="menu menu-left">
+            <div class="menu menu-left menu-A">
                 <?php $pre_tab = 'A';include($_SERVER['DOCUMENT_ROOT'].'/templates/file_manager/tab_menu.php'); ?>
             </div>
-            
-            
+
             <ul class="listing listing-left">
-                <? 
+                <?
                 /*if(count($pwd) > 1){
                     echo '<li class="back">
                         <span class="marker"></span>
@@ -66,10 +66,10 @@
 
 
         <div class="window">
-            <div class="pwd">
+            <div class="pwd pwd-tab-B">
                 <? /* <a>var</a><a>www</a><a>html</a><a>sites</a><a>public html</a> */ ?>
             </div>
-            <div class="menu menu-right">
+            <div class="menu menu-right menu-B">
                 <?php $pre_tab = 'B';include($_SERVER['DOCUMENT_ROOT'].'/templates/file_manager/tab_menu.php'); ?>
             </div>
 
@@ -81,214 +81,214 @@
         </div>
 
 
-	<!-- div class="popups">
+    <!-- div class="popups">
+
+    <ul class="context-menu">
+        <li class="download">download</li>
+        <li class="">rename</li>
+        <li class="">chmod</li>
+        <li class="">chown</li>
+        <li class="">copy</li>
+        <li class="">cut</li>
+        <li class="disabled">paste</li>
+        <li class="">archive</li>
+        <li class="delete">delete</li>
+    </ul>
+
+
+    <div class="confirm-box replace">
+        <div class="message">File <span class="title">"reading.txt"</span> already exists</div>
+        <div class="action-name"><label><span class="checkbox"></span><span>apply to next <span class="number">27</span> conflicts</span></label></div>
+        <div class="controls">
+        <p class="cancel">cancel</p>
+            <p class="keep-original">keep original</p>
+            <p class="ok">replace</p>
+        </div>
+    </div>
 
-	<ul class="context-menu">
-	    <li class="download">download</li>
-	    <li class="">rename</li>
-	    <li class="">chmod</li>
-	    <li class="">chown</li>
-	    <li class="">copy</li>
-	    <li class="">cut</li>
-	    <li class="disabled">paste</li>
-	    <li class="">archive</li>
-	    <li class="delete">delete</li>
-	</ul>
 
+<br><br>
 
-	<div class="confirm-box replace">
-	    <div class="message">File <span class="title">"reading.txt"</span> already exists</div>
-	    <div class="action-name"><label><span class="checkbox"></span><span>apply to next <span class="number">27</span> conflicts</span></label></div>
-	    <div class="controls">
-		<p class="cancel">cancel</p>
-	        <p class="keep-original">keep original</p>
-	        <p class="ok">replace</p>
-	    </div>
-	</div>
+    <div class="confirm-box delete">
+        <div class="message">Are you sure you want to delete file <span class="title">"reading.txt"</span>?</div>
+            <div class="controls">
+        <p class="cancel">cancel</p>
+        <p class="ok">delete</p>
+        </div>
+    </div>
 
 
 <br><br>
 
-	<div class="confirm-box delete">
-	    <div class="message">Are you sure you want to delete file <span class="title">"reading.txt"</span>?</div>
-            <div class="controls">
-		<p class="cancel">cancel</p>
-		<p class="ok">delete</p>
-	    </div>
-	</div>
 
+    <div class="confirm-box rename warning">
+        <div class="message">Rename file <span class="title">"reading.txt"</span></div>
+        <div class="warning">File <span class="title">"reading.txt"</span> already exists</div>
+        <div class="actions">
+            <input type="text" class="new-title" />
+        </div>
+        <div class="controls">
+            <p class="cancel">cancel</p>
+        <p class="ok">rename</p>
+        </div>
+
+        <div class="controls replace">
+            <p class="cancel">cancel</p>
+            <p class="ok">replace</p>
+        </div>
+    </div>
 
 <br><br>
 
 
-	<div class="confirm-box rename warning">
-	    <div class="message">Rename file <span class="title">"reading.txt"</span></div>
-	    <div class="warning">File <span class="title">"reading.txt"</span> already exists</div>
-	    <div class="actions">
-	        <input type="text" class="new-title" />
-	    </div>
-	    <div class="controls">
-    		<p class="cancel">cancel</p>
-		<p class="ok">rename</p>
-	    </div>
+    <div class="confirm-box archive warnin">
+        <div class="message">Create archive</div>
+        <div class="warning">File <span class="title">"reading.tar.gz"</span> already exists</div>
+        <div class="actions">
+            <span class="title">archive name</span><br>
+            <input type="text" class="new-title" />
+            <br>
+
+            <span class="title">archive type</span><br>
+            <select>
+                <option value="tar">tar</option>
+                <option value="zip">zip</option>
+                <option value="rar">rar</option>
+            </select>
+            <br>
+
+            <span class="title">compression level</span><br>
+            <select>
+                <option value="0">0</option>
+                <option value="1">1</option>
+                <option value="2">2</option>
+                <option value="3">3</option>
+                <option value="4">4</option>
+                <option value="5">5</option>
+                <option value="6">6</option>
+                <option value="7">7</option>
+                <option value="8">8</option>
+                <option value="9">9</option>
+                <option value="10">10</option>
+            </select>
+        </div>
+        <div class="controls">
+            <p class="cancel">cancel</p>
+            <p class="ok ripple ripple-radial">create</p>
+        </div>
+
+        <div class="controls replace">
+            <p class="cancel">cancel</p>
+        <p class="ok">replace</p>
+        </div>
+    </div>
 
-	    <div class="controls replace">
-	        <p class="cancel">cancel</p>
-	        <p class="ok">replace</p>
-	    </div>
-	</div>
 
 <br><br>
 
 
-	<div class="confirm-box archive warnin">
-	    <div class="message">Create archive</div>
-	    <div class="warning">File <span class="title">"reading.tar.gz"</span> already exists</div>
-	    <div class="actions">
-	        <span class="title">archive name</span><br>
-	        <input type="text" class="new-title" />
-	        <br>
-
-	        <span class="title">archive type</span><br>
-	        <select>
-	            <option value="tar">tar</option>
-	            <option value="zip">zip</option>
-	            <option value="rar">rar</option>
-	        </select>
-	        <br>
-
-	        <span class="title">compression level</span><br>
-	        <select>
-	            <option value="0">0</option>
-	            <option value="1">1</option>
-	            <option value="2">2</option>
-	            <option value="3">3</option>
-	            <option value="4">4</option>
-	            <option value="5">5</option>
-	            <option value="6">6</option>
-	            <option value="7">7</option>
-	            <option value="8">8</option>
-	            <option value="9">9</option>
-	            <option value="10">10</option>
-	        </select>
-	    </div>
-	    <div class="controls">
-	        <p class="cancel">cancel</p>
-	        <p class="ok ripple ripple-radial">create</p>
-	    </div>
-
-	    <div class="controls replace">
-	        <p class="cancel">cancel</p>
-		<p class="ok">replace</p>
-	    </div>
-	</div>
+    <div class="confirm-box owner-mode warnin-g">
+        <div class="message">Owner - Mode</div>
+        <div class="warning">You have no rights to change owner, group or mode</div>
+        <div class="actions">
+            <div class="owner-group">
+                <div class="owner col">
+                <span class="title">owner</span><br>
+                <select name="owner">
+                    <option value="root">root</option>
+                    <option value="bob">Bob</option>
+                        <option value="ralph">Ralph</option>
+                    </select>
+                </div>
+
+                <div class="group col">
+                <span class="title">group</span><br>
+                <select name="group">
+                    <option value="root">root</option>
+                    <option value="www">www</option>
+                        <option value="apache">apache</option>
+                    </select>
+                </div>
+        </div>
 
+            <div class="mode">
+                <div class="col owner">
+                <span class="title">owner</span><br>
+                <label><span class="title">read</span> <input type="checkbox" name="owner-read" /></label><br />
+                <label><span class="title">write</span> <input type="checkbox" name="owner-write" /></label><br />
+                <label><span class="title">execute</span> <input type="checkbox" name="owner-execute" /></label><br />
+            </div>
+                <div class="col group">
+                <span class="title">group</span><br>
+                <label><span class="title">read</span> <input type="checkbox" name="group-read" /></label><br />
+                <label><span class="title">write</span> <input type="checkbox" name="group-write" /></label><br />
+                <label><span class="title">execute</span> <input type="checkbox" name="group-execute" /></label><br />
+            </div>
+                <div class="col other">
+                <span class="title">other</span><br>
+                <label><span class="title">read</span> <input type="checkbox" name="other-read" /></label><br />
+                <label><span class="title">write</span> <input type="checkbox" name="other-write" /></label><br />
+                <label><span class="title">execute</span> <input type="checkbox" name="other-execute" /></label><br />
+            </div>
+            </div>
+            <div class="recursive">
+                <label><span class="title">recursive</span> <input type="checkbox" name="recursive" /></label>
+            </div>
+        </div>
+        <div class="controls">
+            <p class="cancel">cancel</p>
+            <p class="ok rippler rippler-default">set</p>
+        </div>
+    </div>
+
+    </div--> <!-- popups -->
+
+
+    <div class="warning-box inform hidden">
+        <div class="close ripple"></div>
+        <div class="message">Please Read the reading text at the reading write!</div>
+        <div class="message-small">writing the reading text at the reading write writing the reading text at the reading write!</div>
+    </div>
+
+
+    <div class="warning-box hidden">
+        <div class="close ripple"></div>
+        <div class="message">Please Read the reading text at the reading write!</div>
+        <div class="message-small">writing the reading text at the reading write writing the reading text at the reading write!</div>
+    </div>
+
+
+    <ul class="context-menu tab-a sort-order hidden">
+        <li entity="type"><span class="type active">type</span><span class="up">&nbsp;</span></li>
+        <li entity="size"><span class="size">size</span><span class="up">&nbsp;</span></li>
+        <li entity="date"><span class="date">date</span><span class="up">&nbsp;</span></li>
+        <li entity="name" class="last"><span class="name">name</span><span class="up">&nbsp;</span></li>
+    </ul>
+
+    <ul class="context-menu tab-b sort-order hidden">
+        <li entity="type"><span class="type active">type</span><span class="up">&nbsp;</span></li>
+        <li entity="size"><span class="size">size</span><span class="up">&nbsp;</span></li>
+        <li entity="date"><span class="date">date</span><span class="up">&nbsp;</span></li>
+        <li entity="name" class="last"><span class="name">name</span><span class="up">&nbsp;</span></li>
+    </ul>
 
-<br><br>
 
 
-	<div class="confirm-box owner-mode warnin-g">
-	    <div class="message">Owner - Mode</div>
-	    <div class="warning">You have no rights to change owner, group or mode</div>
-	    <div class="actions">
-	        <div class="owner-group">
-	            <div class="owner col">
-		        <span class="title">owner</span><br>
-		        <select name="owner">
-		            <option value="root">root</option>
-		            <option value="bob">Bob</option>
-	                    <option value="ralph">Ralph</option>
-	                </select>
-	            </div>
-
-	            <div class="group col">
-		        <span class="title">group</span><br>
-		        <select name="group">
-		            <option value="root">root</option>
-		            <option value="www">www</option>
-	                    <option value="apache">apache</option>
-	                </select>
-	    	    </div>
-		</div>
-
-	        <div class="mode">
-	            <div class="col owner">
-		        <span class="title">owner</span><br>
-		        <label><span class="title">read</span> <input type="checkbox" name="owner-read" /></label><br />
-		        <label><span class="title">write</span> <input type="checkbox" name="owner-write" /></label><br />
-		        <label><span class="title">execute</span> <input type="checkbox" name="owner-execute" /></label><br />
-		    </div>
-	            <div class="col group">
-		        <span class="title">group</span><br>
-		        <label><span class="title">read</span> <input type="checkbox" name="group-read" /></label><br />
-		        <label><span class="title">write</span> <input type="checkbox" name="group-write" /></label><br />
-		        <label><span class="title">execute</span> <input type="checkbox" name="group-execute" /></label><br />
-		    </div>
-	            <div class="col other">
-		        <span class="title">other</span><br>
-		        <label><span class="title">read</span> <input type="checkbox" name="other-read" /></label><br />
-		        <label><span class="title">write</span> <input type="checkbox" name="other-write" /></label><br />
-		        <label><span class="title">execute</span> <input type="checkbox" name="other-execute" /></label><br />
-		    </div>
-	        </div>
-	        <div class="recursive">
-	            <label><span class="title">recursive</span> <input type="checkbox" name="recursive" /></label>
-	        </div>
-	    </div>
-	    <div class="controls">
-	        <p class="cancel">cancel</p>
-	        <p class="ok rippler rippler-default">set</p>
-	    </div>
-	</div>
-
-	</div--> <!-- popups -->
-
-
-	<div class="warning-box inform hidden">
-	    <div class="close ripple"></div>
-	    <div class="message">Please Read the reading text at the reading write!</div>
-	    <div class="message-small">writing the reading text at the reading write writing the reading text at the reading write!</div>
-	</div>
-
-
-	<div class="warning-box hidden">
-	    <div class="close ripple"></div>
-	    <div class="message">Please Read the reading text at the reading write!</div>
-	    <div class="message-small">writing the reading text at the reading write writing the reading text at the reading write!</div>
-	</div>
-
-
-	<ul class="context-menu tab-a sort-order hidden">
-	    <li entity="type"><span class="name active">type</span><span class="up">&nbsp;</span></li>
-	    <li entity="size"><span class="name">size</span><span class="up">&nbsp;</span></li>
-	    <li entity="date"><span class="name">date</span><span class="up">&nbsp;</span></li>
-	    <li entity="name" class="last"><span class="name">name</span><span class="up">&nbsp;</span></li>
-	</ul>
-
-	<ul class="context-menu tab-b sort-order hidden">
-	    <li entity="type"><span class="name active">type</span><span class="up">&nbsp;</span></li>
-	    <li entity="size"><span class="name">size</span><span class="up">&nbsp;</span></li>
-	    <li entity="date"><span class="name">date</span><span class="up">&nbsp;</span></li>
-	    <li entity="name" class="last"><span class="name">name</span><span class="up">&nbsp;</span></li>
-	</ul>
-
-
-
-	<div class="fotorama" data-auto="false"></div>
-
-
-        <!-- script src="/js/jquery-1.7.2.min.js"></script -->
-	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
-	<script src="//cdnjs.cloudflare.com/ajax/libs/fotorama/4.6.2/fotorama.js"></script>
-	<!-- script type="text/javascript" src="/js/jquery-ui-1.8.20.custom.min.js"></script -->
-	<script type="text/javascript" src="/js/jquery-ui.min.js"></script>
+            <div class="fotorama" data-auto="false"></div>
+            <div class="progress-container hidden">
+            <div class="progress-elm"><span class="title">Initializing</span><span class="progress" style="backround-position: -96px;  backround-position:-10px"></span><span class="close hidden"></span></div>
+        </div>
+
+        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
+        <script src="//cdnjs.cloudflare.com/ajax/libs/fotorama/4.6.2/fotorama.js"></script>
+        <script type="text/javascript" src="/js/jquery-ui.min.js"></script>
+        <script src="/js/jquery.finder.js"></script>
         <script type="text/javascript" src="/js/hotkeys.js"></script>
         <script type="text/javascript" src="/js/app.js"></script>
         <script type="text/javascript"><?php echo include($_SERVER['DOCUMENT_ROOT'].'/js/i18n.js.php'); ?></script>
         <script type="text/javascript" src="/js/templates.js"></script>
         <script type="text/javascript" src="/js/floating_layer.js"></script>
         <script src="/js/ripple.js"></script>
-        <!-- script src="/js/jquery.uploadify.min.js"></script -->
         <script src="/js/jquery.iframe-transport.js"></script>
         <script src="/js/jquery.fileupload.js"></script>
         <script src="/js/jquery.arcticmodal.js"></script>
@@ -307,9 +307,14 @@
             $(['A', 'B']).each(function(k, letter) {
                 var url = '/upload/';
                 $('#file_upload_' + letter).fileupload({
+                    singleFileUploads: false,
                     add: function (e, data) {
+                        FM.setTabActive(FM['TAB_'+letter]);
+                        
                         var tab = FM.getTabLetter(FM.CURRENT_TAB);
                         var file_relocation = FM['TAB_'+tab+'_CURRENT_PATH'];
+                        
+                        
 
                         $('#file_upload_' + letter).fileupload("option", "url", url + '?dir=' + file_relocation);
                         acc = $('<div>');
@@ -320,18 +325,39 @@
                     url: url,
                     dataType: 'json',
                     done: function (e, data) {
-                        /*$.each(data.result.files, function (index, file) {
-                            $(acc).append($('<p/>').text(file.name + ' uploaded.'));
-                        });*/
+                        var msg = '';
+                        $.each(data.result.files, function (index, file) {
+                            if ('undefined' != typeof file.error) {
+                                msg += '<p class="msg-item">' + file.name + ': ' + file.error + '</p>';
+                            }
+                        });
+
+                        if (msg != '') {
+                            var tpl = Tpl.get('popup_alert', 'FM');
+                            tpl.set(':TEXT', msg);
+                            FM.popupOpen(tpl.finalize());
+                        }
+                        //console.log(e);
+                        //console.log(data);
                     },
                     fail: function(e, data) {
+                        var msg = '';
                         $.each(data.result.files, function (index, file) {
-                            $(acc).append($('<p/>').text(file.name + ' failed to upload.'));
+                            if ('undefined' != typeof file.error) {
+                                msg += '<p class="msg-item">' + file.name + ': ' + file.error + '</p>';
+                            }
                         });
-                        show_msg = true;
+
+                        if (msg != '') {
+                            var tpl = Tpl.get('popup_alert', 'FM');
+                            tpl.set(':TEXT', msg);
+                            FM.popupOpen(tpl.finalize());
+                        }
+                        //console.log(e);
+                        //console.log(data);
                     },
                     always: function(e, data) {
-                        if (show_msg) {
+                        /*if (show_msg) {
                             clearTimeout(window.ht_fd);
                             var info = $('.warning-box.inform').clone(true);
                             $(info).attr('id', 'file-upload-msg');
@@ -346,7 +372,7 @@
                             window.ht_fd = setTimeout(function() {
                                 $('#file-upload-msg').fadeOut();
                             }, 3000);
-                        }
+                        }*/
                         
                         var tab = FM.getTabLetter(FM.CURRENT_TAB);
                         var box = FM['TAB_' + tab];
@@ -371,7 +397,99 @@
                 .prop('disabled', !$.support.fileInput)
                     .parent().addClass($.support.fileInput ? undefined : 'disabled');
             });
+            
+            $.widget("shift.selectable", $.ui.selectable, {
+                options: {}, // required
+                previousIndex: -1, // additional attribute to store previous selection index
+                currentIndex: -1, // additional attribute to store current selection index
+                _create: function() { // required
+                    var self = this;
+
+                    $.ui.selectable.prototype._create.call(this); // default implementation
+
+                    // here is our addition, we are catching "selecting" event with shift key
+                    $(this.element).on('selectableselecting', function(event, ui){
+                        self.currentIndex = $(ui.selecting.tagName, event.target).index(ui.selecting);
+                        if(event.shiftKey && self.previousIndex > -1) {
+                            $(ui.selecting.tagName, event.target).slice(Math.min(self.previousIndex, self.currentIndex), 1 + Math.max(self.previousIndex, self.currentIndex)).addClass('ui-selected');
+                            self.previousIndex = -1;
+                        } else {
+                            self.previousIndex = self.currentIndex;
+                        }
+                    });
+                },
+                destroy: function() { // required, default implementation
+                    $.ui.selectable.prototype.destroy.call(this);
+                },
+                _setOption: function() { // required, default implementation
+                    $.ui.selectable.prototype._setOption.apply(this, arguments);
+                }
+            });
+
+
+            var checkIfArchive = function(item) {console.log(item);
+                var item = $(item).hasClass('dir') ? item : $(item).parents('.dir');
+                var tab = FM.getTabLetter(FM.CURRENT_TAB);
+                var src = $(item).find('.source').val();
+                src = $.parseJSON(src);
+                var tab = FM.getTabLetter(FM.CURRENT_TAB);
+                if (FM.itemIsArchieve(src)) {
+                    $('.menu-'+tab+' .extract-btn').show();
+                }
+                else {
+                    $('.menu-'+tab+' .extract-btn').hide();
+                }
+            }
+            
+            
+            $(".listing-left").selectable({
+                selected: function (event, ui) {
+                    FM.setTabActive(FM.TAB_A, 'skip_highlights');
+                    $(".listing-left .selected").each(function(i, o) {
+                        if (!$(o).hasClass('ui-selected')) {
+                            $(o).removeClass('selected');
+                        }
+                    });
+                    $(ui.selected).addClass('selected');
+                    checkIfArchive(ui.selected);
+                    $(".listing-left .ui-selected").addClass('selected');
+                },
+                unselected: function (event, ui) {
+                    $(".listing-left .selected").each(function(i, o) {
+                        if (!$(o).hasClass('ui-selected')) {
+                            $(o).removeClass('selected');
+                        }
+                    });
+                    FM.setTabActive(FM.TAB_A, 'skip_highlights');
+                    $(ui.unselected).removeClass('selected');
+                }
+            });
+            $(".listing-right").selectable({
+                selected: function (event, ui) {
+                    $(".listing-left .selected").each(function(i, o) {
+                        if (!$(o).hasClass('ui-selected')) {
+                            $(o).removeClass('selected');
+                        }
+                    });
+                    FM.setTabActive(FM.TAB_B, 'skip_highlights');
+                    $(ui.selected).addClass('selected');
+                    checkIfArchive(ui.selected);
+                    $(".listing-left .ui-selected").addClass('selected');
+                },
+                unselected: function (event, ui) {
+                    $(".listing-left .selected").each(function(i, o) {
+                        if (!$(o).hasClass('ui-selected')) {
+                            $(o).removeClass('selected');
+                        }
+                    });
+                    FM.setTabActive(FM.TAB_B, 'skip_highlights');
+                    $(ui.unselected).removeClass('selected');
+                }
+            });
+           
+            
         });
         </script>
 </body>
 </html>
+

+ 26 - 7
web/templates/file_manager/tab_menu.php

@@ -6,12 +6,31 @@
     <!-- The file input field used as target for the file upload widget -->
     <input id="file_upload_<?php echo $pre_tab ?>" type="file" name="files[]" multiple>
 </span>
-<div class="mkfile button" onClick="FM.createFile()">CREATE FILE</div>
-<div class="mkdir button" onClick="FM.createDir()">CREATE DIR</div>
-<div class="mkdir button" onClick="FM.deleteItems()">DELETE</div>
-<div class="mkdir button" onClick="FM.renameItems()">RENAME</div>
+<div class="mkfile button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.createFile()">NEW FILE</div>
+<div class="mkfile button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.createFile()" title="Create File"></div>
+<div class="mkdir button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.createDir()">NEW DIR</div>
+<div class="mkdir button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.createDir()" title="Create Dir"></div>
+<div class="del button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.deleteItems()">DELETE</div>
+<div class="del button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.deleteItems()" title="Delete"></div>
+<div class="rename button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.renameItems()">RENAME</div>
+<div class="rename button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.renameItems()"title="Rename"></div>
+<div class="copy button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.copyItems()">COPY</div>
+<div class="copy button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.copyItems()" title="Copy"></div>
+<div class="archive button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.packItem()">ARCHIVE</div>
+<div class="archive button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.packItem()" title="Create Archive"></div>
+<div class="extract button extract-btn" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.unpackItem()">EXRACT</div>
+<div class="extract button small" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.unpackItem()" title="Extract Archive"></div>
+<div class="download button" onClick="FM.setTabActive(FM['TAB_<?php echo $pre_tab ?>']);FM.downloadFiles()">DOWNLOAD</div><!-- div class="total-size">0 Mb</div -->
 
-<div class="mkdir button" onClick="FM.copyItems()">COPY</div>
 
-<div class="download button" onClick="FM.downloadFiles()">DOWNLOAD</div><!-- div class="total-size">0 Mb</div -->
-<div class="sort-by button">SORT BY<span class="direction"></span><span class="entity">type</span><input type="hidden" class="sort-by-v" /></div>
+<? /* div class="" title="Bulk">
+    <select onChange="FM.bulkOperation(this)">
+        <option value="-1">Select bulk operation</option>
+        <option value="bulkCopy">Bulk copy</option>
+        <option value="bulkRemove">Bulk remove</option>
+    </select>
+</div */ ?><!-- div class="total-size">0 Mb</div -->
+
+
+<div class="sort-by button medium"><span class="direction"></span><span class="entity">type</span><input type="hidden" class="sort-by-v" /></div>
+<!-- div class="sort-by button">SORT BY<span class="direction"></span><span class="entity">type</span><input type="hidden" class="sort-by-v" /></div-->

Some files were not shown because too many files changed in this diff