2012-03-26 21:46:51 +02:00
/ * *
2013-04-13 21:00:13 +02:00
* EGroupware eTemplate2 - JS VFS widgets
2012-03-26 21:46:51 +02:00
*
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @ package etemplate
* @ subpackage api
2021-06-07 17:33:53 +02:00
* @ link https : //www.egroupware.org
2012-03-26 21:46:51 +02:00
* @ author Nathan Gray
* @ copyright Nathan Gray 2012
2019-03-21 12:36:07 +01:00
* /
2020-02-19 17:14:44 +01:00
var _a ;
2012-03-26 21:46:51 +02:00
/ * e g w : u s e s
2020-02-07 17:41:51 +01:00
/ v e n d o r / b o w e r - a s s e t / j q u e r y / d i s t / j q u e r y . j s ;
vfsSelectUI ;
et2 _core _inputWidget ;
et2 _core _valueWidget ;
et2 _widget _description ;
et2 _widget _file ;
expose ;
2012-03-26 21:46:51 +02:00
* /
2021-06-07 17:33:53 +02:00
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" ;
2021-06-08 14:11:59 +02:00
import { egw , egw _get _file _editor _prefered _mimes } from "../jsapi/egw_global" ;
2021-06-07 17:33:53 +02:00
import { expose } from "./expose" ;
2012-03-26 21:46:51 +02:00
/ * *
* Class which implements the "vfs" XET - Tag
2014-02-10 19:25:02 +01:00
*
2013-04-13 21:00:13 +02:00
* @ augments et2 _valueWidget
2012-03-26 21:46:51 +02:00
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfs extends et2 _valueWidget {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfs
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfs . _attributes , _child || { } ) ) ;
this . span = null ;
this . value = "" ;
this . span = jQuery ( document . createElement ( "ul" ) )
2020-02-07 17:41:51 +01:00
. addClass ( 'et2_vfs' ) ;
2021-06-07 17:33:53 +02:00
this . setDOMNode ( this . span [ 0 ] ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
getValue ( ) {
2020-02-07 17:41:51 +01:00
return this . value ;
2021-06-07 17:33:53 +02:00
}
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
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 ;
2021-06-07 17:33:53 +02:00
let path = _value . path ? _value . path : '/' ;
2020-02-07 17:41:51 +01:00
// 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
2021-06-07 17:33:53 +02:00
let sub _path = path . substring ( 0 , _value . path . length - _value . name . length - 1 ) ;
let path _offset , path _parts ;
2020-02-07 17:41:51 +01:00
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 ( '/' ) ;
}
2021-06-07 17:33:53 +02:00
let text ;
for ( let i = path _offset ; i < path _parts . length ; i ++ ) {
2020-02-07 17:41:51 +01:00
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 ) {
2021-06-07 17:33:53 +02:00
text = this . egw ( ) . lang ( 'applications' ) ;
2020-02-07 17:41:51 +01:00
}
break ;
case 3 :
if ( i == 2 ) {
2021-06-07 17:33:53 +02:00
text = this . egw ( ) . lang ( path _parts [ 2 ] ) ;
2020-02-07 17:41:51 +01:00
}
break ;
case 4 :
if ( ! isNaN ( text ) ) {
2021-06-07 17:33:53 +02:00
let link _title = this . egw ( ) . link _title ( path _parts [ 2 ] , path _parts [ 3 ] , function ( title ) {
2020-02-07 17:41:51 +01:00
if ( ! title || this . value . name == title )
return ;
jQuery ( 'li' , this . span ) . last ( ) . text ( title ) ;
2021-06-07 17:33:53 +02:00
} , this ) ;
2020-02-07 17:41:51 +01:00
if ( link _title && typeof link _title !== 'undefined' )
text = link _title ;
}
break ;
}
}
2021-06-07 17:33:53 +02:00
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" ) )
2020-02-07 17:41:51 +01:00
. addClass ( "vfsFilename" )
. text ( text + ( i < path _parts . length - 1 ? '/' : '' ) )
//.attr('title', egw.decodePath(path))
. addClass ( "et2_clickable et2_link" )
2021-06-07 17:33:53 +02:00
. click ( { data : data , egw : this . egw ( ) } , function ( e ) {
if ( ! self . onclick ) {
2020-02-07 17:41:51 +01:00
e . data . egw . open ( e . data . data , "file" ) ;
}
2021-06-07 17:33:53 +02:00
else if ( self . click ( e ) ) {
2020-02-07 17:41:51 +01:00
e . data . egw . open ( e . data . data , "file" ) ;
}
} )
2021-06-07 17:33:53 +02:00
. appendTo ( this . span ) ;
2020-02-07 17:41:51 +01:00
}
// Last part of path do default action
this . _bind _default _action ( node , data ) ;
2021-06-07 17:33:53 +02:00
}
_bind _default _action ( node , data ) {
let links = [ ] ;
let widget = this ;
let defaultAction = null ;
let object = null ;
let app = this . getInstanceManager ( ) . app ;
2020-02-07 17:41:51 +01:00
while ( links . length === 0 && widget . getParent ( ) ) {
2020-02-13 10:39:13 +01:00
object = egw _getAppObjectManager ( app ) . getObjectById ( widget . id ) ;
2020-02-07 17:41:51 +01:00
if ( object && object . manager && object . manager . children ) {
links = object . manager . children ;
}
widget = widget . getParent ( ) ;
}
2021-06-07 17:33:53 +02:00
for ( let k in links ) {
2020-02-07 17:41:51 +01:00
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
2020-03-05 14:53:50 +01:00
egw _keyHandler ( EGW _KEY _ENTER , false , false , false ) ;
2020-02-07 17:41:51 +01:00
} ) ;
// Select row
return true ;
} . bind ( { data : data , object : object } ) ) ;
}
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Code for implementing et2 _IDetachedDOM ( data grid )
*
* @ param { array } _attrs array of attribute - names to push further names onto
* /
2021-06-07 17:33:53 +02:00
getDetachedAttributes ( _attrs ) {
2020-02-07 17:41:51 +01:00
_attrs . push ( "value" ) ;
2021-06-07 17:33:53 +02:00
}
getDetachedNodes ( ) {
2020-02-07 17:41:51 +01:00
return [ this . span [ 0 ] ] ;
2021-06-07 17:33:53 +02:00
}
setDetachedAttributes ( _nodes , _values ) {
2020-02-07 17:41:51 +01:00
this . span = jQuery ( _nodes [ 0 ] ) ;
if ( typeof _values [ "value" ] != 'undefined' ) {
this . set _value ( _values [ "value" ] ) ;
}
2021-06-07 17:33:53 +02:00
}
}
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" ] ) ;
2012-03-27 01:30:27 +02:00
/ * *
2020-02-07 17:41:51 +01:00
* vfs - name
* filename automatically urlencoded on return ( urldecoded on display to user )
*
* @ augments et2 _textbox
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsName extends et2 _textbox {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfsName
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfsName . _attributes , _child || { } ) ) ;
this . input . addClass ( "et2_vfs" ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
if ( _value . path ) {
_value = _value . path ;
}
try {
_value = egw . decodePath ( _value ) ;
}
catch ( e ) {
_value = 'Error! ' + _value ;
}
2021-06-07 17:33:53 +02:00
super . set _value ( _value ) ;
}
getValue ( ) {
return egw . encodePath ( super . getValue ( ) || '' ) ;
}
}
et2 _register _widget ( et2 _vfsName , [ "vfs-name" ] ) ;
2019-01-07 23:04:50 +01:00
/ * *
2020-02-07 17:41:51 +01:00
* vfs - name
* filename automatically urlencoded on return ( urldecoded on display to user )
*
* @ augments et2 _textbox
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsPath extends et2 _vfsName {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfsName
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfsPath . _attributes , _child || { } ) ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
createInputWidget ( ) {
super . createInputWidget ( ) ;
2020-02-07 17:41:51 +01:00
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 ) ) ;
2021-06-07 17:33:53 +02:00
}
change ( _node ) {
2020-02-07 17:41:51 +01:00
if ( this . input . val ( ) ) {
this . set _value ( this . input . val ( ) ) ;
}
2021-06-07 17:33:53 +02:00
return super . change ( _node ) ;
}
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
if ( _value . path ) {
_value = _value . path ;
}
if ( _value === this . options . value && this . _oldValue !== et2 _no _init )
return ;
2021-06-07 17:33:53 +02:00
let path _parts = _value . split ( '/' ) ;
2020-02-07 17:41:51 +01:00
if ( _value === '/' )
path _parts = [ '' ] ;
2021-06-07 17:33:53 +02:00
let path = "/" ;
let text = '' ;
2020-02-07 17:41:51 +01:00
if ( this . span )
this . span . empty ( ) . css ( 'display' , 'flex' ) ;
this . input . val ( '' ) ;
2021-06-07 17:33:53 +02:00
for ( let i = 0 ; i < path _parts . length ; i ++ ) {
2020-02-07 17:41:51 +01:00
path += ( path == '/' ? '' : '/' ) + path _parts [ i ] ;
text = egw . decodePath ( path _parts [ i ] ) ;
2021-06-07 17:33:53 +02:00
let image = path == '/' ? this . egw ( ) . image ( 'navbar' , 'api' ) : this . egw ( ) . image ( text ) ;
2020-02-07 17:41:51 +01:00
// Nice human-readable stuff for apps
if ( path _parts [ 1 ] == 'apps' ) {
if ( i === 1 ) {
2021-06-07 17:33:53 +02:00
text = this . egw ( ) . lang ( 'applications' ) ;
2020-02-07 17:41:51 +01:00
}
else if ( i === 2 ) {
2021-06-07 17:33:53 +02:00
text = this . egw ( ) . lang ( path _parts [ 2 ] ) ;
image = this . egw ( ) . image ( 'navbar' , path _parts [ 2 ] . toLowerCase ( ) ) ;
2020-02-07 17:41:51 +01:00
}
else if ( ! isNaN ( text ) ) {
2021-06-07 17:33:53 +02:00
let link _title = this . egw ( ) . link _title ( path _parts [ 2 ] , path _parts [ 3 ] , function ( title ) {
2020-02-07 17:41:51 +01:00
if ( ! title )
return ;
jQuery ( 'li' , this . span ) . first ( ) . text ( title ) ;
2021-06-07 17:33:53 +02:00
} , this ) ;
2020-02-07 17:41:51 +01:00
if ( link _title && typeof link _title !== 'undefined' )
text = link _title ;
}
}
2021-06-07 17:33:53 +02:00
let self = this ;
let node = jQuery ( document . createElement ( "li" ) )
2020-02-07 17:41:51 +01:00
. addClass ( "vfsPath et2_clickable" )
. text ( text )
//.attr('title', egw.decodePath(path))
2021-06-07 17:33:53 +02:00
. click ( { data : path , egw : this . egw ( ) } , function ( e ) {
return self . set _value ( e . data . data ) ;
2020-02-07 17:41:51 +01:00
} )
2021-06-07 17:33:53 +02:00
. prependTo ( this . span ) ;
if ( image && ! this . options . noicon ) {
node . prepend ( this . egw ( ) . image _element ( image ) ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
jQuery ( this . getDOMNode ( ) ) . append ( this . span ) ;
2020-02-07 17:41:51 +01:00
}
if ( this . isAttached ( ) && this . options . value !== _value ) {
this . _oldValue = this . options . value ;
this . options . value = _value ;
this . change ( ) ;
}
2021-06-07 17:33:53 +02:00
}
getValue ( ) {
2020-02-07 17:41:51 +01:00
return this . options ? this . options . value : null ;
2021-06-07 17:33:53 +02:00
}
}
et2 _vfsPath . _attributes = {
noicon : {
type : "boolean" ,
description : "suppress folder icons" ,
default : true
}
} ;
et2 _register _widget ( et2 _vfsPath , [ "vfs-path" ] ) ;
2013-04-12 11:39:37 +02:00
/ * *
2020-02-07 17:41:51 +01:00
* vfs - name
* filename automatically urlencoded on return ( urldecoded on display to user )
*
* @ augments et2 _textbox _ro
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsName _ro extends et2 _textbox _ro {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfsName _ro
* /
/ * *
* Constructor
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfsName _ro . _attributes , _child || { } ) ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
if ( _value . path ) {
_value = _value . path ;
}
try {
_value = egw . decodePath ( _value ) ;
}
catch ( e ) {
_value = 'Error! ' + _value ;
}
2021-06-07 17:33:53 +02:00
super . set _value ( _value ) ;
}
getValue ( ) {
return egw . encodePath ( super . getValue ( ) || '' ) ;
}
}
et2 _register _widget ( et2 _vfsName _ro , [ "vfs-name_ro" ] ) ;
2012-03-28 01:32:32 +02:00
/ * *
2020-02-07 17:41:51 +01:00
* vfs - mime : icon for mimetype of file , or thumbnail
* incl . optional link overlay icon , if file is a symlink
*
* Creates following structure
* < span class = "iconOverlayContainer" >
* < img class = "et2_vfs vfsMimeIcon" src = "..." / >
* < span class = "overlayContainer" >
* < img class = "overlay" src = "etemplate/templates/default/images/link.png" / >
* < / s p a n >
* < / s p a n >
*
* span . overlayContainer is optional and only generated for symlinks
* @ augments et2 _valueWidget
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsMime extends expose ( ( _a = class et2 _vfsMime extends et2 _valueWidget {
2020-02-19 17:14:44 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfsMime
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-19 17:14:44 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
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 ] ) ;
2020-02-07 17:41:51 +01:00
}
2020-02-19 17:14:44 +01:00
/ * *
* 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
* /
2021-06-07 17:33:53 +02:00
expose _onslide ( gallery , index , slide ) {
2020-02-19 17:14:44 +01:00
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 ) ;
2020-02-07 17:41:51 +01:00
}
2020-02-19 17:14:44 +01:00
return content ;
2021-06-07 17:33:53 +02:00
}
2020-02-19 17:14:44 +01:00
/ * *
* Function to get media content to feed the expose
*
* @ param { type } _value
* @ returns { Array } return an array of object consists of media content
* /
2021-06-07 17:33:53 +02:00
getMedia ( _value ) {
let base _url = egw . webserverUrl . match ( /^\/ig/ ) ? egw ( window ) . window . location . origin + egw . webserverUrl : egw . webserverUrl ;
let mediaContent = [ {
2020-02-19 17:14:44 +01:00
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' ;
2020-02-07 17:41:51 +01:00
}
2020-02-19 17:14:44 +01:00
}
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 ;
2021-06-07 17:33:53 +02:00
}
set _value ( _value ) {
2020-02-19 17:14:44 +01:00
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'
}
2021-06-07 17:33:53 +02:00
let src = this . egw ( ) . mime _icon ( _value . mime , _value . path , undefined , _value . mtime ) ;
2020-02-19 17:14:44 +01:00
if ( src ) {
// Set size of thumbnail
if ( src . indexOf ( "thumbnail.php" ) > - 1 ) {
if ( this . options . size ) {
src += "&thsize=" + this . options . size ;
2020-02-07 17:41:51 +01:00
}
2020-02-19 17:14:44 +01:00
else if ( this . options . thumb _mime _size ) {
2021-06-07 17:33:53 +02:00
let mime _size = this . options . thumb _mime _size . split ( ',' ) ;
let mime _regex = RegExp ( _value . mime . split ( '/' ) [ 0 ] ) ;
2020-02-19 17:14:44 +01:00
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)/ ) ) {
2021-06-07 17:33:53 +02:00
let tooltip _target = this . image . parent ( ) . parent ( ) . parent ( ) . length > 0 ?
2020-02-19 17:14:44 +01:00
// 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 '<img src="' + this . src + '&thsize=512"/>' ;
}
} ) ;
2020-02-07 17:41:51 +01:00
}
}
2020-02-19 17:14:44 +01:00
// 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 ) ;
}
2020-02-07 17:41:51 +01:00
}
2020-02-19 17:14:44 +01:00
else if ( typeof this . overlayContainer != 'undefined' ) {
this . overlayContainer . remove ( ) ;
delete this . overlayContainer ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
}
2020-02-19 17:14:44 +01:00
/ * *
* 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
* /
2021-06-07 17:33:53 +02:00
getDetachedAttributes ( _attrs ) {
2020-02-19 17:14:44 +01:00
_attrs . push ( "value" , "class" ) ;
2021-06-07 17:33:53 +02:00
}
getDetachedNodes ( ) {
2020-02-19 17:14:44 +01:00
return [ this . node , this . iconOverlayContainer [ 0 ] , this . image [ 0 ] ] ;
2021-06-07 17:33:53 +02:00
}
setDetachedAttributes ( _nodes , _values ) {
2020-02-19 17:14:44 +01:00
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' ] ) ;
}
2021-06-07 17:33:53 +02:00
}
} ,
2020-02-19 17:14:44 +01:00
_a . _attributes = {
2020-02-07 17:41:51 +01:00
"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)"
}
2020-02-19 17:14:44 +01:00
} ,
2020-03-30 18:28:48 +02:00
_a . legacyOptions = [ "size" ] ,
2021-06-07 17:33:53 +02:00
_a ) ) {
}
2020-02-20 17:46:53 +01:00
;
2021-06-07 17:33:53 +02:00
et2 _register _widget ( et2 _vfsMime , [ "vfs-mime" ] ) ;
2012-03-27 01:30:27 +02:00
/ * *
2020-02-07 17:41:51 +01:00
* vfs - size
* Human readable file sizes
*
* @ augments et2 _description
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsSize extends et2 _description {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfsSize
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfsSize . _attributes , _child || { } ) ) ;
this . span . addClass ( "et2_vfs" ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
human _size ( size ) {
2020-02-07 17:41:51 +01:00
if ( typeof size !== "number" ) {
size = parseInt ( size ) ;
}
if ( ! size ) {
size = 0 ;
}
2021-06-07 17:33:53 +02:00
const units = [ 'B' , 'KB' , 'MB' , 'GB' , 'TB' , 'PB' , 'EB' , 'ZB' , 'YB' ] ;
let i = 0 ;
2020-02-07 17:41:51 +01:00
while ( size >= 1024 ) {
size /= 1024 ;
++ i ;
}
return size . toFixed ( i == 0 ? 0 : 1 ) + ' ' + units [ i ] ;
2021-06-07 17:33:53 +02:00
}
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
if ( _value . size ) {
_value = _value . size ;
}
jQuery ( this . node ) . text ( this . human _size ( _value ) ) ;
2021-06-07 17:33:53 +02:00
}
setDetachedAttributes ( _nodes , _values ) {
2020-02-07 17:41:51 +01:00
if ( typeof _values [ "value" ] !== "undefined" ) {
this . node = _nodes [ 0 ] ;
this . set _value ( _values [ "value" ] ) ;
delete _values [ "value" ] ;
}
2021-06-07 17:33:53 +02:00
super . setDetachedAttributes ( _nodes , _values ) ;
}
}
et2 _vfsSize . _attributes = {
"value" : {
"type" : "integer"
}
} ;
et2 _register _widget ( et2 _vfsSize , [ "vfs-size" ] ) ;
2012-03-27 01:30:27 +02:00
/ * *
2020-02-07 17:41:51 +01:00
* vfs - mode : textual representation of permissions + extra bits
*
* @ augments et2 _description
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsMode extends et2 _description {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ memberOf et2 _vfsMode
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfsMode . _attributes , _child || { } ) ) ;
this . span . addClass ( "et2_vfs" ) ;
2020-02-07 17:41:51 +01:00
}
/ * *
* 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
* /
2021-06-07 17:33:53 +02:00
text _mode ( _value ) {
let text = [ ] ;
2020-02-07 17:41:51 +01:00
if ( typeof _value != "number" ) {
_value = parseInt ( _value ) ;
}
if ( ! _value )
return "----------" ;
// Figure out type
2021-06-07 17:33:53 +02:00
let type = 'u' ; // unknown
for ( let flag in et2 _vfsMode . types ) {
2020-02-07 17:41:51 +01:00
if ( ( _value & et2 _vfsMode . types [ flag ] ) == et2 _vfsMode . types [ flag ] ) {
type = flag ;
break ;
}
}
// World, group, user - build string backwards
2021-06-07 17:33:53 +02:00
for ( let i = 0 ; i < 3 ; i ++ ) {
for ( let perm in et2 _vfsMode . perms ) {
2020-02-07 17:41:51 +01:00
if ( _value & et2 _vfsMode . perms [ perm ] ) {
text . unshift ( perm ) ;
}
else {
text . unshift ( "-" ) ;
}
}
_value = _value >> 3 ;
}
// Sticky / UID / GID
2021-06-07 17:33:53 +02:00
for ( let i = 0 ; i < et2 _vfsMode . sticky . length ; i ++ ) {
2020-02-07 17:41:51 +01:00
if ( et2 _vfsMode . sticky [ i ] . mask & _value ) {
2021-06-07 17:33:53 +02:00
let current = text [ et2 _vfsMode . sticky [ i ] . position ] ;
2020-02-07 17:41:51 +01:00
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 ( '' ) ;
2021-06-07 17:33:53 +02:00
}
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
if ( _value . size ) {
_value = _value . size ;
}
2021-06-07 17:33:53 +02:00
let text = this . text _mode ( _value ) ;
2020-02-07 17:41:51 +01:00
jQuery ( this . node ) . text ( text ) ;
2021-06-07 17:33:53 +02:00
}
setDetachedAttributes ( _nodes , _values ) {
2020-02-07 17:41:51 +01:00
if ( typeof _values [ "value" ] !== "undefined" ) {
this . node = _nodes [ 0 ] ;
this . set _value ( _values [ "value" ] ) ;
delete _values [ "value" ] ;
}
2021-06-07 17:33:53 +02:00
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" ] ) ;
2012-03-27 01:30:27 +02:00
/ * *
2020-02-07 17:41:51 +01:00
* 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
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsUid extends et2 _selectAccount _ro {
2020-02-07 17:41:51 +01:00
/ * *
* @ memberOf et2 _vfsUid
* @ param _node
* @ param _value
* /
2021-06-07 17:33:53 +02:00
set _title ( _node , _value ) {
2020-02-07 17:41:51 +01:00
if ( _value == "" ) {
arguments [ 1 ] = "root" ;
}
2021-06-07 17:33:53 +02:00
super . set _title ( _node , _value ) ;
}
}
et2 _register _widget ( et2 _vfsUid , [ "vfs-uid" , "vfs-gid" ] ) ;
2012-03-29 01:27:18 +02:00
/ * v f s - u p l o a d a k a V F S f i l e : d i s p l a y s e i t h e r d o w n l o a d a n d d e l e t e ( x ) l i n k s o r a f i l e u p l o a d
2020-02-07 17:41:51 +01:00
* + 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
* /
2021-06-07 17:33:53 +02:00
export class et2 _vfsUpload extends et2 _file {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ param _parent
* @ param attrs
* @ memberof et2 _vfsUpload
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
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 ;
2020-02-07 17:41:51 +01:00
}
// If the path is a directory, allow multiple uploads
2021-06-07 17:33:53 +02:00
if ( this . options . path . substr ( - 1 ) == '/' ) {
this . set _multiple ( true ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
this . list = jQuery ( document . createElement ( 'table' ) ) . appendTo ( this . node ) ;
2020-02-07 17:41:51 +01:00
}
2020-06-10 18:20:16 +02:00
/ * *
* Get any specific async upload options
* /
2021-06-07 17:33:53 +02:00
getAsyncOptions ( self ) {
return jQuery . extend ( { } , super . getAsyncOptions ( self ) , {
2020-06-10 18:20:16 +02:00
target : egw . ajaxUrl ( "EGroupware\\Api\\Etemplate\\Widget\\Vfs::ajax_upload" )
} ) ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* If there is a file / files in the specified location , display them
* Value is the information for the file [ s ] in the specified location .
*
2020-06-10 18:20:16 +02:00
* @ param { Object { } } _value
2020-02-07 17:41:51 +01:00
* /
2021-06-07 17:33:53 +02:00
set _value ( _value ) {
2020-02-07 17:41:51 +01:00
// Remove previous
while ( this . _children . length > 0 ) {
var node = this . _children [ this . _children . length - 1 ] ;
this . removeChild ( node ) ;
2020-03-25 20:48:04 +01:00
node . destroy ( ) ;
2020-02-07 17:41:51 +01:00
}
this . progress . empty ( ) ;
this . list . empty ( ) ;
// Set new
2020-06-10 18:20:16 +02:00
if ( typeof _value == 'object' && _value && Object . keys ( _value ) . length ) {
2021-06-07 17:33:53 +02:00
for ( let i in _value ) {
2020-02-07 17:41:51 +01:00
this . _addFile ( _value [ i ] ) ;
}
}
return true ;
2021-06-07 17:33:53 +02:00
}
getDOMNode ( sender ) {
2020-10-19 16:06:22 +02:00
if ( sender && sender !== this && sender . _type . indexOf ( 'vfs' ) >= 0 ) {
2020-02-07 17:41:51 +01:00
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 {
2021-06-07 17:33:53 +02:00
return super . getDOMNode ( sender ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Add in the request id
*
* @ param { type } form
* /
2021-06-07 17:33:53 +02:00
beforeSend ( form ) {
let extra = super . beforeSend ( form ) ;
2020-02-07 17:41:51 +01:00
extra [ "path" ] = this . options . path ;
return extra ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* A file upload is finished , update the UI
*
* @ param { object } file
* @ param { string | object } response
* /
2021-06-07 17:33:53 +02:00
finishUpload ( file , response ) {
let result = super . finishUpload ( file , response ) ;
2020-02-07 17:41:51 +01:00
if ( typeof response == 'string' )
response = jQuery . parseJSON ( response ) ;
if ( response . response [ 0 ] && typeof response . response [ 0 ] . data . length == 'undefined' ) {
2021-06-07 17:33:53 +02:00
for ( let key in response . response [ 0 ] . data ) {
let value = response . response [ 0 ] . data [ key ] ;
2020-02-07 17:41:51 +01:00
if ( value && value . path ) {
this . _addFile ( value ) ;
jQuery ( "[data-file='" + file . fileName . replace ( /'/g , '"' ) + "']" , this . progress ) . hide ( ) ;
}
}
}
return result ;
2021-06-07 17:33:53 +02:00
}
_addFile ( file _data ) {
2020-02-07 17:41:51 +01:00
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 ) {
2020-03-25 20:48:04 +01:00
this . removeChild ( child ) ;
child . destroy ( ) ;
2020-02-07 17:41:51 +01:00
}
}
}
2020-07-10 13:16:31 +02:00
// Set up for expose
if ( file _data && typeof file _data . download _url === "undefined" ) {
file _data . download _url = "/webdav.php" + file _data . path ;
}
2021-06-07 17:33:53 +02:00
let row = jQuery ( document . createElement ( "tr" ) )
2020-02-07 17:41:51 +01:00
. 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 ) ;
2021-06-07 17:33:53 +02:00
let mime = et2 _createWidget ( 'vfs-mime' , { value : file _data } , this ) ;
2020-07-03 22:23:41 +02:00
// Trigger expose on click, if supported
2021-06-07 17:33:53 +02:00
let vfs _attrs = { value : file _data , onclick : undefined } ;
2020-07-03 22:23:41 +02:00
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
2020-07-10 19:11:05 +02:00
if ( typeof file _data . mime === 'string' &&
2020-07-03 22:23:41 +02:00
( 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 ;
} ;
}
}
2021-06-07 17:33:53 +02:00
let vfs = et2 _createWidget ( 'vfs' , vfs _attrs , this ) ;
2020-02-07 17:41:51 +01:00
// 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 ) {
2021-06-07 17:33:53 +02:00
let self = this ;
let delete _button = jQuery ( document . createElement ( "td" ) )
2020-02-07 17:41:51 +01:00
. appendTo ( row ) ;
jQuery ( "<div />" )
. appendTo ( delete _button )
// We don't use ui-icon because it assigns a bg image
. addClass ( "delete icon" )
. bind ( 'click' , function ( ) {
2021-06-07 17:33:53 +02:00
et2 _createWidget ( "dialog" , {
2020-02-07 17:41:51 +01:00
callback : function ( button ) {
2021-06-07 17:33:53 +02:00
if ( button == et2 _dialog . YES _BUTTON ) {
2020-02-07 17:41:51 +01:00
egw . json ( "filemanager_ui::ajax_action" , [
'delete' ,
[ row . attr ( 'data-path' ) . replace ( /"/g , "'" ) ] ,
''
] , function ( data ) {
if ( data && data . errs == 0 ) {
row . slideUp ( null , row . remove ) ;
}
if ( data && data . msg ) {
2021-06-07 17:33:53 +02:00
self . egw ( ) . message ( data . msg , data . errs == 0 ? 'success' : 'error' ) ;
2020-02-07 17:41:51 +01:00
}
} ) . sendRequest ( ) ;
}
} ,
2021-06-07 17:33:53 +02:00
message : self . egw ( ) . lang ( 'Delete file' ) + '?' ,
title : self . egw ( ) . lang ( 'Confirmation required' ) ,
buttons : et2 _dialog . BUTTONS _YES _NO ,
dialog _type : et2 _dialog . QUESTION _MESSAGE ,
2020-02-07 17:41:51 +01:00
width : 250
2021-06-07 17:33:53 +02:00
} , self ) ;
2020-02-07 17:41:51 +01:00
} ) ;
}
2021-06-07 17:33:53 +02:00
}
}
et2 _vfsUpload . _attributes = {
"value" : {
"type" : "any" // Either nothing, or an object with file info
} ,
"path" : {
"name" : "Path" ,
"description" : "Upload files to the specified VFS path" ,
"type" : "string" ,
"default" : ''
}
} ;
et2 _vfsUpload . legacyOptions = [ "mime" ] ;
et2 _register _widget ( et2 _vfsUpload , [ "vfs-upload" ] ) ;
export class et2 _vfsSelect extends et2 _inputWidget {
2020-02-07 17:41:51 +01:00
/ * *
* Constructor
*
* @ param _parent
* @ param _attrs
* @ memberOf et2 _vfsSelect
* /
2021-06-07 17:33:53 +02:00
constructor ( _parent , _attrs , _child ) {
2020-02-07 17:41:51 +01:00
// Call the inherited constructor
2021-06-07 17:33:53 +02:00
super ( _parent , _attrs , ClassWithAttributes . extendAttributes ( et2 _vfsSelect . _attributes , _child || { } ) ) ;
2020-02-07 17:41:51 +01:00
// Allowed mode options
2021-06-07 17:33:53 +02:00
this . modes = [ 'open' , 'open-multiple' , 'saveas' , 'select-dir' ] ;
2020-02-07 17:41:51 +01:00
// Allow no child widgets
2021-06-07 17:33:53 +02:00
this . supportedWidgetClasses = [ ] ;
this . button = jQuery ( document . createElement ( "button" ) )
. attr ( "title" , this . egw ( ) . lang ( "Select file(s) from VFS" ) )
2020-02-07 17:41:51 +01:00
. addClass ( "et2_button et2_vfs_btn" )
2021-06-07 17:33:53 +02:00
. css ( "background-image" , "url(" + this . egw ( ) . image ( "filemanager/navbar" ) + ")" ) ;
if ( this . options . readonly ) {
this . button . hide ( ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
if ( this . options . button _caption != "" ) {
this . button . text ( this . options . button _caption ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
this . setDOMNode ( this . button [ 0 ] ) ;
2020-02-07 17:41:51 +01:00
}
2021-06-07 17:33:53 +02:00
_content ( _content , _callback ) {
2020-02-07 17:41:51 +01:00
egw ( window ) . loading _prompt ( 'vfs-select' , true , '' , 'body' ) ;
2021-06-07 17:33:53 +02:00
let self = this ;
2020-02-07 17:41:51 +01:00
if ( typeof app . vfsSelectUI != "undefined" ) {
if ( this . dialog && this . dialog . div )
this . dialog . div . dialog ( 'close' ) ;
delete app . vfsSelectUI ;
}
2021-06-07 17:33:53 +02:00
let attrs = {
2020-02-07 17:41:51 +01:00
mode : this . options . mode ,
label : this . options . button _label ,
path : this . options . path || null ,
mime : this . options . mime || null ,
name : this . options . name ,
method : this . options . method ,
recentPaths : et2 _vfsSelect . _getRecentPaths ( )
} ;
var callback = _callback || this . _buildDialog ;
egw ( window ) . json ( 'EGroupware\\Api\\Etemplate\\Widget\\Vfs::ajax_vfsSelect_content' , [ _content , attrs ] , function ( _content ) {
egw ( window ) . loading _prompt ( 'vfs-select' , false ) ;
callback . apply ( self , arguments ) ;
} ) . sendRequest ( true ) ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Builds file navigator dialog
*
* @ param { object } _data content
* /
2021-06-07 17:33:53 +02:00
_buildDialog ( _data ) {
2020-02-07 17:41:51 +01:00
if ( ! _data . content . mode . match ( /open|open-multiple|saveas|select-dir/ ) ) {
egw . debug ( 'warn' , 'Mode is not matched!' ) ;
return ;
}
2021-06-07 17:33:53 +02:00
let self = this ;
let buttons = [
2020-02-07 17:41:51 +01:00
{
text : egw . lang ( _data . content . label ) ,
id : "submit" ,
image : _data . content . mode . match ( /saveas|select-dir/ ) ? "save" : this . options . button _icon
}
] ;
2021-06-07 17:33:53 +02:00
let extra _buttons _action = { } ;
2020-02-07 17:41:51 +01:00
if ( this . options . extra _buttons && this . options . method ) {
2021-06-07 17:33:53 +02:00
for ( let i = 0 ; i < this . options . extra _buttons . length ; i ++ ) {
2020-02-07 17:41:51 +01:00
delete ( this . options . extra _buttons [ i ] [ 'click' ] ) ;
buttons . push ( this . options . extra _buttons [ i ] ) ;
extra _buttons _action [ this . options . extra _buttons [ i ] [ 'id' ] ] = this . options . extra _buttons [ i ] [ 'id' ] ;
}
}
buttons . push ( { text : egw . lang ( "Close" ) , id : "close" , image : "cancel" } ) ;
2020-04-09 22:26:57 +02:00
// Don't rely only on app_name to fetch et2 object as app_name may not
// always represent current app of the window, e.g.: mail admin account.
// Try to fetch et2 from its template name.
2021-06-07 17:33:53 +02:00
let etemplate = jQuery ( 'form' ) . data ( 'etemplate' ) ;
let et2 ;
let currentApp = egw ( window ) . app _name ( ) ;
2021-05-05 16:51:09 +02:00
if ( etemplate && etemplate . name && ! app [ currentApp ] ) {
2020-04-09 22:26:57 +02:00
et2 = etemplate2 . getByTemplate ( etemplate . name ) [ 0 ] ;
2021-05-05 16:51:09 +02:00
currentApp = et2 . name . split ( '.' ) [ 0 ] ;
2020-04-09 22:26:57 +02:00
}
else {
2021-05-05 16:51:09 +02:00
et2 = etemplate2 . getByApplication ( currentApp ) [ 0 ] ;
2020-04-09 22:26:57 +02:00
}
2021-06-07 17:33:53 +02:00
let data = jQuery . extend ( _data , { 'currentapp' : currentApp , etemplate _exec _id : et2 . etemplate _exec _id } ) ;
2020-02-07 17:41:51 +01:00
// define a mini app object for vfs select UI
app . vfsSelectUI = new app . classes . vfsSelectUI ;
// callback for dialog
this . submit _callback = function ( submit _button _id , submit _value , savemode ) {
if ( ( submit _button _id == 'submit' || ( extra _buttons _action && extra _buttons _action [ submit _button _id ] ) ) && submit _value ) {
2021-06-07 17:33:53 +02:00
let files = [ ] ;
2020-02-07 17:41:51 +01:00
switch ( _data . content . mode ) {
case 'open-multiple' :
if ( submit _value . dir && submit _value . dir . selected ) {
for ( var key in Object . keys ( submit _value . dir . selected ) ) {
if ( submit _value . dir . selected [ key ] != "" ) {
files . push ( submit _value . path + '/' + submit _value . dir . selected [ key ] ) ;
}
}
}
break ;
case 'select-dir' :
files = submit _value . path ;
break ;
default :
if ( self . options . method === 'download' )
submit _value . path = _data . content . download _baseUrl ;
files = submit _value . path + '/' + submit _value . name ;
if ( self . options . mode === 'saveas' && ! savemode ) {
for ( var p in _data . content . dir ) {
if ( _data . content . dir [ p ] [ 'name' ] == submit _value . name ) {
var saveModeDialogButtons = [
{ text : self . egw ( ) . lang ( "Yes" ) , id : "overwrite" , class : "ui-priority-primary" , "default" : true , image : 'check' } ,
{ text : self . egw ( ) . lang ( "Rename" ) , id : "rename" , image : 'edit' } ,
{ text : self . egw ( ) . lang ( "Cancel" ) , id : "cancel" }
] ;
2021-06-07 17:33:53 +02:00
return et2 _dialog . show _prompt ( function ( _button _id , _value ) {
2020-02-07 17:41:51 +01:00
switch ( _button _id ) {
case "overwrite" :
return self . submit _callback ( submit _button _id , submit _value , 'overwrite' ) ;
case "rename" :
submit _value . name = _value ;
return self . submit _callback ( submit _button _id , submit _value , 'rename' ) ;
}
} , self . egw ( ) . lang ( 'Do you want to overwrite existing file %1 in directory %2?' , submit _value . name , submit _value . path ) , self . egw ( ) . lang ( 'File %1 already exists' , submit _value . name ) , submit _value . name , saveModeDialogButtons , null ) ;
}
}
}
break ;
}
et2 _vfsSelect . _setRecentPaths ( submit _value . path ) ;
self . value = files ;
if ( self . options . method && self . options . method !== 'download' ) {
2020-12-21 21:53:24 +01:00
egw ( window ) . request ( self . options . method , [ self . options . method _id , files , submit _button _id , savemode ] ) . then ( function ( data ) {
2020-02-07 17:41:51 +01:00
jQuery ( self . node ) . change ( ) ;
2020-12-21 21:53:24 +01:00
} ) ;
2020-02-07 17:41:51 +01:00
}
else {
jQuery ( self . node ) . change ( ) ;
}
delete app . vfsSelectUI ;
return true ;
}
} ;
2021-06-07 17:33:53 +02:00
this . dialog = et2 _createWidget ( "dialog" , {
2020-02-07 17:41:51 +01:00
callback : this . submit _callback ,
title : this . options . dialog _title ,
buttons : buttons ,
minWidth : 500 ,
minHeight : 400 ,
width : 400 ,
value : data ,
template : egw . webserverUrl + '/api/templates/default/vfsSelectUI.xet?1' ,
resizable : false
2021-06-07 17:33:53 +02:00
} , et2 _dialog . _create _parent ( 'api' ) ) ;
2020-02-07 17:41:51 +01:00
this . dialog . template . uniqueId = 'api.vfsSelectUI' ;
2020-03-25 20:48:04 +01:00
app . vfsSelectUI . et2 = this . dialog . template . widgetContainer ;
app . vfsSelectUI . vfsSelectWidget = this ;
2020-02-07 17:41:51 +01:00
// Keep the dialog always at the top
this . dialog . div . parent ( ) . css ( { "z-index" : 100000 } ) ;
this . dialog . div . on ( 'load' , function ( e ) {
app . vfsSelectUI . et2 _ready ( app . vfsSelectUI . et2 , 'api.vfsSelectUI' ) ;
} ) ;
2020-04-09 22:26:57 +02:00
// we need an etemplate_exec_id for better handling serverside parts of
// widgets and since we can not have a etemplate_exec_id specifically
// for dialog template our best shot is to inherit its parent etemplate_exec_id.
this . dialog . template . etemplate _exec _id = et2 . etemplate _exec _id ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Set recent path into sessionStorage
* @ param { string } _path
* /
2021-06-07 17:33:53 +02:00
static _setRecentPaths ( _path ) {
let recentPaths = egw . getSessionItem ( 'api' , 'vfsRecentPaths' ) ?
2020-02-07 17:41:51 +01:00
egw . getSessionItem ( 'api' , 'vfsRecentPaths' ) . split ( ',' ) : [ ] ;
if ( recentPaths . indexOf ( _path ) == - 1 )
recentPaths . push ( _path ) ;
egw . setSessionItem ( 'api' , 'vfsRecentPaths' , recentPaths ) ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Get recent paths from sessionStorage
* @ returns { Array } returns an array of recent paths
* /
2021-06-07 17:33:53 +02:00
static _getRecentPaths ( ) {
2020-02-07 17:41:51 +01:00
return egw . getSessionItem ( 'api' , 'vfsRecentPaths' ) ?
egw . getSessionItem ( 'api' , 'vfsRecentPaths' ) . split ( ',' ) : [ ] ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* click handler
* @ param { event object } e
* /
2021-06-07 17:33:53 +02:00
click ( e ) {
2020-02-07 17:41:51 +01:00
this . _content . call ( this , null ) ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Set the dialog ' s mode .
* Valid options are in et2 _vfsSelect . modes
*
* @ param { string } mode 'open' , 'open-multiple' , 'saveas' or 'select-dir'
* /
2021-06-07 17:33:53 +02:00
set _mode ( mode ) {
2020-02-07 17:41:51 +01:00
// Check mode
if ( jQuery . inArray ( mode , this . modes ) < 0 ) {
this . egw ( ) . debug ( "warn" , "Invalid mode for '%s': %s Valid options:" , this . id , mode , this . modes ) ;
return ;
}
this . options . mode = mode ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Set the label on the dialog ' s OK button .
*
* @ param { string } label
* /
2021-06-07 17:33:53 +02:00
set _button _label ( label ) {
2020-02-07 17:41:51 +01:00
this . options . button _label = label ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Set the caption for vfs - select button
*
* @ param { string } caption string value as a caption
* /
2021-06-07 17:33:53 +02:00
set _button _caption ( caption ) {
2020-02-07 17:41:51 +01:00
this . options . button _caption = caption ;
2021-06-07 17:33:53 +02:00
}
2020-02-07 17:41:51 +01:00
/ * *
* Set the ID passed to the server side callback
*
* @ param { string } id
* /
2021-06-07 17:33:53 +02:00
set _method _id ( id ) {
2020-02-07 17:41:51 +01:00
this . options . method _id = id ;
2021-06-07 17:33:53 +02:00
}
set _readonly ( readonly ) {
2020-02-07 17:41:51 +01:00
this . options . readonly = Boolean ( readonly ) ;
if ( this . options . readonly ) {
this . button . hide ( ) ;
}
else {
this . button . show ( ) ;
}
2021-06-07 17:33:53 +02:00
}
set _value ( value ) {
2020-02-07 17:41:51 +01:00
this . value = value ;
2021-06-07 17:33:53 +02:00
}
getValue ( ) {
2020-02-07 17:41:51 +01:00
return this . value ;
2021-06-07 17:33:53 +02:00
}
}
et2 _vfsSelect . _attributes = {
"mode" : {
name : "Dialog mode" ,
type : "string" ,
description : "One of {open|open-multiple|saveas|select-dir}" ,
default : "open-multiple"
} ,
"method" : {
name : "Server side callback" ,
type : "string" ,
description : " Server side callback to process selected value ( s ) in \ n \
2020-02-07 17:41:51 +01:00
app . class . method or class : : method format . The first parameter will \ n \
be Method ID , the second the file list . 'download' is reserved and it \ n \
means it should use download _baseUrl instead of path in value ( no method \ n \
will be actually executed ) . "
2021-06-07 17:33:53 +02:00
} ,
"method_id" : {
name : "Method ID" ,
type : "any" ,
description : " optional parameter passed to server side callback . \ n \
2020-02-07 17:41:51 +01:00
Can be a string or a function . " ,
2021-06-07 17:33:53 +02:00
default : ""
} ,
"path" : {
name : "Path" ,
type : "string" ,
description : "Start path in VFS. Leave unset to use the last used path."
} ,
"mime" : {
name : "Mime type" ,
type : "any" ,
description : "Limit display to the given mime-type"
} ,
"button_label" : {
name : "Button label" ,
description : "Set the label on the dialog's OK button." ,
default : "open"
} ,
"value" : {
type : "any" ,
description : "Array of paths (strings)"
} ,
"button_caption" : {
name : "button caption" ,
type : "string" ,
default : "Select files from Filemanager ..." ,
description : "Caption for vfs-select button." ,
translate : true
} ,
"button_icon" : {
name : "button icon" ,
type : "string" ,
default : "check" ,
description : "Custom icon to show on submit button."
} ,
"name" : {
name : "File name" ,
type : "any" ,
description : "file name" ,
default : ""
} ,
"dialog_title" : {
name : "dialog title" ,
type : "string" ,
default : "Save as" ,
description : "Title of dialog" ,
translate : true
} ,
"extra_buttons" : {
name : "extra action buttons" ,
type : "any" ,
description : "Extra buttons passed to dialog. It's co-related to method."
}
} ;
2020-02-20 17:46:53 +01:00
;
2021-06-07 17:33:53 +02:00
et2 _register _widget ( et2 _vfsSelect , [ "vfs-select" ] ) ;
2020-02-07 17:41:51 +01:00
//# sourceMappingURL=et2_widget_vfs.js.map