avatar 1
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\EntryPoints;
|
||||
|
||||
@@ -37,9 +37,11 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
'image/gif',
|
||||
);
|
||||
|
||||
protected $imageSizes = array(
|
||||
'x-small' => array(64, 64),
|
||||
'small' => array(128, 128),
|
||||
protected $imageSizes = array(
|
||||
'xxx-small' => array(19, 19),
|
||||
'xx-small' => array(32, 32),
|
||||
'x-small' => array(64, 64),
|
||||
'small' => array(128, 128),
|
||||
'medium' => array(256, 256),
|
||||
'large' => array(512, 512),
|
||||
'x-large' => array(864, 864),
|
||||
@@ -48,16 +50,16 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
|
||||
|
||||
public function run()
|
||||
{
|
||||
{
|
||||
$id = $_GET['id'];
|
||||
if (empty($id)) {
|
||||
throw new BadRequest();
|
||||
}
|
||||
}
|
||||
|
||||
$size = null;
|
||||
$size = null;
|
||||
if (!empty($_GET['size'])) {
|
||||
$size = $_GET['size'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->show($id, $size);
|
||||
}
|
||||
@@ -68,10 +70,10 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
|
||||
if (!$attachment) {
|
||||
throw new NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
if ($attachment->get('parentId') && $attachment->get('parentType')) {
|
||||
$parent = $this->getEntityManager()->getEntity($attachment->get('parentType'), $attachment->get('parentId'));
|
||||
$parent = $this->getEntityManager()->getEntity($attachment->get('parentType'), $attachment->get('parentId'));
|
||||
if ($parent && !$this->getAcl()->check($parent)) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
@@ -94,8 +96,8 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
$thumbFilePath = "data/upload/thumbs/{$attachment->id}_{$size}";
|
||||
|
||||
if (!file_exists($thumbFilePath)) {
|
||||
$targetImage = $this->getThumbImage($filePath, $fileType, $size);
|
||||
ob_start();
|
||||
$targetImage = $this->getThumbImage($filePath, $fileType, $size);
|
||||
ob_start();
|
||||
|
||||
switch ($fileType) {
|
||||
case 'image/jpeg':
|
||||
@@ -106,31 +108,31 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
break;
|
||||
case 'image/gif':
|
||||
imagegif($targetImage);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
$contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
imagedestroy($targetImage);
|
||||
$this->getContainer()->get('fileManager')->putContents($thumbFilePath, $contents);
|
||||
}
|
||||
$filePath = $thumbFilePath;
|
||||
imagedestroy($targetImage);
|
||||
$this->getContainer()->get('fileManager')->putContents($thumbFilePath, $contents);
|
||||
}
|
||||
$filePath = $thumbFilePath;
|
||||
|
||||
} else {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($size)) {
|
||||
if (!empty($size)) {
|
||||
$fileName = $attachment->id . '_' . $size . '.jpg';
|
||||
} else {
|
||||
$fileName = $attachment->get('name');
|
||||
}
|
||||
header('Content-Disposition:inline;filename="'.$fileName.'"');
|
||||
}
|
||||
header('Content-Disposition:inline;filename="'.$fileName.'"');
|
||||
if (!empty($fileType)) {
|
||||
header('Content-Type: ' . $fileType);
|
||||
}
|
||||
}
|
||||
header('Pragma: public');
|
||||
$fileSize = filesize($filePath);
|
||||
$fileSize = filesize($filePath);
|
||||
if ($fileSize) {
|
||||
header('Content-Length: ' . $fileSize);
|
||||
}
|
||||
@@ -148,11 +150,11 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
|
||||
if ($originalWidth <= $width && $originalHeight <= $height) {
|
||||
$targetWidth = $originalWidth;
|
||||
$targetHeight = $originalHeight;
|
||||
$targetHeight = $originalHeight;
|
||||
} else {
|
||||
if ($originalWidth > $originalHeight) {
|
||||
$targetWidth = $width;
|
||||
$targetHeight = $originalHeight / ($originalWidth / $width);
|
||||
$targetHeight = $originalHeight / ($originalWidth / $width);
|
||||
if ($targetHeight > $height) {
|
||||
$targetHeight = $height;
|
||||
$targetWidth = $originalWidth / ($originalHeight / $height);
|
||||
@@ -165,13 +167,13 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
$targetHeight = $originalHeight / ($originalWidth / $width);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
|
||||
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
|
||||
switch ($fileType) {
|
||||
case 'image/jpeg':
|
||||
$sourceImage = imagecreatefromjpeg($filePath);
|
||||
imagecopyresized($targetImage, $sourceImage, 0, 0, 0, 0, $targetWidth, $targetHeight, $originalWidth, $originalHeight);
|
||||
imagecopyresampled ($targetImage, $sourceImage, 0, 0, 0, 0, $targetWidth, $targetHeight, $originalWidth, $originalHeight);
|
||||
break;
|
||||
case 'image/png':
|
||||
$sourceImage = imagecreatefrompng($filePath);
|
||||
@@ -183,8 +185,8 @@ class Image extends \Espo\Core\EntryPoints\Base
|
||||
break;
|
||||
case 'image/gif':
|
||||
$sourceImage = imagecreatefromgif($filePath);
|
||||
imagecopyresized($targetImage, $sourceImage, 0, 0, 0, 0, $targetWidth, $targetHeight, $originalWidth, $originalHeight);
|
||||
break;
|
||||
imagecopyresampled($targetImage, $sourceImage, 0, 0, 0, 0, $targetWidth, $targetHeight, $originalWidth, $originalHeight);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
"password": "Password",
|
||||
"passwordConfirm": "Confirm Password",
|
||||
"newPassword": "New Password",
|
||||
"newPasswordConfirm": "Confirm New Password"
|
||||
"newPasswordConfirm": "Confirm New Password",
|
||||
"avatar": "Avatar"
|
||||
},
|
||||
"links": {
|
||||
"teams": "Teams",
|
||||
@@ -30,7 +31,8 @@
|
||||
"Username": "Username",
|
||||
"Email Address": "Email Address",
|
||||
"Password": "Password",
|
||||
"Login": "Login"
|
||||
"Login": "Login",
|
||||
"Setup Avatar": "Setup Avatar"
|
||||
},
|
||||
"tooltips": {
|
||||
"defaultTeam": "All records created by this user will be related to this team by default.",
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
"Flotr": {
|
||||
"path": "client/lib/flotr2.min.js",
|
||||
"exportsTo": "window",
|
||||
"exportsAs": "Flotr"
|
||||
"exportsAs": "Flotr"
|
||||
},
|
||||
"Summernote": {
|
||||
"path": "client/lib/summernote.min.js",
|
||||
"exportsTo": "$",
|
||||
"exportsAs": "summernote"
|
||||
},
|
||||
"exportsAs": "summernote"
|
||||
},
|
||||
"Textcomplete": {
|
||||
"path": "client/lib/jquery.textcomplete.js",
|
||||
"exportsTo": "$",
|
||||
@@ -18,5 +18,10 @@
|
||||
"path": "client/lib/select2.min.js",
|
||||
"exportsTo": "$",
|
||||
"exportsAs": "select2"
|
||||
},
|
||||
"Cropper": {
|
||||
"path": "client/lib/cropper.min.js",
|
||||
"exportsTo": "$",
|
||||
"exportsAs": "cropper"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,11 @@
|
||||
"roles": {
|
||||
"type": "linkMultiple",
|
||||
"tooltip": true
|
||||
},
|
||||
"avatar": {
|
||||
"type": "image",
|
||||
"view": "User.Fields.Avatar",
|
||||
"previewSize": "small"
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
/*!
|
||||
* Cropper v0.7.4-beta
|
||||
* https://github.com/fengyuanchen/cropper
|
||||
*
|
||||
* Copyright 2014 Fengyuan Chen
|
||||
* Released under the MIT license
|
||||
*/
|
||||
|
||||
.cropper-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
|
||||
.cropper-container img {
|
||||
width: 100%;
|
||||
max-width: none !important;
|
||||
height: 100%;
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.cropper-modal,
|
||||
.cropper-canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.cropper-canvas {
|
||||
background-color: #fff;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.cropper-modal {
|
||||
background-color: #000;
|
||||
filter: alpha(opacity=50);
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.cropper-dragger {
|
||||
position: absolute;
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
}
|
||||
|
||||
.cropper-viewer {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
outline-width: 1px;
|
||||
outline-style: solid;
|
||||
outline-color: #69f;
|
||||
outline-color: rgba(51, 102, 255, .75);
|
||||
}
|
||||
|
||||
.cropper-dashed {
|
||||
position: absolute;
|
||||
display: block;
|
||||
filter: alpha(opacity=50);
|
||||
border: 0 dashed #fff;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.cropper-dashed.dashed-h {
|
||||
top: 33.3%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 33.3%;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.cropper-dashed.dashed-v {
|
||||
top: 0;
|
||||
left: 33.3%;
|
||||
width: 33.3%;
|
||||
height: 100%;
|
||||
border-right-width: 1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.cropper-face,
|
||||
.cropper-line,
|
||||
.cropper-point {
|
||||
position: absolute;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: alpha(opacity=10);
|
||||
opacity: .1;
|
||||
}
|
||||
|
||||
.cropper-face {
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: move;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.cropper-line {
|
||||
background-color: #69f;
|
||||
}
|
||||
|
||||
.cropper-line.line-e {
|
||||
top: 0;
|
||||
right: -3px;
|
||||
width: 5px;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.cropper-line.line-n {
|
||||
top: -3px;
|
||||
left: 0;
|
||||
height: 5px;
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.cropper-line.line-w {
|
||||
top: 0;
|
||||
left: -3px;
|
||||
width: 5px;
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.cropper-line.line-s {
|
||||
bottom: -3px;
|
||||
left: 0;
|
||||
height: 5px;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.cropper-point {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background-color: #69f;
|
||||
filter: alpha(opacity=75);
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.cropper-point.point-e {
|
||||
top: 50%;
|
||||
right: -3px;
|
||||
margin-top: -3px;
|
||||
cursor: e-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-n {
|
||||
top: -3px;
|
||||
left: 50%;
|
||||
margin-left: -3px;
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-w {
|
||||
top: 50%;
|
||||
left: -3px;
|
||||
margin-top: -3px;
|
||||
cursor: w-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-s {
|
||||
bottom: -3px;
|
||||
left: 50%;
|
||||
margin-left: -3px;
|
||||
cursor: s-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-ne {
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
cursor: ne-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-nw {
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
cursor: nw-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-sw {
|
||||
bottom: -3px;
|
||||
left: -3px;
|
||||
cursor: sw-resize;
|
||||
}
|
||||
|
||||
.cropper-point.point-se {
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: se-resize;
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cropper-point.point-se:before {
|
||||
position: absolute;
|
||||
right: -50%;
|
||||
bottom: -50%;
|
||||
display: block;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
content: " ";
|
||||
background-color: #69f;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.cropper-point.point-se {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.cropper-point.point-se {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.cropper-point.point-se {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
filter: alpha(opacity=75);
|
||||
opacity: .75;
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper classes for JavaScript */
|
||||
|
||||
.cropper-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.cropper-invisible {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
width: auto !important;
|
||||
max-width: none !important;
|
||||
height: auto !important;
|
||||
max-height: none !important;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.cropper-move {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.cropper-crop {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.cropper-disabled .cropper-canvas,
|
||||
.cropper-disabled .cropper-face,
|
||||
.cropper-disabled .cropper-line,
|
||||
.cropper-disabled .cropper-point {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
Vendored
+9
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
|
||||
<link href="client/css/cropper.css" rel="stylesheet">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div style="text-align: center;" class="image-container"></div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default" data-action="zoomIn"><span class="glyphicon glyphicon-zoom-in"></span></button>
|
||||
<button class="btn btn-default" data-action="zoomOut"><span class="glyphicon glyphicon-zoom-out"></span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
|
||||
@@ -50,16 +50,16 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
var $div = $(e.currentTarget).parent();
|
||||
this.deleteAttachment();
|
||||
$div.parent().remove();
|
||||
},
|
||||
},
|
||||
'change input.file': function (e) {
|
||||
var $file = $(e.currentTarget);
|
||||
var files = e.currentTarget.files;
|
||||
var files = e.currentTarget.files;
|
||||
if (files.length) {
|
||||
this.uploadFile(files[0]);
|
||||
$file.replaceWith($file.clone(true));
|
||||
}
|
||||
}
|
||||
},
|
||||
'click a[data-action="showImagePreview"]': function (e) {
|
||||
'click a[data-action="showImagePreview"]': function (e) {
|
||||
var id = $(e.currentTarget).data('id');
|
||||
this.createView('preview', 'Modals.ImagePreview', {
|
||||
id: id,
|
||||
@@ -121,7 +121,7 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
if (this.mode == 'edit') {
|
||||
if (this.mode == 'edit') {
|
||||
this.$attachment = this.$el.find('div.attachment');
|
||||
|
||||
var name = this.model.get(this.nameName);
|
||||
@@ -129,9 +129,9 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
var id = this.model.get(this.idName);
|
||||
if (id) {
|
||||
this.addAttachmentBox(name, type, id);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getDetailPreview: function (name, type, id) {
|
||||
var preview = name;
|
||||
@@ -141,7 +141,7 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
case 'image/jpeg':
|
||||
case 'image/gif':
|
||||
preview = '<a data-action="showImagePreview" data-id="' + id + '" href="?entryPoint=image&id=' + id + '"><img src="?entryPoint=image&size='+this.previewSize+'&id=' + id + '"></a>';
|
||||
}
|
||||
}
|
||||
return preview;
|
||||
},
|
||||
|
||||
@@ -179,17 +179,17 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
}
|
||||
},
|
||||
|
||||
deleteAttachment: function () {
|
||||
var id = this.model.get(this.idName);
|
||||
var o = {};
|
||||
deleteAttachment: function () {
|
||||
var id = this.model.get(this.idName);
|
||||
var o = {};
|
||||
o[this.idName] = null;
|
||||
o[this.nameName] = null;
|
||||
o[this.nameName] = null;
|
||||
this.model.set(o);
|
||||
|
||||
this.$attachment.empty();
|
||||
|
||||
if (id) {
|
||||
if (this.model.isNew()) {
|
||||
if (this.model.isNew()) {
|
||||
this.getModelFactory().create('Attachment', function (attachment) {
|
||||
attachment.id = id;
|
||||
attachment.destroy();
|
||||
@@ -200,16 +200,16 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
|
||||
setAttachment: function (attachment) {
|
||||
var arr = _.clone(this.model.get(this.idsName));
|
||||
var o = {};
|
||||
var o = {};
|
||||
o[this.idName] = attachment.id;
|
||||
o[this.nameName] = attachment.get('name');
|
||||
this.model.set(o);
|
||||
},
|
||||
|
||||
uploadFile: function (file) {
|
||||
uploadFile: function (file) {
|
||||
var isCanceled = false;
|
||||
|
||||
this.getModelFactory().create('Attachment', function (attachment) {
|
||||
this.getModelFactory().create('Attachment', function (attachment) {
|
||||
var $att = this.addAttachmentBox(file.name, file.type);
|
||||
|
||||
this.$el.find('.attachment-button').addClass('hidden');
|
||||
@@ -221,42 +221,53 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
|
||||
var fileReader = new FileReader();
|
||||
fileReader.onload = function (e) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'Attachment/action/upload',
|
||||
data: e.target.result,
|
||||
contentType: 'multipart/encrypted',
|
||||
timeout: 0,
|
||||
}).done(function (data) {
|
||||
attachment.id = data.attachmentId;
|
||||
attachment.set('name', file.name);
|
||||
attachment.set('type', file.type || 'text/plain');
|
||||
attachment.set('size', file.size);
|
||||
attachment.set('role', 'Attachment');
|
||||
attachment.set('parentType', this.model.name);
|
||||
attachment.set('parentId', this.model.id);
|
||||
|
||||
attachment.once('sync', function () {
|
||||
if (!isCanceled) {
|
||||
$att.trigger('ready');
|
||||
this.setAttachment(attachment);
|
||||
}
|
||||
}, this);
|
||||
attachment.save();
|
||||
this.handleFileUpload(file, e.target.result, function (result, fileParams) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: 'Attachment/action/upload',
|
||||
data: result,
|
||||
contentType: 'multipart/encrypted',
|
||||
timeout: 0,
|
||||
}).done(function (data) {
|
||||
attachment.id = data.attachmentId;
|
||||
attachment.set('name', fileParams.name);
|
||||
attachment.set('type', fileParams.type || 'text/plain');
|
||||
attachment.set('size', fileParams.size);
|
||||
attachment.set('role', 'Attachment');
|
||||
attachment.set('parentType', this.model.name);
|
||||
attachment.set('parentId', this.model.id);
|
||||
|
||||
attachment.once('sync', function () {
|
||||
if (!isCanceled) {
|
||||
$att.trigger('ready');
|
||||
this.setAttachment(attachment);
|
||||
}
|
||||
}, this);
|
||||
attachment.save();
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
fileReader.readAsDataURL(file);
|
||||
fileReader.readAsDataURL(file);
|
||||
}, this);
|
||||
},
|
||||
|
||||
handleFileUpload: function (file, contents, callback) {
|
||||
var params = {
|
||||
name: file.name,
|
||||
type: file.type,
|
||||
size: file.size
|
||||
};
|
||||
callback(contents, params);
|
||||
},
|
||||
|
||||
addAttachmentBox: function (name, type, id) {
|
||||
this.$attachment.empty();
|
||||
|
||||
var self = this;
|
||||
var self = this;
|
||||
|
||||
var removeLink = '<a href="javascript:" class="remove-attachment pull-right"><span class="glyphicon glyphicon-remove"></span></a>';
|
||||
|
||||
var preview = name;
|
||||
var preview = name;
|
||||
if (this.showPreview && id) {
|
||||
preview = this.getEditPreview(name, type, id);
|
||||
}
|
||||
@@ -267,11 +278,11 @@ Espo.define('Views.Fields.File', 'Views.Fields.Link', function (Dep) {
|
||||
.append($('<span class="preview">' + preview + '</span>').css('width', '270px'))
|
||||
.append(removeLink);
|
||||
|
||||
var $container = $('<div>').append($att);
|
||||
this.$attachment.append($container);
|
||||
var $container = $('<div>').append($att);
|
||||
this.$attachment.append($container);
|
||||
|
||||
if (!id) {
|
||||
var $loading = $('<span class="small">' + this.translate('Uploading...') + '</span>');
|
||||
var $loading = $('<span class="small">' + this.translate('Uploading...') + '</span>');
|
||||
$container.append($loading);
|
||||
$att.on('ready', function () {
|
||||
$loading.html(self.translate('Ready'));
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.Fields.Image', 'Views.Fields.File', function (Dep) {
|
||||
|
||||
@@ -36,7 +36,7 @@ Espo.define('Views.Fields.Image', 'Views.Fields.File', function (Dep) {
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
|
||||
if ('previewSize' in this.params) {
|
||||
if ('previewSize' in this.params && this.params.previewSize) {
|
||||
this.previewSize = this.params.previewSize;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.Modal', 'View', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
return Dep.extend({
|
||||
|
||||
cssName: 'modal-dialog',
|
||||
|
||||
header: false,
|
||||
header: false,
|
||||
|
||||
dialog: null,
|
||||
|
||||
@@ -38,7 +38,7 @@ Espo.define('Views.Modal', 'View', function (Dep) {
|
||||
onClick: function (dialog) {
|
||||
dialog.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
width: false,
|
||||
@@ -50,7 +50,7 @@ Espo.define('Views.Modal', 'View', function (Dep) {
|
||||
this.options = this.options || {};
|
||||
this.options.el = this.containerSelector;
|
||||
|
||||
this.on('render', function () {
|
||||
this.on('render', function () {
|
||||
$(containerSelector).remove();
|
||||
$('<div />').css('display', 'none').attr('id', id).appendTo('body');
|
||||
|
||||
@@ -72,10 +72,10 @@ Espo.define('Views.Modal', 'View', function (Dep) {
|
||||
this.remove();
|
||||
}.bind(this)
|
||||
});
|
||||
this.setElement(containerSelector + ' .body');
|
||||
this.setElement(containerSelector + ' .body');
|
||||
}, this);
|
||||
|
||||
this.on('after:render', function () {
|
||||
this.on('after:render', function () {
|
||||
$(containerSelector).show();
|
||||
this.dialog.show();
|
||||
});
|
||||
@@ -90,7 +90,7 @@ Espo.define('Views.Modal', 'View', function (Dep) {
|
||||
|
||||
close: function () {
|
||||
this.dialog.close();
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.Modals.ImageCrop', ['Views.Modal', 'lib!Cropper'], function (Dep, Cropper) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
cssName: 'image-crop',
|
||||
|
||||
template: 'modals.image-crop',
|
||||
|
||||
events: {
|
||||
'click [data-action="zoomIn"]': function () {
|
||||
this.$img.cropper('zoom', 0.1);
|
||||
},
|
||||
'click [data-action="zoomOut"]': function () {
|
||||
this.$img.cropper('zoom', -0.1);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
this.header = this.translate('Setup Avatar', 'labels', 'User');
|
||||
|
||||
this.buttons = [
|
||||
{
|
||||
name: 'crop',
|
||||
label: 'Submit',
|
||||
style: 'primary',
|
||||
onClick: function (dialog) {
|
||||
this.crop();
|
||||
}.bind(this)
|
||||
},
|
||||
{
|
||||
name: 'cancel',
|
||||
label: 'Cancel',
|
||||
onClick: function (dialog) {
|
||||
this.close();
|
||||
}.bind(this)
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
var $img = this.$img = $('<img>').attr('src', this.options.contents).addClass('hidden');
|
||||
|
||||
this.$el.find('.image-container').append($img);
|
||||
|
||||
$img.cropper({
|
||||
aspectRatio: 1,
|
||||
movable: true,
|
||||
resizable: true,
|
||||
rotatable: false,
|
||||
});
|
||||
},
|
||||
|
||||
crop: function () {
|
||||
var dataUrl = this.$img.cropper('getDataURL', 'image/jpeg');
|
||||
this.trigger('crop', dataUrl);
|
||||
this.close();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
Espo.define('Views.User.Fields.Avatar', 'Views.Fields.Image', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
handleFileUpload: function (file, contents, callback) {
|
||||
|
||||
this.createView('crop', 'Modals.ImageCrop', {
|
||||
contents: contents
|
||||
}, function (view) {
|
||||
view.render();
|
||||
|
||||
var croped = false;
|
||||
|
||||
this.listenToOnce(view, 'crop', function (croppedContents, params) {
|
||||
croped = true;
|
||||
setTimeout(function () {
|
||||
params = params || {};
|
||||
params.name = 'avatar.jpg';
|
||||
params.type = 'image/jpeg';
|
||||
|
||||
callback(croppedContents, params);
|
||||
}.bind(this), 10);
|
||||
});
|
||||
this.listenToOnce(view, 'remove', function () {
|
||||
if (!croped) {
|
||||
setTimeout(function () {
|
||||
this.render();
|
||||
}.bind(this), 10);
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -17,9 +17,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.User.Record.DetailSide', 'Views.Record.DetailSide', function (Dep) {
|
||||
Espo.define('Views.User.Record.DetailSide', 'Views.Record.DetailSide', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -29,10 +29,10 @@ Espo.define('Views.User.Record.DetailSide', 'Views.Record.DetailSide', function
|
||||
label: false,
|
||||
view: 'Record.Panels.Side',
|
||||
options: {
|
||||
fields: ['teams', 'roles'],
|
||||
fields: ['avatar'],
|
||||
mode: 'detail',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
});
|
||||
|
||||
@@ -17,17 +17,16 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.User.Record.Detail', 'Views.Record.Detail', function (Dep) {
|
||||
Espo.define('Views.User.Record.Detail', 'Views.Record.Detail', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
sideView: false,
|
||||
sideView: 'User.Record.DetailSide',
|
||||
|
||||
editModeEnabled: false,
|
||||
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
this.buttons = _.clone(this.buttons);
|
||||
@@ -58,12 +57,12 @@ Espo.define('Views.User.Record.Detail', 'Views.Record.Detail', function (Dep) {
|
||||
|
||||
if (this.model.id == this.getUser().id) {
|
||||
this.listenTo(this.model, 'after:save', function () {
|
||||
this.getUser().set(this.model.toJSON());
|
||||
this.getUser().set(this.model.toJSON());
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
actionChangePassword: function () {
|
||||
actionChangePassword: function () {
|
||||
this.notify('Loading...');
|
||||
|
||||
this.createView('changePassword', 'Modals.ChangePassword', {
|
||||
@@ -73,7 +72,7 @@ Espo.define('Views.User.Record.Detail', 'Views.Record.Detail', function (Dep) {
|
||||
this.notify(false);
|
||||
|
||||
this.listenToOnce(view, 'changed', function () {
|
||||
setTimeout(function () {
|
||||
setTimeout(function () {
|
||||
this.getBaseController().logout();
|
||||
}.bind(this), 2000);
|
||||
}, this);
|
||||
@@ -94,20 +93,20 @@ Espo.define('Views.User.Record.Detail', 'Views.Record.Detail', function (Dep) {
|
||||
data: {
|
||||
id: this.model.id,
|
||||
}
|
||||
}).done(function (aclData) {
|
||||
}).done(function (aclData) {
|
||||
this.createView('access', 'User.Access', {
|
||||
aclData: aclData,
|
||||
model: this.model,
|
||||
}, function (view) {
|
||||
this.notify(false);
|
||||
view.render();
|
||||
view.render();
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
|
||||
|
||||
},
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.User.Record.EditSide', 'Views.Record.EditSide', function (Dep) {
|
||||
Espo.define('Views.User.Record.EditSide', 'Views.Record.EditSide', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -29,13 +29,13 @@ Espo.define('Views.User.Record.EditSide', 'Views.Record.EditSide', function (Dep
|
||||
label: false,
|
||||
view: 'Record.Panels.Side',
|
||||
options: {
|
||||
fields: ['teams', 'roles'],
|
||||
fields: ['avatar'],
|
||||
mode: 'edit',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -17,20 +17,20 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('Views.User.Record.Edit', 'Views.Record.Edit', function (Dep) {
|
||||
Espo.define('Views.User.Record.Edit', 'Views.Record.Edit', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
sideView: false,
|
||||
sideView: 'User.Record.EditSide',
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
|
||||
if (this.model.id == this.getUser().id) {
|
||||
this.listenTo(this.model, 'after:save', function () {
|
||||
this.getUser().set(this.model.toJSON());
|
||||
this.getUser().set(this.model.toJSON());
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
@@ -43,7 +43,7 @@ Espo.define('Views.User.Record.Edit', 'Views.Record.Edit', function (Dep) {
|
||||
|
||||
var layout = _.clone(simpleLayout);
|
||||
|
||||
if (this.type == 'edit') {
|
||||
if (this.type == 'edit') {
|
||||
layout.push({
|
||||
label: 'Password',
|
||||
rows: [
|
||||
@@ -53,7 +53,7 @@ Espo.define('Views.User.Record.Edit', 'Views.Record.Edit', function (Dep) {
|
||||
params: {
|
||||
required: self.isNew,
|
||||
readyToChange: true
|
||||
}
|
||||
}
|
||||
},{
|
||||
name: 'generatePassword',
|
||||
view: 'User.Fields.GeneratePassword',
|
||||
@@ -65,7 +65,7 @@ Espo.define('Views.User.Record.Edit', 'Views.Record.Edit', function (Dep) {
|
||||
params: {
|
||||
required: self.isNew,
|
||||
readyToChange: true
|
||||
}
|
||||
}
|
||||
},{
|
||||
name: 'passwordInfo',
|
||||
customLabel: '',
|
||||
@@ -101,7 +101,7 @@ Espo.define('Views.User.Record.Edit', 'Views.Record.Edit', function (Dep) {
|
||||
return data;
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user