mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-21 00:02:17 +02:00
N°7433 - Allow MFA configuration in the portal (#670)
* N°7433 - Extension for MFA * Portal user profile brick * fix mfa tab display * Portal user profile brick * Portal user profile brick * mfa portal action * extensibility on portal to make mfa recovery mode work * Portal user profile brick extension * Portal user profile brick extension * display alert section in user portal profile layout * protect mfa via transaction_id mecanism * Fix transaction ids * Fix when no MFA * N°7433 - Allow MFA configuration in the portal (refactor interfaces) * N°7433 - Allow MFA configuration in the portal (revert unnecessary changes) * N°7433 - Allow MFA configuration in the portal (finer style) * N°7433 - Allow MFA configuration in the portal (PHPDoc update) * N°7433 - PR review --------- Co-authored-by: Eric Espie <eric.espie@combodo.com>
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
{# User profile brick base layout #}
|
||||
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
|
||||
|
||||
{% set oContactForm = forms.contact %}
|
||||
{% set oPreferencesForm = forms.preferences %}
|
||||
{% set oPasswordForm = forms.password %}
|
||||
{% if sTab == "" %}
|
||||
{% set sTab = "user-info" %}
|
||||
{% endif %}
|
||||
|
||||
{% block pPageBodyClass %}{{ parent() }} page_user-profile_brick{% endblock %}
|
||||
|
||||
@@ -20,228 +20,82 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="user-profile-wrapper">
|
||||
{% block pUserProfileWrapper %}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:PersonalInformations:Title'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form id="{{ oContactForm.id }}" class="" method="POST" action="{{ oContactForm.renderer.GetEndpoint()|raw }}">
|
||||
<input type="hidden" name="transaction_id" value="{{ oContactForm.transaction_id }}" />
|
||||
<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>
|
||||
<div class="form_fields">
|
||||
{{ oContactForm.renderer.GetBaseLayout()|raw }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
{% if oBrick.GetShowPictureForm() %}
|
||||
{% block pUserProfilePictureFormContainer %}
|
||||
<div class="panel panel-default user_profile_picture">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:Photo:Title'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body" style="position: relative;">
|
||||
<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">
|
||||
<span type="button" class="btn btn-default btn_edit">
|
||||
<span class="fas fa-pencil-alt fa-fw"></span>
|
||||
<input id="picture" type="file" name="picture" />
|
||||
</span>
|
||||
{#<button type="button" class="btn btn-default btn_undo" title="{{ 'UI:Button:ResetImage'|dict_s }}" disabled>
|
||||
<span class="fas fa-undo fa-fw"></span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn_reset" title="{{ 'UI:Button:RemoveImage'|dict_s }}">
|
||||
<span class="fas fa-trash-o fa-fw"></span>
|
||||
</button>#}
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
<div class="form_alerts">
|
||||
{% if sMessage is defined %}
|
||||
<div id="success-message-content" class="alert alert-success" role="alert">{{ sMessage }}</div>
|
||||
{% else %}
|
||||
<div id="success-message-content" style="display:none;" class="alert alert-success" role="alert"></div>
|
||||
{% endif %}
|
||||
|
||||
{% if oBrick.GetShowPreferencesForm() %}
|
||||
{% block pUserProfilePreferencesFormContainer %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Class:appUserPreferences/Attribute:preferences'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form id="{{ oPreferencesForm.id }}" class="" method="POST" action="{{ oPreferencesForm.renderer.GetEndpoint()|raw }}">
|
||||
<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>
|
||||
<div class="form_fields">
|
||||
{{ oPreferencesForm.renderer.GetBaseLayout()|raw }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
{% if sError is defined %}
|
||||
<div id="error-message-content" class="alert alert-error alert-danger" role="alert">{{ sError }}</div>
|
||||
{% else %}
|
||||
<div id="error-message-content" style="display:none;" class="alert alert-error alert-danger" role="alert"></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<ul class="nav nav-pills _tabs">
|
||||
{% if aTabsValues is defined and aTabsValues|length > 0 %}
|
||||
<li{% if sTab == "user-info" %} class="active"{% endif %} data-id="user-info" data-label="{{ 'MyAccount:UserInfo:Tab:Title'|dict_s }}">
|
||||
<a href="{{ app.url_generator.generate('p_user_profile_brick', {'sBrickId': oBrick.GetId(), 'sDisplayMode': '_self', 'sTab': "user-info"}) }}"
|
||||
id="btn_tab_for_user-info">
|
||||
{{ 'MyAccount:UserInfo:Tab:Title'|dict_s }}
|
||||
</a>
|
||||
</li>
|
||||
{% for aTab in aTabsValues %}
|
||||
<li{% if sTab == aTab.code %} class="active"{% endif %} data-id="{{ aTab.code }}" data-label="{{ aTab.label }}">
|
||||
<a href="{{ app.url_generator.generate('p_user_profile_brick', {'sBrickId': oBrick.GetId(), 'sDisplayMode': '_self', 'sTab': aTab.code}) }}"
|
||||
id="btn_tab_for_{{ aTab.code }}">
|
||||
{{ aTab.label|raw }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
{% if sTab == "user-info" %}
|
||||
{% set oContactForm = forms.contact %}
|
||||
{% set oPreferencesForm = forms.preferences %}
|
||||
{% set oPasswordForm = forms.password %}
|
||||
{% include 'itop-portal-base/portal/templates/bricks/user-profile/user_info.html.twig' %}
|
||||
{% else %}
|
||||
<div id="user-profile-wrapper">
|
||||
<div class="row">
|
||||
{% import "itop-portal-base/portal/templates/helpers/macros.twig" as Macro %}
|
||||
{{ Macro.BlockExtension(aPluginFormData, 'html', oBrick) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if oBrick.GetShowPasswordForm() %}
|
||||
{% block pUserProfilePasswordFormContainer %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:Password:Title'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if oPasswordForm is not null %}
|
||||
<form id="{{ oPasswordForm.id }}" class="" method="POST" action="{{ oPasswordForm.renderer.GetEndpoint()|raw }}" autocomplete="off">
|
||||
<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>
|
||||
<div class="form_fields">
|
||||
{{ oPasswordForm.renderer.GetBaseLayout()|raw }}
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ 'Brick:Portal:UserProfile:Password:CantChangeContactAdministrator'|dict_format(constant('ITOP_APPLICATION_SHORT')) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form_buttons">
|
||||
{% block pUserProfileFormButtons %}
|
||||
<div class="form_btn_regular">
|
||||
{% if sFormMode == constant('\\Combodo\\iTop\\Portal\\Helper\\ObjectFormHandlerHelper::ENUM_MODE_EDIT') %}
|
||||
<input class="btn btn-primary form_btn_submit" type="submit" value="{{ 'Portal:Button:Submit'|dict_s }}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block pPageReadyScripts %}
|
||||
{{ parent() }}
|
||||
{% import "itop-portal-base/portal/templates/helpers/macros.twig" as Macro %}
|
||||
{{ Macro.BlockExtension(aPluginFormData, 'ready_script', oBrick) }}
|
||||
|
||||
// Personal informations form
|
||||
var oContactFormFieldSet = $('#{{ oContactForm.id }} > .form_fields').field_set({{ oContactForm.fieldset|json_encode()|raw }});
|
||||
$('#{{ oContactForm.id }}').portal_form_handler({
|
||||
formmanager_class: "{{ oContactForm.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ oContactForm.formmanager_data|json_encode()|raw }},
|
||||
field_set: oContactFormFieldSet,
|
||||
endpoint: "{{ oContactForm.renderer.GetEndpoint()|raw }}"
|
||||
});
|
||||
|
||||
// Preferences form
|
||||
var oPreferencesFormFieldSet = $('#{{ oPreferencesForm.id }} > .form_fields').field_set({{ oPreferencesForm.fieldset|json_encode()|raw }});
|
||||
$('#{{ oPreferencesForm.id }}').portal_form_handler({
|
||||
formmanager_class: "{{ oPreferencesForm.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ oPreferencesForm.formmanager_data|json_encode()|raw }},
|
||||
field_set: oPreferencesFormFieldSet,
|
||||
endpoint: "{{ oPreferencesForm.renderer.GetEndpoint()|raw }}"
|
||||
});
|
||||
|
||||
{% if oPasswordForm is not null %}
|
||||
// Password form
|
||||
var oPasswordFormFieldSet = $('#{{ oPasswordForm.id }} > .form_fields').field_set({{ oPasswordForm.fieldset|json_encode()|raw }});
|
||||
$('#{{ oPasswordForm.id }}').portal_form_handler({
|
||||
formmanager_class: "{{ oPasswordForm.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ oPasswordForm.formmanager_data|json_encode()|raw }},
|
||||
field_set: oPasswordFormFieldSet,
|
||||
endpoint: "{{ oPasswordForm.renderer.GetEndpoint()|raw }}"
|
||||
});
|
||||
{% if sTab == "" %}
|
||||
{% set sTab = "user-info" %}
|
||||
{% 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');
|
||||
});
|
||||
{% if sTab == "user-info" %}
|
||||
{% set oContactForm = forms.contact %}
|
||||
{% set oPreferencesForm = forms.preferences %}
|
||||
{% set oPasswordForm = forms.password %}
|
||||
{% include 'itop-portal-base/portal/templates/bricks/user-profile/user_info.ready.js.twig' %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
// Submit button
|
||||
$('#user-profile-wrapper .form_buttons .form_btn_submit').off('click').on('click', function(oEvent){
|
||||
oEvent.preventDefault();
|
||||
{% block pPageLiveScriptHelpers %}
|
||||
{{ parent() }}
|
||||
{% import "itop-portal-base/portal/templates/helpers/macros.twig" as Macro %}
|
||||
{{ Macro.BlockExtension(aPluginFormData, 'script', oBrick) }}
|
||||
{% endblock %}
|
||||
|
||||
// Resetting feedback
|
||||
$('#user-profile-wrapper .form_alerts .alert').hide();
|
||||
$('#user-profile-wrapper .form_alerts .alert > p').remove();
|
||||
$('#user-profile-wrapper .form_field').removeClass('has-error');
|
||||
$('#user-profile-wrapper .form_field .help-block > p').remove();
|
||||
|
||||
// Submiting contact form through AJAX
|
||||
$('#{{ oContactForm.id }}').portal_form_handler('submit', oEvent);
|
||||
|
||||
// Submiting preferences form through AJAX
|
||||
$('#{{ oPreferencesForm.id }}').portal_form_handler('submit', oEvent);
|
||||
|
||||
{% if oPasswordForm is not null %}
|
||||
// Submiting password form through AJAX
|
||||
// Only if fields are filled
|
||||
$('#{{ oPasswordForm.id }} :password').each(function(iIndex, oElem){
|
||||
if($(oElem).val() !== '')
|
||||
{
|
||||
$('#{{ oPasswordForm.id }}').portal_form_handler('submit', oEvent);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
{% endblock %}
|
||||
{% block pStyleinline %}
|
||||
{{ parent() }}
|
||||
<style>
|
||||
{% import "itop-portal-base/portal/templates/helpers/macros.twig" as Macro %}
|
||||
{{ Macro.BlockExtension(aPluginFormData, 'css', oBrick) }}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
<div id="user-profile-wrapper">
|
||||
{% block pUserProfileWrapper %}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:PersonalInformations:Title'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form id="{{ oContactForm.id }}" class="" method="POST" action="{{ oContactForm.renderer.GetEndpoint()|raw }}">
|
||||
<input type="hidden" name="transaction_id" value="{{ oContactForm.transaction_id }}" />
|
||||
<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>
|
||||
<div class="form_fields">
|
||||
{{ oContactForm.renderer.GetBaseLayout()|raw }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
{% if oBrick.GetShowPictureForm() %}
|
||||
{% block pUserProfilePictureFormContainer %}
|
||||
<div class="panel panel-default user_profile_picture">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:Photo:Title'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body" style="position: relative;">
|
||||
<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">
|
||||
<span type="button" class="btn btn-default btn_edit">
|
||||
<span class="fas fa-pencil-alt fa-fw"></span>
|
||||
<input id="picture" type="file" name="picture" />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if oBrick.GetShowPreferencesForm() %}
|
||||
{% block pUserProfilePreferencesFormContainer %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Class:appUserPreferences/Attribute:preferences'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form id="{{ oPreferencesForm.id }}" class="" method="POST" action="{{ oPreferencesForm.renderer.GetEndpoint()|raw }}">
|
||||
<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>
|
||||
<div class="form_fields">
|
||||
{{ oPreferencesForm.renderer.GetBaseLayout()|raw }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
|
||||
{% if oBrick.GetShowPasswordForm() %}
|
||||
{% block pUserProfilePasswordFormContainer %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ 'Brick:Portal:UserProfile:Password:Title'|dict_s }}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% if oPasswordForm is not null %}
|
||||
<form id="{{ oPasswordForm.id }}" class="" method="POST" action="{{ oPasswordForm.renderer.GetEndpoint()|raw }}" autocomplete="off">
|
||||
<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>
|
||||
<div class="form_fields">
|
||||
{{ oPasswordForm.renderer.GetBaseLayout()|raw }}
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
{{ 'Brick:Portal:UserProfile:Password:CantChangeContactAdministrator'|dict_format(constant('ITOP_APPLICATION_SHORT')) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form_buttons">
|
||||
{% block pUserProfileFormButtons %}
|
||||
<div class="form_btn_regular">
|
||||
{% if sFormMode == constant('\\Combodo\\iTop\\Portal\\Helper\\ObjectFormHandlerHelper::ENUM_MODE_EDIT') %}
|
||||
<input class="btn btn-primary form_btn_submit" type="submit" value="{{ 'Portal:Button:Submit'|dict_s }}">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
@@ -0,0 +1,100 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
// Personal informations form
|
||||
var oContactFormFieldSet = $('#{{ oContactForm.id }} > .form_fields').field_set({{ oContactForm.fieldset|json_encode()|raw }});
|
||||
$('#{{ oContactForm.id }}').portal_form_handler({
|
||||
formmanager_class: "{{ oContactForm.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ oContactForm.formmanager_data|json_encode()|raw }},
|
||||
field_set: oContactFormFieldSet,
|
||||
endpoint: "{{ oContactForm.renderer.GetEndpoint()|raw }}"
|
||||
});
|
||||
|
||||
// Preferences form
|
||||
var oPreferencesFormFieldSet = $('#{{ oPreferencesForm.id }} > .form_fields').field_set({{ oPreferencesForm.fieldset|json_encode()|raw }});
|
||||
$('#{{ oPreferencesForm.id }}').portal_form_handler({
|
||||
formmanager_class: "{{ oPreferencesForm.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ oPreferencesForm.formmanager_data|json_encode()|raw }},
|
||||
field_set: oPreferencesFormFieldSet,
|
||||
endpoint: "{{ oPreferencesForm.renderer.GetEndpoint()|raw }}"
|
||||
});
|
||||
|
||||
{% if oPasswordForm is not null %}
|
||||
// Password form
|
||||
var oPasswordFormFieldSet = $('#{{ oPasswordForm.id }} > .form_fields').field_set({{ oPasswordForm.fieldset|json_encode()|raw }});
|
||||
$('#{{ oPasswordForm.id }}').portal_form_handler({
|
||||
formmanager_class: "{{ oPasswordForm.formmanager_class|escape('js') }}",
|
||||
formmanager_data: {{ oPasswordForm.formmanager_data|json_encode()|raw }},
|
||||
field_set: oPasswordFormFieldSet,
|
||||
endpoint: "{{ oPasswordForm.renderer.GetEndpoint()|raw }}"
|
||||
});
|
||||
{% 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();
|
||||
|
||||
// Resetting feedback
|
||||
$('#user-profile-wrapper .form_alerts .alert').hide();
|
||||
$('#user-profile-wrapper .form_alerts .alert > p').remove();
|
||||
$('#user-profile-wrapper .form_field').removeClass('has-error');
|
||||
$('#user-profile-wrapper .form_field .help-block > p').remove();
|
||||
|
||||
// Submiting contact form through AJAX
|
||||
$('#{{ oContactForm.id }}').portal_form_handler('submit', oEvent);
|
||||
|
||||
// Submiting preferences form through AJAX
|
||||
$('#{{ oPreferencesForm.id }}').portal_form_handler('submit', oEvent);
|
||||
|
||||
{% if oPasswordForm is not null %}
|
||||
// Submiting password form through AJAX
|
||||
// Only if fields are filled
|
||||
$('#{{ oPasswordForm.id }} :password').each(function(iIndex, oElem){
|
||||
if($(oElem).val() !== '')
|
||||
{
|
||||
$('#{{ oPasswordForm.id }}').portal_form_handler('submit', oEvent);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
{# @copyright Copyright (C) 2010-2024 Combodo SAS #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
|
||||
{% macro BlockExtension(aPluginFormData, sBlockName, oBrick) %}
|
||||
{% for oPortalData in aPluginFormData %}
|
||||
{% if (oPortalData is defined and oPortalData.GetBlockExtension(sBlockName)) %}
|
||||
{% set oBlockExtension = oPortalData.GetBlockExtension(sBlockName) %}
|
||||
{% set sTwig = oBlockExtension.GetTwig() %}
|
||||
{% set aData = oBlockExtension.GetData() %}
|
||||
{% include sTwig ignore missing %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
@@ -78,9 +78,9 @@
|
||||
{% block pStyleinline %}
|
||||
{# UI Extensions inline CSS #}
|
||||
{% if app['ui_extensions_helper'].css_inline is not null %}
|
||||
<style>
|
||||
{{ app['ui_extensions_helper'].css_inline|raw }}
|
||||
</style>
|
||||
<style>
|
||||
{{ app['ui_extensions_helper'].css_inline|raw }}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user