/**
* EGroupware eTemplate2 - JS VFS widgets
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link https://www.egroupware.org
* @author Nathan Gray
* @copyright Nathan Gray 2012
*/
var _a;
/*egw:uses
/vendor/bower-asset/jquery/dist/jquery.js;
vfsSelectUI;
et2_core_inputWidget;
et2_core_valueWidget;
et2_widget_description;
et2_widget_file;
expose;
*/
import { et2_valueWidget } from "./et2_core_valueWidget";
import { et2_createWidget, et2_register_widget } from "./et2_core_widget";
import { ClassWithAttributes } from "./et2_core_inheritance";
import { et2_textbox, et2_textbox_ro } from "./et2_widget_textbox";
import { et2_description } from "./et2_widget_description";
import { et2_selectAccount_ro } from "./et2_widget_selectAccount";
import { et2_file } from "./et2_widget_file";
import { et2_dialog } from "./et2_widget_dialog";
import { et2_inputWidget } from "./et2_core_inputWidget";
import { et2_no_init } from "./et2_core_common";
import { egw, egw_get_file_editor_prefered_mimes } from "../jsapi/egw_global";
import { expose } from "./expose";
import { egw_getAppObjectManager } from "../egw_action/egw_action.js";
import { egw_keyHandler } from '../egw_action/egw_keymanager.js';
import { EGW_KEY_ENTER } from '../egw_action/egw_action_constants.js';
import { etemplate2 } from "./etemplate2";
/**
* Class which implements the "vfs" XET-Tag
*
* @augments et2_valueWidget
*/
export class et2_vfs extends et2_valueWidget {
/**
* Constructor
*
* @memberOf et2_vfs
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfs._attributes, _child || {}));
this.span = null;
this.value = "";
this.span = jQuery(document.createElement("ul"))
.addClass('et2_vfs');
this.setDOMNode(this.span[0]);
}
getValue() {
return this.value;
}
set_value(_value) {
if (typeof _value !== 'object') {
// Only warn if it's an actual value, just blank for falsy values
if (_value) {
this.egw().debug("warn", "%s only has path, needs full array", this.id, _value);
}
this.span.empty().text(_value);
return;
}
this.span.empty();
this.value = _value;
let path = _value.path ? _value.path : '/';
// calculate path as parent of name, which can contain slashes
// eg. _value.path=/home/ralf/sub/file, _value.name=sub/file --> path=/home/ralf
// --> generate clickable fields for sub/ + file
let sub_path = path.substring(0, _value.path.length - _value.name.length - 1);
let path_offset, path_parts;
if (_value.path.indexOf(_value.name) >= 0 && sub_path[sub_path.length - 1] === '/') {
path = sub_path;
path_offset = path.split('/').length;
path_parts = _value.path.split('/');
}
else {
if (_value.path.indexOf(_value.name) >= 0) {
// Remove name from end, so we can add it again later
path = sub_path;
}
path_offset = 0;
path_parts = _value.name.split('/');
}
let text;
for (let i = path_offset; i < path_parts.length; i++) {
path += (path == '/' ? '' : '/') + path_parts[i];
text = egw.decodePath(path_parts[i]);
// Nice human-readable stuff for apps
if (path_parts[1] == 'apps') {
switch (path_parts.length) {
case 2:
if (i == 1) {
text = this.egw().lang('applications');
}
break;
case 3:
if (i == 2) {
text = this.egw().lang(path_parts[2]);
}
break;
case 4:
if (!isNaN(text)) {
let link_title = this.egw().link_title(path_parts[2], path_parts[3], function (title) {
if (!title || this.value.name == title)
return;
jQuery('li', this.span).last().text(title);
}, this);
if (link_title && typeof link_title !== 'undefined')
text = link_title;
}
break;
}
}
let self = this;
var data = { path: path, type: i < path_parts.length - 1 ? et2_vfs.DIR_MIME_TYPE : _value.mime };
var node = jQuery(document.createElement("li"))
.addClass("vfsFilename")
.text(text + (i < path_parts.length - 1 ? '/' : ''))
//.attr('title', egw.decodePath(path))
.addClass("et2_clickable et2_link")
.click({ data: data, egw: this.egw() }, function (e) {
if (!self.onclick) {
e.data.egw.open(e.data.data, "file");
}
else if (self.click(e)) {
e.data.egw.open(e.data.data, "file");
}
})
.appendTo(this.span);
}
// Last part of path do default action
this._bind_default_action(node, data);
}
_bind_default_action(node, data) {
let links = [];
let widget = this;
let defaultAction = null;
let object = null;
let app = this.getInstanceManager().app;
while (links.length === 0 && widget.getParent()) {
object = egw_getAppObjectManager(app).getObjectById(widget.id);
if (object && object.manager && object.manager.children) {
links = object.manager.children;
}
widget = widget.getParent();
}
for (let k in links) {
if (links[k].default && links[k].enabled.exec(links[k])) {
defaultAction = links[k];
break;
}
}
if (defaultAction && !this.onclick) {
node.off('click').click({ data: data, egw: this.egw() }, function (e) {
// Wait until object selection happens
window.setTimeout(function () {
// execute default action
egw_keyHandler(EGW_KEY_ENTER, false, false, false);
});
// Select row
return true;
}.bind({ data: data, object: object }));
}
}
/**
* Code for implementing et2_IDetachedDOM (data grid)
*
* @param {array} _attrs array of attribute-names to push further names onto
*/
getDetachedAttributes(_attrs) {
_attrs.push("value");
}
getDetachedNodes() {
return [this.span[0]];
}
setDetachedAttributes(_nodes, _values) {
this.span = jQuery(_nodes[0]);
if (typeof _values["value"] != 'undefined') {
this.set_value(_values["value"]);
}
}
}
et2_vfs._attributes = {
"value": {
"type": "any",
"description": "Array of (stat) information about the file"
}
};
/**
* Mime type of directories
*/
et2_vfs.DIR_MIME_TYPE = 'httpd/unix-directory';
et2_register_widget(et2_vfs, ["vfs"]);
/**
* vfs-name
* filename automatically urlencoded on return (urldecoded on display to user)
*
* @augments et2_textbox
*/
export class et2_vfsName extends et2_textbox {
/**
* Constructor
*
* @memberOf et2_vfsName
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsName._attributes, _child || {}));
this.input.addClass("et2_vfs");
}
set_value(_value) {
if (_value.path) {
_value = _value.path;
}
try {
_value = egw.decodePath(_value);
}
catch (e) {
_value = 'Error! ' + _value;
}
super.set_value(_value);
}
getValue() {
return egw.encodePath(super.getValue() || '');
}
}
et2_register_widget(et2_vfsName, ["vfs-name"]);
/**
* vfs-name
* filename automatically urlencoded on return (urldecoded on display to user)
*
* @augments et2_textbox
*/
export class et2_vfsPath extends et2_vfsName {
/**
* Constructor
*
* @memberOf et2_vfsName
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsPath._attributes, _child || {}));
}
createInputWidget() {
super.createInputWidget();
this.div = jQuery(document.createElement("div"))
.addClass('et2_vfsPath');
this.span = jQuery(document.createElement("ul"))
.appendTo(this.div);
this.div.prepend(this.input);
this.setDOMNode(this.div[0]);
this.span.on('wheel', function (e) {
var delta = e.originalEvent["deltaY"] > 0 ? 30 : -30;
this.scrollLeft = this.scrollLeft - delta;
});
this.span.on('mouseover', function (e) {
if (this.scrollWidth > this.clientWidth) {
jQuery(this).addClass('scrollable');
}
else {
jQuery(this).removeClass('scrollable');
}
});
this.input.on('focus', function () {
this.input.val(this.options.value);
this.span.hide();
}.bind(this))
.on('focusout', function () {
// Can't use show() because it uses the wrong display
this.span.css('display', 'flex');
this.input.val('');
}.bind(this));
}
change(_node) {
if (this.input.val()) {
this.set_value(this.input.val());
}
return super.change(_node);
}
set_value(_value) {
if (_value.path) {
_value = _value.path;
}
if (_value === this.options.value && this._oldValue !== et2_no_init)
return;
let path_parts = _value.split('/');
if (_value === '/')
path_parts = [''];
let path = "/";
let text = '';
if (this.span)
this.span.empty().css('display', 'flex');
this.input.val('');
for (let i = 0; i < path_parts.length; i++) {
path += (path == '/' ? '' : '/') + path_parts[i];
text = egw.decodePath(path_parts[i]);
let image = path == '/' ? this.egw().image('navbar', 'api') : this.egw().image(text);
// Nice human-readable stuff for apps
if (path_parts[1] == 'apps') {
if (i === 1) {
text = this.egw().lang('applications');
}
else if (i === 2) {
text = this.egw().lang(path_parts[2]);
image = this.egw().image('navbar', path_parts[2].toLowerCase());
}
else if (!isNaN(text)) {
let link_title = this.egw().link_title(path_parts[2], path_parts[3], function (title) {
if (!title)
return;
jQuery('li', this.span).first().text(title);
}, this);
if (link_title && typeof link_title !== 'undefined')
text = link_title;
}
}
let self = this;
let node = jQuery(document.createElement("li"))
.addClass("vfsPath et2_clickable")
.text(text)
//.attr('title', egw.decodePath(path))
.click({ data: path, egw: this.egw() }, function (e) {
return self.set_value(e.data.data);
})
.prependTo(this.span);
if (image && !this.options.noicon) {
node.prepend(this.egw().image_element(image));
}
jQuery(this.getDOMNode()).append(this.span);
}
if (this.isAttached() && this.options.value !== _value) {
this._oldValue = this.options.value;
this.options.value = _value;
this.change();
}
}
getValue() {
return this.options ? this.options.value : null;
}
}
et2_vfsPath._attributes = {
noicon: {
type: "boolean",
description: "suppress folder icons",
default: true
}
};
et2_register_widget(et2_vfsPath, ["vfs-path"]);
/**
* vfs-name
* filename automatically urlencoded on return (urldecoded on display to user)
*
* @augments et2_textbox_ro
*/
export class et2_vfsName_ro extends et2_textbox_ro {
/**
* Constructor
*
* @memberOf et2_vfsName_ro
*/
/**
* Constructor
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsName_ro._attributes, _child || {}));
}
set_value(_value) {
if (_value.path) {
_value = _value.path;
}
try {
_value = egw.decodePath(_value);
}
catch (e) {
_value = 'Error! ' + _value;
}
super.set_value(_value);
}
getValue() {
return egw.encodePath(super.getValue() || '');
}
}
et2_register_widget(et2_vfsName_ro, ["vfs-name_ro"]);
/**
* vfs-mime: icon for mimetype of file, or thumbnail
* incl. optional link overlay icon, if file is a symlink
*
* Creates following structure
*
*
*
*
*
* span.overlayContainer is optional and only generated for symlinks
* @augments et2_valueWidget
*/
export class et2_vfsMime extends expose((_a = class et2_vfsMime extends et2_valueWidget {
/**
* Constructor
*
* @memberOf et2_vfsMime
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsMime._attributes, _child || {}));
this.iconOverlayContainer = null;
this.image = null;
this.iconOverlayContainer = jQuery(document.createElement('span')).addClass('iconOverlayContainer');
this.image = jQuery(document.createElement("img"));
this.image.addClass("et2_vfs vfsMimeIcon");
this.iconOverlayContainer.append(this.image);
this.setDOMNode(this.iconOverlayContainer[0]);
}
/**
* Handler for expose slide action, from expose
* Returns data needed for the given index, or false to let expose handle it
*
* @param {Gallery} gallery
* @param {integer} index
* @param {DOMNode} slide
* @return {Array} array of objects consist of media contnet
*/
expose_onslide(gallery, index, slide) {
var content = false;
if (this.options.expose_callback && typeof this.options.expose_callback == 'function') {
//Call the callback to load more items
content = this.options.expose_callback.call(this, [gallery, index]);
if (content)
this.add(content);
}
return content;
}
/**
* Function to get media content to feed the expose
*
* @param {type} _value
* @returns {Array} return an array of object consists of media content
*/
getMedia(_value) {
let base_url = egw.webserverUrl.match(/^\/ig/) ? egw(window).window.location.origin + egw.webserverUrl : egw.webserverUrl;
let mediaContent = [{
title: _value.name,
type: _value.mime,
href: _value.download_url
}];
// check if download_url is not already an url (some stream-wrappers allow to specify that!)
if (_value.download_url && (_value.download_url[0] == '/' || _value.download_url.substr(0, 4) != 'http')) {
mediaContent[0].href = base_url + _value.download_url;
if (mediaContent[0].href && mediaContent[0].href.match(/\/webdav.php/, 'ig')) {
mediaContent[0]["download_href"] = mediaContent[0].href + '?download';
}
}
if (_value && _value.mime && _value.mime.match(/video\//, 'ig')) {
mediaContent[0]["thumbnail"] = this.egw().mime_icon(_value.mime, _value.path, undefined, _value.mtime);
}
else {
mediaContent[0]["thumbnail"] = _value.path && _value.mime ?
this.egw().mime_icon(_value.mime, _value.path, undefined, _value.mtime) :
this.image.attr('src') + '&thheight=128';
}
return mediaContent;
}
set_value(_value) {
if (typeof _value !== 'object') {
this.egw().debug("warn", "%s only has path, needs array with path & mime", this.id, _value);
// Keep going, will be 'unknown type'
}
let src = this.egw().mime_icon(_value.mime, _value.path, undefined, _value.mtime);
if (src) {
// Set size of thumbnail
if (src.indexOf("thumbnail.php") > -1) {
if (this.options.size) {
src += "&thsize=" + this.options.size;
}
else if (this.options.thumb_mime_size) {
let mime_size = this.options.thumb_mime_size.split(',');
let mime_regex = RegExp(_value.mime.split('/')[0]);
if (typeof mime_size != 'undefined' && jQuery.isArray(mime_size)
&& !isNaN(mime_size[mime_size.length - 1]) && isNaN(mime_size[0]) && this.options.thumb_mime_size.match(mime_regex[0], 'ig')) {
src += "&thsize=" + mime_size[mime_size.length - 1];
}
}
this.image.css("max-width", "100%");
}
this.image.attr("src", src);
// tooltip for mimetypes with available detailed thumbnail
if (_value.mime && _value.mime.match(/application\/vnd\.oasis\.opendocument\.(text|presentation|spreadsheet|chart)/)) {
let tooltip_target = this.image.parent().parent().parent().length > 0 ?
// Nextmatch row
this.image.parent().parent().parent() :
// Not in nextmatch
this.image.parent();
tooltip_target.tooltip({
items: "img",
position: { my: "right top", at: "left top", collision: "flipfit" },
content: function () {
return '
';
}
});
}
}
// add/remove link icon, if file is (not) a symlink
if ((_value.mode & et2_vfsMode.types.l) == et2_vfsMode.types.l) {
if (typeof this.overlayContainer == 'undefined') {
this.overlayContainer = jQuery(document.createElement('span')).addClass('overlayContainer');
this.overlayContainer.append(jQuery(document.createElement('img'))
.addClass('overlay').attr('src', this.egw().image('link', 'etemplate')));
this.iconOverlayContainer.append(this.overlayContainer);
}
}
else if (typeof this.overlayContainer != 'undefined') {
this.overlayContainer.remove();
delete this.overlayContainer;
}
}
/**
* Implementation of "et2_IDetachedDOM" for fast viewing in gridview
* Override to add needed attributes
*
* @param {array} _attrs array of attribute-names to push further names onto
*/
getDetachedAttributes(_attrs) {
_attrs.push("value", "class");
}
getDetachedNodes() {
return [this.node, this.iconOverlayContainer[0], this.image[0]];
}
setDetachedAttributes(_nodes, _values) {
this.iconOverlayContainer = jQuery(_nodes[1]);
this.image = jQuery(_nodes[2]);
this.node = _nodes[0];
this.overlayContainer = _nodes[0].children[1];
if (typeof _values['class'] != "undefined") {
this.image.addClass(_values['class']);
}
if (typeof _values['value'] != "undefined") {
this.set_value(_values['value']);
}
}
},
_a._attributes = {
"value": {
"type": "any",
"description": "Array of (stat) information about the file"
},
"size": {
"name": "Icon size",
"type": "integer",
"description": "Size of icon / thumbnail, in pixels",
"default": et2_no_init
},
"expose_callback": {
"name": "expose_callback",
"type": "js",
"default": et2_no_init,
"description": "JS code which is executed when expose slides."
},
expose_view: {
name: "Expose view",
type: "boolean",
default: true,
description: "Clicking on an image would popup an expose view"
},
thumb_mime_size: {
name: "Image thumbnail size",
type: "string",
default: "",
description: " Size of thumbnail in pixel for specified mime type with syntax of: mime_type(s),size (eg. image,video,128)"
}
},
_a.legacyOptions = ["size"],
_a)) {
}
;
et2_register_widget(et2_vfsMime, ["vfs-mime"]);
/**
* vfs-size
* Human readable file sizes
*
* @augments et2_description
*/
export class et2_vfsSize extends et2_description {
/**
* Constructor
*
* @memberOf et2_vfsSize
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsSize._attributes, _child || {}));
this.span.addClass("et2_vfs");
}
human_size(size) {
if (typeof size !== "number") {
size = parseInt(size);
}
if (!size) {
size = 0;
}
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let i = 0;
while (size >= 1024) {
size /= 1024;
++i;
}
return size.toFixed(i == 0 ? 0 : 1) + ' ' + units[i];
}
set_value(_value) {
if (_value.size) {
_value = _value.size;
}
jQuery(this.node).text(this.human_size(_value));
}
setDetachedAttributes(_nodes, _values) {
if (typeof _values["value"] !== "undefined") {
this.node = _nodes[0];
this.set_value(_values["value"]);
delete _values["value"];
}
super.setDetachedAttributes(_nodes, _values);
}
}
et2_vfsSize._attributes = {
"value": {
"type": "integer"
}
};
et2_register_widget(et2_vfsSize, ["vfs-size"]);
/**
* vfs-mode: textual representation of permissions + extra bits
*
* @augments et2_description
*/
export class et2_vfsMode extends et2_description {
/**
* Constructor
*
* @memberOf et2_vfsMode
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsMode._attributes, _child || {}));
this.span.addClass("et2_vfs");
}
/**
* Get text for file stuff
* Result will be like -rwxr--r--. First char is type, then read, write, execute (or other bits) for
* user, group, world
*
* @param {number} _value vfs mode
*/
text_mode(_value) {
let text = [];
if (typeof _value != "number") {
_value = parseInt(_value);
}
if (!_value)
return "----------";
// Figure out type
let type = 'u'; // unknown
for (let flag in et2_vfsMode.types) {
if ((_value & et2_vfsMode.types[flag]) == et2_vfsMode.types[flag]) {
type = flag;
break;
}
}
// World, group, user - build string backwards
for (let i = 0; i < 3; i++) {
for (let perm in et2_vfsMode.perms) {
if (_value & et2_vfsMode.perms[perm]) {
text.unshift(perm);
}
else {
text.unshift("-");
}
}
_value = _value >> 3;
}
// Sticky / UID / GID
for (let i = 0; i < et2_vfsMode.sticky.length; i++) {
if (et2_vfsMode.sticky[i].mask & _value) {
let current = text[et2_vfsMode.sticky[i].position];
text[et2_vfsMode.sticky[i].position] = et2_vfsMode.sticky[i]["char"];
if (current == 'x')
text[et2_vfsMode.sticky[i].position].toLowerCase();
}
}
return type + text.join('');
}
set_value(_value) {
if (_value.size) {
_value = _value.size;
}
let text = this.text_mode(_value);
jQuery(this.node).text(text);
}
setDetachedAttributes(_nodes, _values) {
if (typeof _values["value"] !== "undefined") {
this.node = _nodes[0];
this.set_value(_values["value"]);
delete _values["value"];
}
super.setDetachedAttributes(_nodes, _values);
}
}
// Masks for file types
et2_vfsMode.types = {
'l': 0xA000,
's': 0xC000,
'p': 0x1000,
'c': 0x2000,
'd': 0x4000,
'b': 0x6000,
'-': 0x8000 // Regular
};
// Sticky / UID / GID
et2_vfsMode.sticky = [
{ mask: 0x200, "char": "T", position: 9 },
{ mask: 0x400, "char": "S", position: 6 },
{ mask: 0x800, "char": "S", position: 3 } // SUID
];
et2_vfsMode.perms = {
'x': 0x1,
'w': 0x2,
'r': 0x4 // Read
};
et2_register_widget(et2_vfsMode, ["vfs-mode"]);
/**
* vfs-uid / vfs-gid: Displays the name for an ID.
* Same as read-only selectAccount, except if there's no user it shows "root"
*
* @augments et2_selectAccount_ro
*/
export class et2_vfsUid extends et2_selectAccount_ro {
/**
* @memberOf et2_vfsUid
* @param _node
* @param _value
*/
set_title(_node, _value) {
if (_value == "") {
arguments[1] = "root";
}
super.set_title(_node, _value);
}
}
et2_register_widget(et2_vfsUid, ["vfs-uid", "vfs-gid"]);
/* vfs-upload aka VFS file: displays either download and delete (x) links or a file upload
* + ID is either a vfs path or colon separated $app:$id:$relative_path, eg: infolog:123:special/offer
* + if empty($id) / new entry, file is created in a hidden temporary directory in users home directory
* and calling app is responsible to move content of that dir to entry directory, after entry is saved
* + option: required mimetype or regular expression for mimetype to match, eg. '/^text\//i' for all text files
* + if path ends in a slash, multiple files can be uploaded, their original filename is kept then
*
* @augments et2_file
*/
export class et2_vfsUpload extends et2_file {
/**
* Constructor
*
* @param _parent
* @param attrs
* @memberof et2_vfsUpload
*/
constructor(_parent, _attrs, _child) {
// Call the inherited constructor
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_vfsUpload._attributes, _child || {}));
this.list = null;
jQuery(this.node).addClass("et2_vfs");
if (!this.options.path) {
this.options.path = this.options.id;
}
// If the path is a directory, allow multiple uploads
if (this.options.path.substr(-1) == '/') {
this.set_multiple(true);
}
this.list = jQuery(document.createElement('table')).appendTo(this.node);
}
/**
* Get any specific async upload options
*/
getAsyncOptions(self) {
return jQuery.extend({}, super.getAsyncOptions(self), {
target: egw.ajaxUrl("EGroupware\\Api\\Etemplate\\Widget\\Vfs::ajax_upload")
});
}
/**
* If there is a file / files in the specified location, display them
* Value is the information for the file[s] in the specified location.
*
* @param {Object{}} _value
*/
set_value(_value) {
// Remove previous
while (this._children.length > 0) {
var node = this._children[this._children.length - 1];
this.removeChild(node);
node.destroy();
}
this.progress.empty();
this.list.empty();
// Set new
if (typeof _value == 'object' && _value && Object.keys(_value).length) {
for (let i in _value) {
this._addFile(_value[i]);
}
}
return true;
}
getDOMNode(sender) {
if (sender && sender !== this && sender._type.indexOf('vfs') >= 0) {
var value = sender.getValue && sender.getValue() || sender.options.value || {};
var row = jQuery("[data-path='" + (value.path.replace(/'/g, '"')) + "']", this.list);
if (sender._type === 'vfs-mime') {
return jQuery('.icon', row).get(0) || null;
}
else {
return jQuery('.title', row).get(0) || null;
}
}
else {
return super.getDOMNode(sender);
}
}
/**
* Add in the request id
*
* @param {type} form
*/
beforeSend(form) {
let extra = super.beforeSend(form);
extra["path"] = this.options.path;
return extra;
}
/**
* A file upload is finished, update the UI
*
* @param {object} file
* @param {string|object} response
*/
finishUpload(file, response) {
let result = super.finishUpload(file, response);
if (typeof response == 'string')
response = jQuery.parseJSON(response);
if (response.response[0] && typeof response.response[0].data.length == 'undefined') {
for (let key in response.response[0].data) {
let value = response.response[0].data[key];
if (value && value.path) {
this._addFile(value);
jQuery("[data-file='" + file.fileName.replace(/'/g, '"') + "']", this.progress).hide();
}
}
}
return result;
}
_addFile(file_data) {
if (jQuery("[data-path='" + file_data.path.replace(/'/g, '"') + "']").remove().length) {
for (var child_index = this._children.length - 1; child_index >= 0; child_index--) {
var child = this._children[child_index];
if (child.options.value.path === file_data.path) {
this.removeChild(child);
child.destroy();
}
}
}
// Set up for expose
if (file_data && typeof file_data.download_url === "undefined") {
file_data.download_url = "/webdav.php" + file_data.path;
}
let row = jQuery(document.createElement("tr"))
.attr("data-path", file_data.path.replace(/'/g, '"'))
.attr("draggable", "true")
.appendTo(this.list);
jQuery(document.createElement("td"))
.addClass('icon')
.appendTo(row);
jQuery(document.createElement("td"))
.addClass('title')
.appendTo(row);
let mime = et2_createWidget('vfs-mime', { value: file_data }, this);
// Trigger expose on click, if supported
let vfs_attrs = { value: file_data, onclick: undefined };
if (file_data && (typeof file_data.download_url != 'undefined')) {
var fe_mime = egw_get_file_editor_prefered_mimes(file_data.mime);
// Check if the link entry is mime with media type, in order to open it in expose view
if (typeof file_data.mime === 'string' &&
(file_data.mime.match(mime.mime_regexp, 'ig') || (fe_mime && fe_mime.mime[file_data.mime]))) {
vfs_attrs.onclick = function (ev) {
ev.stopPropagation();
// Pass it off to the associated vfsMime widget
jQuery('img', this.parentNode.parentNode).trigger("click");
return false;
};
}
}
let vfs = et2_createWidget('vfs', vfs_attrs, this);
// If already attached, need to do this explicitly
if (this.isAttached()) {
mime.set_value(file_data);
vfs.set_value(file_data);
mime.doLoadingFinished();
vfs.doLoadingFinished();
}
// Add in delete button
if (!this.options.readonly) {
let self = this;
let delete_button = jQuery(document.createElement("td"))
.appendTo(row);
jQuery("