mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-20 00:58:48 +02:00
Customer portal : Edit profile picture
SVN:trunk[4231]
This commit is contained in:
@@ -21,6 +21,7 @@ namespace Combodo\iTop\Portal\Controller;
|
||||
|
||||
use \Exception;
|
||||
use \IssueLog;
|
||||
use \utils;
|
||||
use \MetaModel;
|
||||
use \UserRights;
|
||||
use \Silex\Application;
|
||||
@@ -34,6 +35,7 @@ use \Combodo\iTop\Renderer\Bootstrap\BsFormRenderer;
|
||||
|
||||
class UserProfileBrickController extends BrickController
|
||||
{
|
||||
const ENUM_FORM_TYPE_PICTURE = 'picture';
|
||||
|
||||
public function DisplayAction(Request $oRequest, Application $oApp, $sBrickId)
|
||||
{
|
||||
@@ -79,6 +81,10 @@ class UserProfileBrickController extends BrickController
|
||||
{
|
||||
$aData['form'] = $this->HandlePasswordForm($oRequest, $oApp);
|
||||
}
|
||||
elseif ($sFormType === static::ENUM_FORM_TYPE_PICTURE)
|
||||
{
|
||||
$aData['form'] = $this->HandlePictureForm($oRequest, $oApp, $sFormMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception('Unknown form type.');
|
||||
@@ -235,6 +241,66 @@ class UserProfileBrickController extends BrickController
|
||||
return $aFormData;
|
||||
}
|
||||
|
||||
public function HandlePictureForm(Request $oRequest, Application $oApp, $sFormMode)
|
||||
{
|
||||
$aFormData = array();
|
||||
$oRequestParams = $oRequest->request;
|
||||
$sPictureAttCode = 'picture';
|
||||
|
||||
// Handling form
|
||||
$sOperation = $oRequestParams->get('operation');
|
||||
// - No operation specified
|
||||
if ($sOperation === null)
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Operation parameter must be specified.');
|
||||
$oApp->abort(500, 'Operation parameter must be specified.');
|
||||
}
|
||||
// - Submit
|
||||
else if ($sOperation === 'submit')
|
||||
{
|
||||
$oRequestFiles = $oRequest->files;
|
||||
$oPictureFile = $oRequestFiles->get($sPictureAttCode);
|
||||
if ($oPictureFile === null)
|
||||
{
|
||||
IssueLog::Error(__METHOD__ . ' at line ' . __LINE__ . ' : Parameter picture must be defined.');
|
||||
$oApp->abort(500, 'Parameter picture must be defined.');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Retrieving image as an ORMDocument
|
||||
$oImage = utils::ReadPostedDocument($sPictureAttCode);
|
||||
// Retrieving current contact
|
||||
$oCurContact = UserRights::GetContactObject();
|
||||
// Resizing image
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($oCurContact), $sPictureAttCode);
|
||||
$aSize = utils::GetImageSize($oImage->GetData());
|
||||
$oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'), $oAttDef->Get('storage_max_height'));
|
||||
// Setting it to the contact
|
||||
$oCurContact->Set($sPictureAttCode, $oImage);
|
||||
// Forcing allowed writing on the object if necessary.
|
||||
$oCurContact->AllowWrite(true);
|
||||
$oCurContact->DBUpdate();
|
||||
}
|
||||
catch (FileUploadException $e)
|
||||
{
|
||||
$aFormData['error'] = $e->GetMessage();
|
||||
}
|
||||
|
||||
$aFormData['picture_url'] = $oImage->GetDownloadURL(get_class($oCurContact), $oCurContact->GetKey(), $sPictureAttCode);
|
||||
$aFormData['validation'] = array(
|
||||
'valid' => true,
|
||||
'messages' => array()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else, submit from another form
|
||||
}
|
||||
|
||||
return $aFormData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -29,7 +29,8 @@ class UserProfileRouter extends AbstractRouter
|
||||
'bind' => 'p_user_profile_brick',
|
||||
'values' => array(
|
||||
'sBrickId' => null
|
||||
))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -41,17 +41,37 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel panel-default user_profile_picture">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Photo</h3>
|
||||
</div>
|
||||
<div class="panel-body" style="position: relative;">
|
||||
<div class="text-center">
|
||||
<img src="{{ sUserPhotoUrl }}" style="max-width: 175px;"/>
|
||||
<!--<input type="file" id="xx" name="xx" />-->
|
||||
<div style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; background-color: #000000; opacity: 0.5;"></div>
|
||||
<div style="position: absolute; bottom: 0.5em; left: 0px; width: 100%; color: #FFFFFF; font-size: 1.5em; font-style: italic;">Picture edition not available in beta</div>
|
||||
<div class="form_alerts">
|
||||
<div class="alert alert-success" role="alert" style="display: none;"></div>
|
||||
<div class="alert alert-warning" role="alert" style="display: none;"></div>
|
||||
<div class="alert alert-error alert-danger" role="alert" style="display: none;"></div>
|
||||
</div>
|
||||
<form id="picture-form" method="POST" action="{{ app['url_generator'].generate('p_user_profile_brick') }}">
|
||||
<input type="hidden" name="current_values[form_type]" value="{{ constant('\\Combodo\\iTop\\Portal\\Controller\\UserProfileBrickController::ENUM_FORM_TYPE_PICTURE') }}" />
|
||||
<input type="hidden" name="operation" value="submit" />
|
||||
<div class="text-center">
|
||||
<span class="preview">
|
||||
<img src="{{ sUserPhotoUrl }}"/>
|
||||
</span>
|
||||
<span class="actions">
|
||||
<button type="button" class="btn btn-default btn_edit">
|
||||
<span class="fa fa-pencil fa-fw"></span>
|
||||
<input id="picture" type="file" name="picture" />
|
||||
</button>
|
||||
{#<button type="button" class="btn btn-default btn_undo" title="{{ 'UI:Button:ResetImage'|dict_s }}" disabled>
|
||||
<span class="fa fa-undo fa-fw"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn_reset" title="{{ 'UI:Button:RemoveImage'|dict_s }}">
|
||||
<span class="fa fa-trash-o fa-fw"></span>
|
||||
</button>#}
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
@@ -136,6 +156,46 @@
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
// Picture form
|
||||
// - JQuery upload widget
|
||||
$('#picture-form #picture').fileupload({
|
||||
dataType: 'json',
|
||||
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
|
||||
disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent)
|
||||
})
|
||||
.on('fileuploadsend', function(oEvent, oData){
|
||||
$('.user_profile_picture .form_alerts .alert-error').hide()
|
||||
$('#page_overlay .overlay_content .content_loader').clone().prependTo('.user_profile_picture .panel-body');
|
||||
})
|
||||
.on('fileuploadalways', function(oEvent, oData){
|
||||
$('.user_profile_picture .content_loader').remove();
|
||||
})
|
||||
.on('fileuploaddone', function(oEvent, oData){
|
||||
if( (oData._response.result.form !== undefined) && (oData._response.result.form.validation.valid === true) )
|
||||
{
|
||||
// Retrieving picture url
|
||||
var sPictureUrl = oData._response.result.form.picture_url;
|
||||
// Replacing form preview image
|
||||
$('#picture-form .preview img').attr('src', sPictureUrl);
|
||||
// Replacing menu image
|
||||
$('#topbar .user_photo, #sidebar .user_photo').css('background-image', 'url("' + sPictureUrl + '")');
|
||||
}
|
||||
})
|
||||
.on('fileuploadfail', function(oEvent, oData){
|
||||
if( (oData._response.jqXHR.responseJSON !== undefined) && (oData._response.jqXHR.responseJSON.error_message !== undefined) )
|
||||
{
|
||||
$('.user_profile_picture .form_alerts .alert-error').show().text(oData._response.jqXHR.responseJSON.error_message);
|
||||
}
|
||||
});
|
||||
// - Undo button
|
||||
/*$('#user-profile-wrapper .actions .btn_undo').on('click', function(oEvent){
|
||||
console.log('Picture undo trigger');
|
||||
});*/
|
||||
// - Reset button
|
||||
$('#user-profile-wrapper .actions .btn_reset').on('click', function(oEvent){
|
||||
console.log('Picture reset trigger');
|
||||
});
|
||||
|
||||
// Submit button
|
||||
$('#user-profile-wrapper .form_buttons .form_btn_submit').off('click').on('click', function(oEvent){
|
||||
oEvent.preventDefault();
|
||||
@@ -168,6 +228,6 @@
|
||||
return false;
|
||||
}
|
||||
});
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
});
|
||||
{% endblock %}
|
||||
@@ -1617,8 +1617,8 @@ output {
|
||||
.form-control:focus {
|
||||
border-color: $brand-primary;
|
||||
outline: 0;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6)
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(234, 125, 30, 0.6); /* Last rgb color is $brand-primary */
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(234, 125, 30, 0.6)
|
||||
}
|
||||
.form-control::-moz-placeholder {
|
||||
color: #dddddd;
|
||||
@@ -2160,8 +2160,8 @@ fieldset[disabled] .btn-default:active,
|
||||
.btn-default.disabled.active,
|
||||
.btn-default[disabled].active,
|
||||
fieldset[disabled] .btn-default.active {
|
||||
background-color: #474949;
|
||||
border-color: #474949
|
||||
background-color: #BBBBBB;
|
||||
border-color: $gray-light;
|
||||
}
|
||||
.btn-default .badge {
|
||||
color: #474949;
|
||||
|
||||
@@ -495,8 +495,50 @@ footer{
|
||||
/**********************/
|
||||
/* Brick user profile */
|
||||
/**********************/
|
||||
.home .userprofile-brick{
|
||||
background-color: #E8E7E7;
|
||||
#user-profile-wrapper .user_profile_picture .content_loader{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding-top: 4em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background-color: black;
|
||||
opacity: 0.5;
|
||||
}
|
||||
#user-profile-wrapper .user_profile_picture .preview{
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
max-width: 175px;
|
||||
max-height: 175px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#user-profile-wrapper .user_profile_picture .actions{
|
||||
display: inline-block;
|
||||
vertical-align: top; /*middle;*/
|
||||
margin-left: 5px;
|
||||
}
|
||||
#user-profile-wrapper .user_profile_picture .actions .btn{
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#user-profile-wrapper .user_profile_picture .actions .btn:last-child{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
#user-profile-wrapper .user_profile_picture .actions .btn.btn_edit{
|
||||
overflow: hidden;
|
||||
}
|
||||
#user-profile-wrapper .user_profile_picture .actions .btn.btn_edit input{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/****************/
|
||||
|
||||
Reference in New Issue
Block a user