Commit 1b0234cb authored by Mario's avatar Mario
Browse files

files_ng: implement drag and drop

parent bee277cd
Pipeline #370566 passed with stage
in 2 minutes and 55 seconds
......@@ -19,6 +19,8 @@ class Attach_edit extends Controller {
}
$attach_id = ((x($_POST, 'attach_id')) ? intval($_POST['attach_id']) : null);
$channel_id = ((x($_POST, 'channel_id')) ? intval($_POST['channel_id']) : null);
$dnd = ((x($_POST, 'dnd')) ? intval($_POST['dnd']) : null);
$nick = ((x($_POST, 'nick')) ? notags($_POST['nick']) : '');
$delete = ((x($_POST, 'delete')) ? intval($_POST['delete']) : 0);
$newfolder = ((x($_POST, 'newfolder_' . $attach_id)) ? notags($_POST['newfolder_' . $attach_id]) : '');
......@@ -33,7 +35,7 @@ class Attach_edit extends Controller {
return;
}
$channel = channelx_by_nick($nick);
$channel = channelx_by_n($channel_id);
if (! $channel) {
notice(t('Channel not found.') . EOL);
......@@ -41,11 +43,9 @@ class Attach_edit extends Controller {
}
$nick = $channel['channel_address'];
$channel_id = $channel['channel_id'];
$observer = App::get_observer();
$observer_hash = (($observer) ? $observer['xchan_hash'] : '');
$r = q("SELECT uid, hash, creator, folder, filename, is_photo FROM attach WHERE id = %d AND uid = %d",
intval($attach_id),
intval($channel_id)
......@@ -83,7 +83,7 @@ class Attach_edit extends Controller {
}
}
if(!$is_owner && !$admin_delete) {
if (!$is_owner && !$admin_delete) {
if(! $is_creator) {
notice( t('Permission denied.') . EOL);
return;
......@@ -137,8 +137,7 @@ class Attach_edit extends Controller {
);
}
if($is_owner) {
if ($is_owner && ! $dnd) {
$acl = new AccessList($channel);
$acl->set_from_array($_REQUEST);
$x = $acl->get();
......@@ -156,6 +155,10 @@ class Attach_edit extends Controller {
Libsync::build_sync_packet($channel_id, ['file' => [$sync]]);
}
if ($dnd) {
json_return_and_die([ 'success' => true ]);
}
$url = get_cloud_url($channel_id, $nick, $resource);
goaway(dirname($url));
......
......@@ -12,16 +12,16 @@ class File_upload extends \Zotlabs\Web\Controller {
function post() {
logger('file upload: ' . print_r($_REQUEST,true));
hz_syslog('file upload: ' . print_r($_REQUEST,true));
logger('file upload: ' . print_r($_FILES,true));
$channel = (($_REQUEST['channick']) ? channelx_by_nick($_REQUEST['channick']) : null);
if(! $channel) {
logger('channel not found');
killme();
}
$_REQUEST['source'] = 'file_upload';
if($channel['channel_id'] != local_channel()) {
......@@ -83,7 +83,7 @@ class File_upload extends \Zotlabs\Web\Controller {
];
}
}
else {
else {
if(! array_key_exists('userfile',$_FILES)) {
$_FILES['userfile'] = [
'name' => $_FILES['files']['name'],
......@@ -104,7 +104,7 @@ class File_upload extends \Zotlabs\Web\Controller {
}
}
goaway(z_root() . '/' . $_REQUEST['return_url']);
}
}
......@@ -83,7 +83,6 @@ class Browser extends DAV\Browser\Plugin {
// (owner_id = channel_id) is visitor owner of this directory?
$is_owner = ((local_channel() && $this->auth->owner_id == local_channel()) ? true : false);
$cat = ((x($_REQUEST,'cat')) ? $cat : '');
if ($this->auth->getTimezone()) {
......@@ -97,6 +96,10 @@ class Browser extends DAV\Browser\Plugin {
$files = $this->server->getPropertiesForPath($path, [], 1);
$parent = $this->server->tree->getNodeForPath($path);
$arr = explode('/', $parent->os_path);
end($arr);
$folder_parent = isset($arr[1]) ? prev($arr) : '';
$parent_path = [];
// only show parent if not leaving /cloud/; TODO how to improve this?
......@@ -111,13 +114,14 @@ class Browser extends DAV\Browser\Plugin {
$folder_list = attach_folder_select_list($this->auth->owner_id);
$nick = $this->auth->owner_nick;
$owner = $this->auth->owner_id;
$channel_id = $this->auth->owner_id;
$is_root_folder = ((basename($path) === $nick) ? true : false);
$f = [];
foreach ($files as $file) {
$ft = [];
$type = null;
......@@ -130,7 +134,7 @@ class Browser extends DAV\Browser\Plugin {
$node = $this->server->tree->getNodeForPath($href);
$data = $node->data;
$attach_hash = $data['hash'];
$parent_hash = $node->folder_hash;
$folder_hash = $node->folder_hash;
list(, $filename) = \Sabre\Uri\split($href);
......@@ -152,22 +156,22 @@ class Browser extends DAV\Browser\Plugin {
// Some name mapping is preferred
switch ($v) {
case '{DAV:}collection' :
$type[$k] = t('Collection');
$type[$k] = 'Collection';
break;
case '{DAV:}principal' :
$type[$k] = t('Principal');
$type[$k] = 'Principal';
break;
case '{urn:ietf:params:xml:ns:carddav}addressbook' :
$type[$k] = t('Addressbook');
$type[$k] = 'Addressbook';
break;
case '{urn:ietf:params:xml:ns:caldav}calendar' :
$type[$k] = t('Calendar');
$type[$k] = 'Calendar';
break;
case '{urn:ietf:params:xml:ns:caldav}schedule-inbox' :
$type[$k] = t('Schedule Inbox');
$type[$k] = 'Schedule Inbox';
break;
case '{urn:ietf:params:xml:ns:caldav}schedule-outbox' :
$type[$k] = t('Schedule Outbox');
$type[$k] = 'Schedule Outbox';
break;
case '{http://calendarserver.org/ns/}calendar-proxy-read' :
$type[$k] = 'Proxy-Read';
......@@ -226,31 +230,32 @@ class Browser extends DAV\Browser\Plugin {
$lockstate = (($data['allow_cid'] || $data['allow_gid'] || $data['deny_cid'] || $data['deny_gid']) ? 'lock' : 'unlock');
$id = $data['id'];
$terms = q("select * from term where oid = %d AND otype = %d",
intval($id),
intval(TERM_OBJ_FILE)
);
$categories = [];
$terms_str = '';
if($terms) {
foreach($terms as $t) {
$term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
if(! trim($term))
continue;
$categories[] = array('term' => $term, 'url' => $t['url']);
if ($terms_str)
$terms_str .= ',';
$terms_str .= $term;
if($id) {
$terms = q("select * from term where oid = %d AND otype = %d",
intval($id),
intval(TERM_OBJ_FILE)
);
$categories = [];
$terms_str = '';
if($terms) {
foreach($terms as $t) {
$term = htmlspecialchars($t['term'],ENT_COMPAT,'UTF-8',false) ;
if(! trim($term))
continue;
$categories[] = array('term' => $term, 'url' => $t['url']);
if ($terms_str)
$terms_str .= ',';
$terms_str .= $term;
}
$ft['terms'] = replace_macros(get_markup_template('item_categories.tpl'),array(
'$categories' => $categories
));
}
$ft['terms'] = replace_macros(get_markup_template('item_categories.tpl'),array(
'$categories' => $categories
));
}
// put the array for this file together
$ft['attach_id'] = $id;
$ft['fileStorageUrl'] = substr($href, 0, strpos($href, "/cloud/")) . "/filestorage/" . $this->auth->owner_nick;
$ft['icon'] = $icon;
$ft['photo_icon'] = $photo_icon;
$ft['is_owner'] = $is_owner;
......@@ -286,7 +291,7 @@ class Browser extends DAV\Browser\Plugin {
$folders = $folder_list;
if($data['is_dir']) {
// can not copy a folder into itself
unset($folders[$parent_hash]);
unset($folders[$folder_hash]);
}
$ft['newfolder'] = ['newfolder_' . $id, t('Select a target location'), $data['folder'], '', $folders];
......@@ -325,6 +330,9 @@ class Browser extends DAV\Browser\Plugin {
'$is_admin' => is_site_admin(),
'$admin_delete' => t('Admin Delete'),
'$parentpath' => $parent_path,
'$folder_parent' => $folder_parent,
'$folder' => $parent->folder_hash,
'$is_root_folder' => $is_root_folder,
'$cpath' => bin2hex(App::$query_string),
'$tiles' => intval($_SESSION['cloud_tiles']),
'$entries' => $f,
......@@ -335,7 +343,7 @@ class Browser extends DAV\Browser\Plugin {
'$parent' => t('parent'),
'$edit' => t('Submit'),
'$delete' => t('Delete'),
'$nick' => $nick,
'$channel_id' => $channel_id,
'$cpdesc' => t('Copy/paste this code to attach file to a post'),
'$cpldesc' => t('Copy/paste this URL to link file from a web page'),
......@@ -377,6 +385,7 @@ class Browser extends DAV\Browser\Plugin {
// SimpleCollection, we won't need to show the panel either.
if (get_class($node) === 'Sabre\\DAV\\SimpleCollection')
return;
require_once('include/acl_selectors.php');
$aclselect = null;
......@@ -432,7 +441,6 @@ class Browser extends DAV\Browser\Plugin {
if(strpos($path,$special) === 0)
$path = trim(substr($path,$count),'/');
$output .= replace_macros(get_markup_template('cloud_actionspanel.tpl'), array(
'$folder_header' => t('Create new folder'),
'$folder_submit' => t('Create'),
......@@ -448,7 +456,7 @@ class Browser extends DAV\Browser\Plugin {
'$lockstate' => $lockstate,
'$return_url' => \App::$cmd,
'$path' => $path,
'$folder' => find_folder_hash_by_path($this->auth->owner_id, $path),
'$folder' => $node->folder_hash,
'$dragdroptext' => t('Drop files here to immediately upload'),
'$notify' => ['notify', t('Show in your contacts shared folder'), 0, '', [t('No'), t('Yes')]]
));
......
......@@ -44,7 +44,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
*
* @var string $os_path
*/
private $os_path = '';
public $os_path = '';
/**
* @brief Sets up the directory node, expects a full path.
......@@ -704,21 +704,21 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo
if ($cat) {
$r = q("select $prefix attach.id, attach.uid, attach.hash, attach.filename,
attach.filetype, attach.filesize, attach.revision, attach.folder, attach.creator,
attach.flags, attach.is_dir, attach.created, attach.edited, attach.display_path,
attach.allow_cid, attach.allow_gid, attach.deny_cid, attach.deny_gid from attach
left join term on attach.id = term.oid
where term.term = '%s' and attach.uid = %d $perms $suffix",
attach.filetype, attach.filesize, attach.revision, attach.folder, attach.creator,
attach.flags, attach.is_dir, attach.created, attach.edited, attach.display_path,
attach.allow_cid, attach.allow_gid, attach.deny_cid, attach.deny_gid from attach
left join term on attach.id = term.oid
where term.term = '%s' and attach.uid = %d $perms $suffix",
dbesc($cat),
intval($channel_id)
);
}
else {
$r = q("select $prefix attach.id, attach.uid, attach.hash, attach.filename,
attach.filetype, attach.filesize, attach.revision, attach.folder, attach.creator,
attach.flags, attach.is_dir, attach.created, attach.edited, attach.display_path,
attach.allow_cid, attach.allow_gid, attach.deny_cid, attach.deny_gid from attach
where folder = '%s' and uid = %d $perms $suffix",
attach.filetype, attach.filesize, attach.revision, attach.folder, attach.creator,
attach.flags, attach.is_dir, attach.created, attach.edited, attach.display_path,
attach.allow_cid, attach.allow_gid, attach.deny_cid, attach.deny_gid from attach
where folder = '%s' and uid = %d $perms $suffix",
dbesc($folder),
intval($channel_id)
);
......
......@@ -2513,7 +2513,7 @@ function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpat
* * \e boolean \b success
* * \e string \b resource_id
*/
function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '', $check_dupes = true) {
function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '', $recurse = true) {
$ret = [
'success' => false,
......@@ -2524,9 +2524,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
if(! ($c && $resource_id))
return $ret;
// find the resource to be moved
$r = q("select * from attach where hash = '%s' and uid = %d limit 1",
dbesc($resource_id),
intval($channel_id)
......@@ -2539,7 +2537,6 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
$oldstorepath = dbunescbin($r[0]['content']);
// find the resource we are moving to
if($new_folder_hash) {
$n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1",
dbesc($new_folder_hash),
......@@ -2553,24 +2550,21 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
$newstorepath = dbunescbin($n[0]['content']) . '/' . $resource_id;
}
else {
// root directory
$newdirname = EMPTY_STR;
$newalbumname = EMPTY_STR;
$newstorepath = 'store/' . $c['channel_address'] . '/' . $resource_id;
}
if (file_exists($oldstorepath))
if ($recurse) {
rename($oldstorepath,$newstorepath);
}
$oldfilename = $r[0]['filename'];
$filename = (($newname) ? basename($newname) : $oldfilename);
// duplicate detection.
if($check_dupes) {
$s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ",
dbesc($filename),
dbesc($new_folder_hash)
......@@ -2621,11 +2615,11 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
while($found);
$filename = $basename . '(' . $x . ')' . $ext;
}
else
else {
$filename = $basename . $ext;
}
}
}
}
......@@ -2669,8 +2663,10 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
dbesc($resource_id)
);
foreach($ps as $p) {
rename($oldstorepath . '-' . $p['imgscale'], $p['content']);
if ($recurse) {
foreach($ps as $p) {
rename($oldstorepath . '-' . $p['imgscale'], $p['content']);
}
}
}
......@@ -2717,7 +2713,7 @@ function attach_move($channel_id, $resource_id, $new_folder_hash, $newname = '',
* * \e boolean \b success
* * \e string \b resource_id of the new resource
*/
function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '', $check_dupes = true) {
function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '', $recurse = true) {
$ret = [
'success' => false,
......@@ -2728,8 +2724,7 @@ function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '',
if(! ($c && $resource_id))
return $ret;
// find the resource to be moved
// find the resource to be copied
$r = q("select * from attach where hash = '%s' and uid = %d limit 1",
dbesc($resource_id),
intval($channel_id)
......@@ -2747,7 +2742,6 @@ function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '',
$oldstorepath = dbunescbin($r[0]['content']);
// find the resource we are copying to
if($new_folder_hash) {
$n = q("select * from attach where hash = '%s' and uid = %d and is_dir = 1 limit 1",
dbesc($new_folder_hash),
......@@ -2763,25 +2757,24 @@ function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '',
$newstorepath = dbunescbin($n[0]['content']) . '/' . $new_resource_id;
}
else {
// root directory
$newdirname = EMPTY_STR;
$newalbumname = EMPTY_STR;
$newstorepath = 'store/' . $c['channel_address'] . '/' . $new_resource_id;
}
if(is_dir($oldstorepath))
if(is_dir($oldstorepath)) {
os_mkdir($newstorepath,STORAGE_DEFAULT_PERMISSIONS,true);
else
}
else {
copy($oldstorepath,$newstorepath);
}
$oldfilename = $r[0]['filename'];
$filename = (($newname) ? basename($newname) : $oldfilename);
// duplicate detection. If 'overwrite' is specified, return false because we can't yet do that.
if($check_dupes) {
if($recurse) {
$s = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ",
dbesc($filename),
dbesc($new_folder_hash)
......@@ -2831,8 +2824,9 @@ function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '',
while($found);
$filename = $basename . '(' . $x . ')' . $ext;
}
else
else {
$filename = $basename . $ext;
}
}
}
}
......@@ -2874,9 +2868,7 @@ function attach_copy($channel_id, $resource_id, $new_folder_hash, $newname = '',
if($p['imgscale'] > 0)
copy($oldstorepath, $p['content']);
}
create_table_from_array('photo', $p, ['content']);
}
}
......
......@@ -64,6 +64,19 @@
box-shadow: inset 0 0px 7px #5cb85c;
}
.attach-drop-ok {
background-color: aliceblue;
}
.attach-drop-zone {
border-top-width: 3px;
border-top-style: dashed;
border-top-color: #eee;
border-bottom-width: 3px;
border-bottom-style: dashed;
border-bottom-color: #eee;
}
.upload-progress-bar {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOM2RFTDwAE2QHxFMHIIwAAAABJRU5ErkJggg==') repeat-y;
background-size: 0px;
......
......@@ -3,11 +3,15 @@
*/
$(document).ready(function () {
// call initialization file
if (window.File && window.FileList && window.FileReader) {
UploadInit();
}
var attach_drop_id;
var attach_draging;
$('.cloud-tool-perms-btn').on('click', function (e) {
e.preventDefault();
let id = $(this).data('id');
......@@ -76,7 +80,7 @@ $(document).ready(function () {
$.post('attach_edit', form, function (data) {
if (data.success) {
$('#cloud-index-' + id).remove();
$('#cloud-index-' + id + ', #cloud-tools-' + id).remove();
$('body').css('cursor', 'auto');
}
return true;
......@@ -86,7 +90,6 @@ $(document).ready(function () {
return false;
});
$('.cloud-tool-cancel-btn').on('click', function (e) {
e.preventDefault();
let id = $(this).data('id');
......@@ -97,15 +100,98 @@ $(document).ready(function () {
});
// DnD
$(document).on('drop', function (e) {
e.preventDefault();
e.stopPropagation();
});
$(document).on('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
});
$(document).on('dragleave', function (e) {
e.preventDefault();
e.stopPropagation();
});
$('.cloud-index.attach-drop').on('drop', function (e) {
let target = $(this);
let folder = target.data('folder');
let id = target.data('id');
if(typeof folder === typeof undefined) {
return false;
}
// Check if it's a file
if (e.dataTransfer.files[0]) {
$('#file-directory').val('');
//folder = $('.attach-drop-zone').data('folder');
$('#file-folder').val(folder);
return true;
}
if(id === attach_drop_id) {
return false;
}
if(target.hasClass('attach-drop-zone') && attach_draging) {
return false;
}
target.removeClass('attach-drop-ok');
$.post('attach_edit', {'channel_id': channelId, 'dnd': 1, 'attach_id': attach_drop_id, ['newfolder_' + attach_drop_id]: folder }, function (data) {
if (data.success) {
$('#cloud-index-' + attach_drop_id + ', #cloud-tools-' + attach_drop_id).remove();
attach_drop_id = null;
}
});
});
$('.cloud-index.attach-drop').on('dragover', function (e) {
let target = $(this);
if(target.hasClass('attach-drop-zone') && attach_draging) {
return false;
}
target.addClass('attach-drop-ok');
});
$('.cloud-index').on('dragleave', function (e) {
let target = $(this);
target.removeClass('attach-drop-ok');
});
$('.cloud-index').on('dragstart', function (e) {
let target = $(this);
attach_drop_id = target.data('id');
// dragstart is not fired if a file is draged onto the window
// we use this to distinguish between drags and file drops
attach_draging = true;
});
$('.cloud-index').on('dragend', function (e) {
let target = $(this);
target.removeClass('attach-drop-ok');
attach_draging = false;
});
});
// initialize
function UploadInit() {
var fileselect = $("#files-upload");
var filedrag = $("#cloud-drag-area");
var submit = $("#upload-submit");
var count = 1;
var filedrag = $(".cloud-index.attach-drop");
$('#invisible-cloud-file-upload').fileupload({
url: 'file_upload',
......@@ -137,7 +223,6 @@ function UploadInit