mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-22 16:03:47 +01:00
Thumbnails (and handling) of uploaded files on new entries that have not yet been saved
This commit is contained in:
parent
ee62801ace
commit
d5c24a2c8e
@ -2339,6 +2339,10 @@ window.egw_LAB.wait(function() {
|
|||||||
list(,$dates) = each($this->read_calendar(array($content['account_id'] ? $content['account_id'] : 'c'.$content['id']),false));
|
list(,$dates) = each($this->read_calendar(array($content['account_id'] ? $content['account_id'] : 'c'.$content['id']),false));
|
||||||
if(is_array($dates)) $content += $dates;
|
if(is_array($dates)) $content += $dates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Registry has view_id as contact_id, so set it (custom fields uses it)
|
||||||
|
$content['contact_id'] = $content['id'];
|
||||||
|
|
||||||
// Avoid ID conflict with tree & selectboxes
|
// Avoid ID conflict with tree & selectboxes
|
||||||
$content['cat_id_tree'] = $content['cat_id'];
|
$content['cat_id_tree'] = $content['cat_id'];
|
||||||
|
|
||||||
|
@ -627,6 +627,7 @@ var et2_customfields_list = (function(){ "use strict"; return et2_valueWidget.ex
|
|||||||
// Filemanager select
|
// Filemanager select
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
|
mode: widget.options.multiple ? 'open-multiple' : 'open',
|
||||||
method: 'EGroupware\\Api\\Etemplate\\Widget\\Link::link_existing',
|
method: 'EGroupware\\Api\\Etemplate\\Widget\\Link::link_existing',
|
||||||
method_id: attrs.path,
|
method_id: attrs.path,
|
||||||
button_label: egw.lang('Link')
|
button_label: egw.lang('Link')
|
||||||
|
@ -104,13 +104,14 @@ var et2_file = (function(){ "use strict"; return et2_inputWidget.extend(
|
|||||||
*
|
*
|
||||||
* @memberOf et2_file
|
* @memberOf et2_file
|
||||||
*/
|
*/
|
||||||
init: function() {
|
init: function(_parent, attrs) {
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
this.node = null;
|
this.node = null;
|
||||||
this.input = null;
|
this.input = null;
|
||||||
this.progress = null;
|
this.progress = null;
|
||||||
this.span = null;
|
this.span = null;
|
||||||
|
if(!this.options.value) this.options.value = {};
|
||||||
|
|
||||||
if(!this.options.id) {
|
if(!this.options.id) {
|
||||||
console.warn("File widget needs an ID. Used 'file_widget'.");
|
console.warn("File widget needs an ID. Used 'file_widget'.");
|
||||||
@ -122,6 +123,12 @@ var et2_file = (function(){ "use strict"; return et2_inputWidget.extend(
|
|||||||
{
|
{
|
||||||
this.options.multiple = true;
|
this.options.multiple = true;
|
||||||
}
|
}
|
||||||
|
// If ID ends in /, it's a directory - allow multiple
|
||||||
|
else if (this.options.id.substr(-1) === "/")
|
||||||
|
{
|
||||||
|
this.options.multiple = true;
|
||||||
|
attrs.multiple = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the URL to have the request ID & the widget ID
|
// Set up the URL to have the request ID & the widget ID
|
||||||
var instance = this.getInstanceManager();
|
var instance = this.getInstanceManager();
|
||||||
@ -579,7 +586,10 @@ var et2_file = (function(){ "use strict"; return et2_inputWidget.extend(
|
|||||||
|
|
||||||
if(typeof response == 'string') response = jQuery.parseJSON(response);
|
if(typeof response == 'string') response = jQuery.parseJSON(response);
|
||||||
if(response.response[0] && typeof response.response[0].data.length == 'undefined') {
|
if(response.response[0] && typeof response.response[0].data.length == 'undefined') {
|
||||||
if(typeof this.options.value != 'object') this.options.value = {};
|
if(typeof this.options.value !== 'object' || !this.options.multiple)
|
||||||
|
{
|
||||||
|
this.set_value({});
|
||||||
|
}
|
||||||
for(var key in response.response[0].data) {
|
for(var key in response.response[0].data) {
|
||||||
if(typeof response.response[0].data[key] == "string")
|
if(typeof response.response[0].data[key] == "string")
|
||||||
{
|
{
|
||||||
|
@ -718,15 +718,6 @@ var et2_vfsUpload = (function(){ "use strict"; return et2_file.extend(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Value is determined by what's at the location specified by path
|
|
||||||
*
|
|
||||||
* @returns {null}
|
|
||||||
*/
|
|
||||||
getValue: function() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
getDOMNode: function(sender) {
|
getDOMNode: function(sender) {
|
||||||
if(sender !== this && sender._type.indexOf('vfs') >= 0 )
|
if(sender !== this && sender._type.indexOf('vfs') >= 0 )
|
||||||
{
|
{
|
||||||
@ -761,6 +752,26 @@ var et2_vfsUpload = (function(){ "use strict"; return et2_file.extend(
|
|||||||
return extra;
|
return extra;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A file upload is finished, update the UI
|
||||||
|
*/
|
||||||
|
finishUpload: function(file, response) {
|
||||||
|
var result = this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
if(typeof response == 'string') response = jQuery.parseJSON(response);
|
||||||
|
if(response.response[0] && typeof response.response[0].data.length == 'undefined') {
|
||||||
|
for(var key in response.response[0].data) {
|
||||||
|
var value = response.response[0].data[key];
|
||||||
|
if(value && value.path)
|
||||||
|
{
|
||||||
|
this._addFile(value);
|
||||||
|
jQuery("[data-file='"+file.fileName+"']",this.progress).hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
_addFile: function(file_data) {
|
_addFile: function(file_data) {
|
||||||
var row = jQuery(document.createElement("tr"))
|
var row = jQuery(document.createElement("tr"))
|
||||||
.attr("data-path", file_data.path)
|
.attr("data-path", file_data.path)
|
||||||
@ -776,6 +787,15 @@ var et2_vfsUpload = (function(){ "use strict"; return et2_file.extend(
|
|||||||
var mime = et2_createWidget('vfs-mime',{value: file_data},this);
|
var mime = et2_createWidget('vfs-mime',{value: file_data},this);
|
||||||
var vfs = et2_createWidget('vfs', {value: file_data}, this);
|
var vfs = et2_createWidget('vfs', {value: file_data}, 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
|
// Add in delete button
|
||||||
if (!this.options.readonly)
|
if (!this.options.readonly)
|
||||||
{
|
{
|
||||||
|
@ -995,6 +995,16 @@ class Contacts extends Contacts\Storage
|
|||||||
$contact['uid'] = $to_write['uid'];
|
$contact['uid'] = $to_write['uid'];
|
||||||
$contact['etag'] = $to_write['etag'];
|
$contact['etag'] = $to_write['etag'];
|
||||||
|
|
||||||
|
// Clear any files saved with new entries
|
||||||
|
// They've been dealt with already and they cause errors with linking
|
||||||
|
foreach(array_keys($this->customfields) as $field)
|
||||||
|
{
|
||||||
|
if(is_array($to_write[Storage::CF_PREFIX.$field]))
|
||||||
|
{
|
||||||
|
unset($to_write[Storage::CF_PREFIX.$field]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if contact is an account and account-relevant data got updated, handle it like account got updated
|
// if contact is an account and account-relevant data got updated, handle it like account got updated
|
||||||
if ($contact['account_id'] && $isUpdate &&
|
if ($contact['account_id'] && $isUpdate &&
|
||||||
($old['email'] != $contact['email'] || $old['n_family'] != $contact['n_family'] || $old['n_given'] != $contact['n_given']))
|
($old['email'] != $contact['email'] || $old['n_family'] != $contact['n_family'] || $old['n_given'] != $contact['n_given']))
|
||||||
|
@ -1051,7 +1051,7 @@ class Sql extends Api\Storage
|
|||||||
* @param array $extra_cols =array() extra-data to be saved
|
* @param array $extra_cols =array() extra-data to be saved
|
||||||
* @return bool false on success, errornumber on failure
|
* @return bool false on success, errornumber on failure
|
||||||
*/
|
*/
|
||||||
function save_customfields($data, array $extra_cols=array())
|
function save_customfields(&$data, array $extra_cols=array())
|
||||||
{
|
{
|
||||||
return parent::save_customfields($data, array('contact_owner' => $data['owner'])+$extra_cols);
|
return parent::save_customfields($data, array('contact_owner' => $data['owner'])+$extra_cols);
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,10 @@ class Customfields extends Transformer
|
|||||||
$field_name = $this->id[0] == self::$prefix && $customfields[substr($this->id,1)] ? $this->id : self::form_name($form_name != self::GLOBAL_ID ? $form_name : $cname, $field);
|
$field_name = $this->id[0] == self::$prefix && $customfields[substr($this->id,1)] ? $this->id : self::form_name($form_name != self::GLOBAL_ID ? $form_name : $cname, $field);
|
||||||
$valid =& self::get_array($validated, $field_name, true);
|
$valid =& self::get_array($validated, $field_name, true);
|
||||||
|
|
||||||
if (is_array($valid)) $valid = implode(',', $valid);
|
// Arrays are not valid, but leave filemanager alone, we'll catch it
|
||||||
|
// when saving. This allows files for new entries.
|
||||||
|
if (is_array($valid) && $field_settings['type'] !== 'filemanager') $valid = implode(',', $valid);
|
||||||
|
|
||||||
// NULL is valid for most fields, but not custom fields due to backend handling
|
// NULL is valid for most fields, but not custom fields due to backend handling
|
||||||
// See so_sql_cf->save()
|
// See so_sql_cf->save()
|
||||||
if (is_null($valid)) $valid = false;
|
if (is_null($valid)) $valid = false;
|
||||||
@ -414,4 +417,58 @@ class Customfields extends Transformer
|
|||||||
//error_log(__METHOD__."() $form_name $field: ".array2string($value).' --> '.array2string($value));
|
//error_log(__METHOD__."() $form_name $field: ".array2string($value).' --> '.array2string($value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle any uploaded files that weren't dealt with immediately when uploaded.
|
||||||
|
* This usually happens for new entries, where we don't have the entry's ID
|
||||||
|
* to properly file it in the VFS. Files are stored temporarily until we
|
||||||
|
* have the ID, then here we move the files to their proper location.
|
||||||
|
*
|
||||||
|
* @staticvar array $_customfields List of custom field data, kept to avoid
|
||||||
|
* loading it multiple times if called again.
|
||||||
|
*
|
||||||
|
* @param string $app Current application
|
||||||
|
* @param string $entry_id Application ID of the new entry
|
||||||
|
* @param Array $values Array of entry data, including custom fields.
|
||||||
|
* File information from the VFS widget (via self::validate()) will be found &
|
||||||
|
* dealt with. Successful or not, the value is cleared to avoid trying to insert it into
|
||||||
|
* the database, which would generate errors.
|
||||||
|
* @param Array $customfields Pass the custom field list if you have it to avoid loading it again
|
||||||
|
*/
|
||||||
|
public static function handle_files($app, $entry_id, &$values, &$customfields = array())
|
||||||
|
{
|
||||||
|
if(!is_array($values) || !$entry_id) return;
|
||||||
|
|
||||||
|
if(!$customfields)
|
||||||
|
{
|
||||||
|
static $_customfields = array();
|
||||||
|
if(!$_customfields[$app])
|
||||||
|
{
|
||||||
|
$_customfields[$app] = Api\Storage\Customfields::get($app);
|
||||||
|
}
|
||||||
|
$customfields = $_customfields[$app];
|
||||||
|
}
|
||||||
|
foreach ($customfields as $field_name => $field)
|
||||||
|
{
|
||||||
|
if($field['type'] == 'filemanager')
|
||||||
|
{
|
||||||
|
$value =& $values[static::$prefix.$field_name];
|
||||||
|
static::handle_file($entry_id, $field, $value);
|
||||||
|
unset($values[static::$prefix.$field_name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function handle_file($entry_id, $field, $value)
|
||||||
|
{
|
||||||
|
$path = Vfs::get_vfs_path($field['app'].":$entry_id:".$field['label']);
|
||||||
|
if($path)
|
||||||
|
{
|
||||||
|
foreach($value as $file)
|
||||||
|
{
|
||||||
|
$file['tmp_name'] = Api\Vfs::PREFIX.$file['path'];
|
||||||
|
Vfs::store_file($path, $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,13 +85,13 @@ class File extends Etemplate\Widget
|
|||||||
}
|
}
|
||||||
foreach($file_list as $file)
|
foreach($file_list as $file)
|
||||||
{
|
{
|
||||||
self::process_uploaded_file($field, $file, $mime, $file_data);
|
static::process_uploaded_file($field, $file, $mime, $file_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Just one file
|
// Just one file
|
||||||
self::process_uploaded_file($field, $files, $mime, $file_data);
|
static::process_uploaded_file($field, $files, $mime, $file_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,11 +56,15 @@ class Vfs extends File
|
|||||||
if(!is_numeric($id))
|
if(!is_numeric($id))
|
||||||
{
|
{
|
||||||
$_id = self::expand_name($id,0,0,0,0,self::$request->content);
|
$_id = self::expand_name($id,0,0,0,0,self::$request->content);
|
||||||
if($_id != $id)
|
if($_id != $id && $_id)
|
||||||
{
|
{
|
||||||
$id = $_id;
|
$id = $_id;
|
||||||
$form_name = "$app:$id:$relpath";
|
$form_name = "$app:$id:$relpath";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$value =& self::get_array(self::$request->content, $form_name, true);
|
$value =& self::get_array(self::$request->content, $form_name, true);
|
||||||
$path = Api\Link::vfs_path($app,$id,'',true);
|
$path = Api\Link::vfs_path($app,$id,'',true);
|
||||||
@ -113,9 +117,23 @@ class Vfs extends File
|
|||||||
public static function ajax_upload()
|
public static function ajax_upload()
|
||||||
{
|
{
|
||||||
parent::ajax_upload();
|
parent::ajax_upload();
|
||||||
foreach($_FILES as $file)
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process one uploaded file. There should only be one per request...
|
||||||
|
*
|
||||||
|
* Overriden from the parent to see if we can safely show the thumbnail immediately
|
||||||
|
*/
|
||||||
|
protected static function process_uploaded_file($field, Array &$file, $mime, Array &$file_data)
|
||||||
{
|
{
|
||||||
self::store_file($_REQUEST['path'] ? $_REQUEST['path'] : $_REQUEST['widget_id'], $file);
|
parent::process_uploaded_file($field, $file, $mime, $file_data);
|
||||||
|
$path = self::store_file($_REQUEST['path'] ? $_REQUEST['path'] : $_REQUEST['widget_id'], $file);
|
||||||
|
if($path)
|
||||||
|
{
|
||||||
|
$file_data[basename($file['tmp_name'])]['name'] = $file['name'];
|
||||||
|
$file_data[basename($file['tmp_name'])]['path'] = $path;
|
||||||
|
$file_data[basename($file['tmp_name'])]['mime'] = $file['type'];
|
||||||
|
$file_data[basename($file['tmp_name'])]['mtime'] = time();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +250,7 @@ class Vfs extends File
|
|||||||
* When the form is submitted, the information for all files uploaded is available in the returned
|
* When the form is submitted, the information for all files uploaded is available in the returned
|
||||||
* $content array and the application should deal with the file.
|
* $content array and the application should deal with the file.
|
||||||
*/
|
*/
|
||||||
public static function store_file($path, $file)
|
public static function store_file($path, &$file)
|
||||||
{
|
{
|
||||||
$name = $_REQUEST['widget_id'];
|
$name = $_REQUEST['widget_id'];
|
||||||
|
|
||||||
@ -242,16 +260,17 @@ class Vfs extends File
|
|||||||
$path = self::get_vfs_path($path);
|
$path = self::get_vfs_path($path);
|
||||||
}
|
}
|
||||||
$filename = $file['name'];
|
$filename = $file['name'];
|
||||||
if (substr($path,-1) != '/')
|
if ($path && substr($path,-1) != '/')
|
||||||
{
|
{
|
||||||
// add extension to path
|
// add extension to path
|
||||||
$parts = explode('.',$filename);
|
$parts = explode('.',$filename);
|
||||||
if (($extension = array_pop($parts)) && Api\MimeMagic::ext2mime($extension)) // really an extension --> add it to path
|
if (($extension = array_pop($parts)) && Api\MimeMagic::ext2mime($extension)) // really an extension --> add it to path
|
||||||
{
|
{
|
||||||
$path .= '.'.$extension;
|
$path .= '.'.$extension;
|
||||||
|
$file['name'] = Api\Vfs::basename($path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // multiple upload with dir given (trailing slash)
|
else if ($path) // multiple upload with dir given (trailing slash)
|
||||||
{
|
{
|
||||||
$path .= Api\Vfs::encodePathComponent($filename);
|
$path .= Api\Vfs::encodePathComponent($filename);
|
||||||
}
|
}
|
||||||
@ -331,10 +350,15 @@ class Vfs extends File
|
|||||||
if(!is_numeric($id))
|
if(!is_numeric($id))
|
||||||
{
|
{
|
||||||
$_id = self::expand_name($id,0,0,0,0,self::$request->content);
|
$_id = self::expand_name($id,0,0,0,0,self::$request->content);
|
||||||
if($_id != $id)
|
if($_id != $id && $_id)
|
||||||
{
|
{
|
||||||
$id = $_id;
|
$id = $_id;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ID didn't resolve, try again without it as a 'new record'
|
||||||
|
return static::get_vfs_path("$app::$relpath");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$path = Api\Link::vfs_path($app,$id,'',true);
|
$path = Api\Link::vfs_path($app,$id,'',true);
|
||||||
}
|
}
|
||||||
|
@ -216,14 +216,18 @@ class Storage extends Storage\Base
|
|||||||
* @param array $extra_cols =array() extra-data to be saved
|
* @param array $extra_cols =array() extra-data to be saved
|
||||||
* @return bool false on success, errornumber on failure
|
* @return bool false on success, errornumber on failure
|
||||||
*/
|
*/
|
||||||
function save_customfields($data, array $extra_cols=array())
|
function save_customfields(&$data, array $extra_cols=array())
|
||||||
{
|
{
|
||||||
|
$id = isset($data[$this->autoinc_id]) ? $data[$this->autoinc_id] : $data[$this->db_key_cols[$this->autoinc_id]];
|
||||||
|
|
||||||
|
\EGroupware\Api\Etemplate\Widget\Customfields::handle_files($this->app, $id, $data, $this->customfields);
|
||||||
|
|
||||||
foreach (array_keys((array)$this->customfields) as $name)
|
foreach (array_keys((array)$this->customfields) as $name)
|
||||||
{
|
{
|
||||||
if (!isset($data[$field = $this->get_cf_field($name)])) continue;
|
if (!isset($data[$field = $this->get_cf_field($name)])) continue;
|
||||||
|
|
||||||
$where = array(
|
$where = array(
|
||||||
$this->extra_id => isset($data[$this->autoinc_id]) ? $data[$this->autoinc_id] : $data[$this->db_key_cols[$this->autoinc_id]],
|
$this->extra_id => $id,
|
||||||
$this->extra_key => $name,
|
$this->extra_key => $name,
|
||||||
);
|
);
|
||||||
$is_multiple = $this->is_multiple($name);
|
$is_multiple = $this->is_multiple($name);
|
||||||
|
@ -630,6 +630,10 @@ class infolog_so
|
|||||||
$this->db->delete($this->extra_table,$where,__LINE__,__FILE__);
|
$this->db->delete($this->extra_table,$where,__LINE__,__FILE__);
|
||||||
}
|
}
|
||||||
$to_delete = array();
|
$to_delete = array();
|
||||||
|
|
||||||
|
// Deal with files in new entries
|
||||||
|
Api\Etemplate\Widget\Customfields::handle_files('infolog',$info_id,$values);
|
||||||
|
|
||||||
foreach($values as $key => $val)
|
foreach($values as $key => $val)
|
||||||
{
|
{
|
||||||
if ($key[0] != '#')
|
if ($key[0] != '#')
|
||||||
|
Loading…
Reference in New Issue
Block a user