This commit is contained in:
Xes
2025-08-14 22:41:49 +02:00
parent 2de81ccc46
commit 8ce45119b6
39774 changed files with 4309466 additions and 0 deletions

View File

@@ -0,0 +1,423 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{#
This code manages the many-to-[one|many] association field popup
#}
{% autoescape false %}
{% set associationadmin = sonata_admin.field_description.associationadmin %}
<!-- edit many association -->
<script type="text/javascript">
{#
handle link click in a list :
- if the parent has an objectId defined then the related input get updated
- if the parent has NO object then an ajax request is made to refresh the popup
#}
var field_dialog_form_list_link_{{ id }} = function(event) {
initialize_popup_{{ id }}();
var target = jQuery(this);
if (target.attr('href').length === 0 || target.attr('href') === '#') {
return;
}
event.preventDefault();
event.stopPropagation();
Admin.log('[{{ id }}|field_dialog_form_list_link] handle link click in a list');
var element = jQuery(this).parents('#field_dialog_{{ id }} .sonata-ba-list-field');
// the user does not click on a row column
if (element.length == 0) {
Admin.log('[{{ id }}|field_dialog_form_list_link] the user does not click on a row column, make ajax call to retrieve inner html');
// make a recursive call (ie: reset the filter)
jQuery.ajax({
type: 'GET',
url: jQuery(this).attr('href'),
dataType: 'html',
success: function(html) {
Admin.log('[{{ id }}|field_dialog_form_list_link] callback success, attach valid js event');
field_dialog_content_{{ id }}.html(html);
field_dialog_form_list_handle_action_{{ id }}();
Admin.shared_setup(field_dialog_{{ id }});
}
});
return;
}
Admin.log('[{{ id }}|field_dialog_form_list_link] the user select one element, update input and hide the modal');
jQuery('#{{ id }}').val(element.attr('objectId'));
jQuery('#{{ id }}').trigger('change');
field_dialog_{{ id }}.modal('hide');
};
// this function handle action on the modal list when inside a selected list
var field_dialog_form_list_handle_action_{{ id }} = function() {
Admin.log('[{{ id }}|field_dialog_form_list_handle_action] attaching valid js event');
// capture the submit event to make an ajax call, ie : POST data to the
// related create admin
jQuery('a', field_dialog_{{ id }}).on('click', field_dialog_form_list_link_{{ id }});
jQuery('form', field_dialog_{{ id }}).on('submit', function(event) {
event.preventDefault();
var form = jQuery(this);
Admin.log('[{{ id }}|field_dialog_form_list_handle_action] catching submit event, sending ajax request');
jQuery(form).ajaxSubmit({
type: form.attr('method'),
url: form.attr('action'),
dataType: 'html',
data: {_xml_http_request: true},
success: function(html) {
Admin.log('[{{ id }}|field_dialog_form_list_handle_action] form submit success, restoring event');
field_dialog_content_{{ id }}.html(html);
field_dialog_form_list_handle_action_{{ id }}();
Admin.shared_setup(field_dialog_{{ id }});
}
});
});
};
// handle the list link
var field_dialog_form_list_{{ id }} = function(event) {
initialize_popup_{{ id }}();
event.preventDefault();
event.stopPropagation();
Admin.log('[{{ id }}|field_dialog_form_list] open the list modal');
var a = jQuery(this);
field_dialog_content_{{ id }}.html('');
// retrieve the form element from the related admin generator
jQuery.ajax({
url: a.attr('href'),
dataType: 'html',
success: function(html) {
Admin.log('[{{ id }}|field_dialog_form_list] retrieving the list content');
// populate the popup container
field_dialog_content_{{ id }}.html(html);
field_dialog_title_{{ id }}.html("{{ associationadmin.label|trans({}, associationadmin.translationdomain) }}");
Admin.shared_setup(field_dialog_{{ id }});
field_dialog_form_list_handle_action_{{ id }}();
// open the dialog in modal mode
field_dialog_{{ id }}.modal();
Admin.setup_list_modal(field_dialog_{{ id }});
}
});
};
// handle the add link
var field_dialog_form_add_{{ id }} = function(event) {
initialize_popup_{{ id }}();
event.preventDefault();
event.stopPropagation();
var a = jQuery(this);
field_dialog_content_{{ id }}.html('');
Admin.log('[{{ id }}|field_dialog_form_add] add link action');
// retrieve the form element from the related admin generator
jQuery.ajax({
url: a.attr('href'),
dataType: 'html',
success: function(html) {
Admin.log('[{{ id }}|field_dialog_form_add] ajax success', field_dialog_{{ id }});
// populate the popup container
field_dialog_content_{{ id }}.html(html);
field_dialog_title_{{ id }}.html("{{ associationadmin.label|trans({}, associationadmin.translationdomain) }}");
Admin.shared_setup(field_dialog_{{ id }});
// capture the submit event to make an ajax call, ie : POST data to the
// related create admin
jQuery('a', field_dialog_{{ id }}).on('click', field_dialog_form_action_{{ id }});
jQuery('form', field_dialog_{{ id }}).on('submit', field_dialog_form_action_{{ id }});
// open the dialog in modal mode
field_dialog_{{ id }}.modal();
Admin.setup_list_modal(field_dialog_{{ id }});
}
});
};
// handle the post data
var field_dialog_form_action_{{ id }} = function(event) {
var element = jQuery(this);
// return if the link is an anchor inside the same page
if (
this.nodeName === 'A'
&& (
element.attr('href').length === 0
|| element.attr('href')[0] === '#'
|| element.attr('href').substr(0, 11) === 'javascript:'
)
) {
Admin.log('[{{ id }}|field_dialog_form_action] element is an anchor or a script, skipping action', this);
return;
}
event.preventDefault();
event.stopPropagation();
Admin.log('[{{ id }}|field_dialog_form_action] action catch', this);
initialize_popup_{{ id }}();
if (this.nodeName == 'FORM') {
var url = element.attr('action');
var type = element.attr('method');
} else if (this.nodeName == 'A') {
var url = element.attr('href');
var type = 'GET';
} else {
alert('unexpected element : @' + this.nodeName + '@');
return;
}
if (element.hasClass('sonata-ba-action')) {
Admin.log('[{{ id }}|field_dialog_form_action] reserved action stop catch all events');
return;
}
var data = {
_xml_http_request: true
}
var form = jQuery(this);
Admin.log('[{{ id }}|field_dialog_form_action] execute ajax call');
// the ajax post
jQuery(form).ajaxSubmit({
url: url,
type: type,
data: data,
success: function(data) {
Admin.log('[{{ id }}|field_dialog_form_action] ajax success');
// if the crud action return ok, then the element has been added
// so the widget container must be refresh with the last option available
if (typeof data != 'string' && data.result == 'ok') {
field_dialog_{{ id }}.modal('hide');
{% if sonata_admin.edit == 'list' %}
{#
in this case we update the hidden input, and call the change event to
retrieve the post information
#}
jQuery('#{{ id }}').val(data.objectId);
jQuery('#{{ id }}').change();
{% else %}
// reload the form element
jQuery('#field_widget_{{ id }}').closest('form').ajaxSubmit({
url: '{{ path('sonata_admin_retrieve_form_element', {
'elementId': id,
'subclass': sonata_admin.admin.getActiveSubclassCode(),
'objectId': sonata_admin.admin.root.id(sonata_admin.admin.root.subject),
'uniqid': sonata_admin.admin.root.uniqid,
'code': sonata_admin.admin.root.code
}) }}',
data: {_xml_http_request: true },
dataType: 'html',
type: 'POST',
success: function(html) {
jQuery('#field_container_{{ id }}').replaceWith(html);
var newElement = jQuery('#{{ id }} [value="' + data.objectId + '"]');
if (newElement.is("input")) {
newElement.attr('checked', 'checked');
} else {
newElement.attr('selected', 'selected');
}
jQuery('#field_container_{{ id }}').trigger('sonata-admin-append-form-element');
}
});
{% endif %}
return;
}
// otherwise, display form error
field_dialog_content_{{ id }}.html(data);
Admin.shared_setup(field_dialog_{{ id }});
// reattach the event
jQuery('form', field_dialog_{{ id }}).submit(field_dialog_form_action_{{ id }});
}
});
return false;
};
var field_dialog_{{ id }} = false;
var field_dialog_content_{{ id }} = false;
var field_dialog_title_{{ id }} = false;
function initialize_popup_{{ id }}() {
// initialize component
if (!field_dialog_{{ id }}) {
field_dialog_{{ id }} = jQuery("#field_dialog_{{ id }}");
field_dialog_content_{{ id }} = jQuery(".modal-body", "#field_dialog_{{ id }}");
field_dialog_title_{{ id }} = jQuery(".modal-title", "#field_dialog_{{ id }}");
// move the dialog as a child of the root element, nested form breaks html ...
jQuery(document.body).append(field_dialog_{{ id }});
Admin.log('[{{ id }}|field_dialog] move dialog container as a document child');
}
}
{#
This code is used to defined the "add" popup
#}
// this function initializes the popup
// this can be only done this way as popup can be cascaded
function start_field_dialog_form_add_{{ id }}(link) {
// remove the html event
link.onclick = null;
initialize_popup_{{ id }}();
// add the jQuery event to the a element
jQuery(link)
.click(field_dialog_form_add_{{ id }})
.trigger('click')
;
return false;
}
if (field_dialog_{{ id }}) {
Admin.shared_setup(field_dialog_{{ id }});
}
{% if sonata_admin.edit == 'list' %}
{#
This code is used to defined the "list" popup
#}
// this function initializes the popup
// this can be only done this way as popup can be cascaded
function start_field_dialog_form_list_{{ id }}(link) {
link.onclick = null;
initialize_popup_{{ id }}();
// add the jQuery event to the a element
jQuery(link)
.click(field_dialog_form_list_{{ id }})
.trigger('click')
;
return false;
}
function remove_selected_element_{{ id }}(link) {
link.onclick = null;
jQuery(link)
.click(field_remove_element_{{ id}})
.trigger('click')
;
return false;
}
function field_remove_element_{{ id }}(event) {
event.preventDefault();
if (jQuery('#{{ id }} option').get(0)) {
jQuery('#{{ id }}').attr('selectedIndex', '-1').children("option:selected").attr("selected", false);
}
jQuery('#{{ id }}').val('');
jQuery('#{{ id }}').trigger('change');
return false;
}
{#
attach onchange event on the input
#}
// update the label
jQuery('#{{ id }}').on('change', function(event) {
Admin.log('[{{ id }}|on:change] update the label');
jQuery('#field_widget_{{ id }}').html("<span><img src=\"{{ asset('bundles/sonataadmin/ajax-loader.gif') }}\" style=\"vertical-align: middle; margin-right: 10px\"/>{{ 'loading_information'|trans([], 'SonataAdminBundle') }}</span>");
jQuery.ajax({
type: 'GET',
url: '{{ path('sonata_admin_short_object_information', {
'objectId': 'OBJECT_ID',
'uniqid': associationadmin.uniqid,
'code': associationadmin.code,
'linkParameters': sonata_admin.field_description.options.link_parameters
})}}'.replace('OBJECT_ID', jQuery(this).val()),
dataType: 'html',
success: function(html) {
jQuery('#field_widget_{{ id }}').html(html);
}
});
});
{% endif %}
</script>
<!-- / edit many association -->
{% endautoescape %}

View File

@@ -0,0 +1,127 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% if sonata_admin.field_description.hasassociationadmin %}
<div id="field_container_{{ id }}" class="field-container">
<span id="field_widget_{{ id }}" >
{% if sonata_admin.edit == 'inline' %}
{% if sonata_admin.inline == 'table' %}
{% if form.children|length > 0 %}
<table class="table table-bordered">
<thead>
<tr>
{% for field_name, nested_field in form.children[0].children %}
{% if field_name == '_delete' %}
<th>{{ 'action_delete'|trans({}, 'SonataAdminBundle') }}</th>
{% else %}
<th {{ nested_field.vars['required'] ? 'class="required"' : '' }}>
{{ nested_field.vars['sonata_admin'].admin.trans(nested_field.vars.label) }}
</th>
{% endif %}
{% endfor %}
</tr>
</thead>
<tbody class="sonata-ba-tbody">
{% for nested_group_field_name, nested_group_field in form.children %}
<tr>
{% for field_name, nested_field in nested_group_field.children %}
<td class="sonata-ba-td-{{ id }}-{{ field_name }} control-group{% if nested_field.vars.errors|length > 0 %} error sonata-ba-field-error{% endif %}">
{% if sonata_admin.field_description.associationadmin.hasformfielddescriptions(field_name) is defined %}
{{ form_widget(nested_field) }}
{% set dummy = nested_group_field.setrendered %}
{% else %}
{{ form_widget(nested_field) }}
{% endif %}
{% if nested_field.vars.errors|length > 0 %}
<div class="help-inline sonata-ba-field-error-messages">
{{ form_errors(nested_field) }}
</div>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% elseif form.children|length > 0 %}
<div>
{% for nested_group_field_name, nested_group_field in form.children %}
{% for field_name, nested_field in nested_group_field.children %}
{% if sonata_admin.field_description.associationadmin.hasformfielddescriptions(field_name) is defined %}
{{ form_row(nested_field, {
'inline': 'natural',
'edit' : 'inline'
}) }}
{% set dummy = nested_group_field.setrendered %}
{% else %}
{% if nested_field.vars.name == '_delete' %}
{{ form_row(nested_field, { 'label': ('action_delete'|trans({}, 'SonataAdminBundle')) }) }}
{% else %}
{{ form_row(nested_field) }}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endif %}
{% else %}
{{ form_widget(form) }}
{% endif %}
</span>
{% if sonata_admin.edit == 'inline' %}
{% if sonata_admin.field_description.associationadmin.hasroute('create') and sonata_admin.field_description.associationadmin.isGranted('CREATE') and btn_add %}
<span id="field_actions_{{ id }}" >
<a
href="{{ sonata_admin.field_description.associationadmin.generateUrl('create', sonata_admin.field_description.getOption('link_parameters', {})) }}"
onclick="return start_field_retrieve_{{ id }}(this);"
class="btn btn-success btn-sm sonata-ba-action"
title="{{ btn_add|trans({}, btn_catalogue) }}"
>
<i class="fa fa-plus-circle"></i>
{{ btn_add|trans({}, btn_catalogue) }}
</a>
</span>
{% endif %}
{# include association code #}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_script.html.twig' %}
{% else %}
<div id="field_container_{{ id }}" class="field-container">
<span id="field_widget_{{ id }}" >
{{ form_widget(form) }}
</span>
<span id="field_actions_{{ id }}" class="field-actions">
{% if sonata_admin.field_description.associationadmin.hasRoute('create') and sonata_admin.field_description.associationadmin.isGranted('CREATE') and btn_add %}
<a
href="{{ sonata_admin.field_description.associationadmin.generateUrl('create', sonata_admin.field_description.getOption('link_parameters', {})) }}"
onclick="return start_field_dialog_form_add_{{ id }}(this);"
class="btn btn-success btn-sm sonata-ba-action"
title="{{ btn_add|trans({}, btn_catalogue) }}"
>
<i class="fa fa-plus-circle"></i>
{{ btn_add|trans({}, btn_catalogue) }}
</a>
{% endif %}
</span>
{% include 'SonataAdminBundle:CRUD/Association:edit_modal.html.twig' %}
</div>
{% include 'SonataAdminBundle:CRUD/Association:edit_many_script.html.twig' %}
{% endif %}
</div>
{% endif %}

View File

@@ -0,0 +1,89 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% if not sonata_admin.field_description.hasassociationadmin%}
{{ value|render_relation_element(sonata_admin.field_description) }}
{% elseif sonata_admin.edit == 'inline' %}
{% for field_description in sonata_admin.field_description.associationadmin.formfielddescriptions %}
{{ form_row(form[field_description.name])}}
{% endfor %}
{% else %}
<div id="field_container_{{ id }}" class="field-container">
{% if sonata_admin.edit == 'list' %}
<span id="field_widget_{{ id }}" class="field-short-description">
{% if sonata_admin.admin.id(sonata_admin.value) %}
{{ render(path('sonata_admin_short_object_information', {
'code': sonata_admin.field_description.associationadmin.code,
'objectId': sonata_admin.field_description.associationadmin.id(sonata_admin.value),
'uniqid': sonata_admin.field_description.associationadmin.uniqid,
'linkParameters': sonata_admin.field_description.options.link_parameters
})) }}
{% elseif sonata_admin.field_description.options.placeholder is defined and sonata_admin.field_description.options.placeholder %}
<span class="inner-field-short-description">
{{ sonata_admin.field_description.options.placeholder|trans({}, 'SonataAdminBundle') }}
</span>
{% endif %}
</span>
<span style="display: none" >
{{ form_widget(form) }}
</span>
{% else %}
<span id="field_widget_{{ id }}" >
{{ form_widget(form) }}
</span>
{% endif %}
<div id="field_actions_{{ id }}" class="field-actions">
{% set display_btn_list = sonata_admin.edit == 'list' and sonata_admin.field_description.associationadmin.hasRoute('list') and sonata_admin.field_description.associationadmin.isGranted('LIST') and btn_list %}
{% set display_btn_add = sonata_admin.edit != 'admin' and sonata_admin.field_description.associationadmin.hasRoute('create') and sonata_admin.field_description.associationadmin.isGranted('CREATE') and btn_add %}
{% if display_btn_list or display_btn_add %}
<div class="btn-group">
{% if display_btn_list %}
<a href="{{ sonata_admin.field_description.associationadmin.generateUrl('list', sonata_admin.field_description.getOption('link_parameters', {})) }}"
onclick="return start_field_dialog_form_list_{{ id }}(this);"
class="btn btn-info btn-sm sonata-ba-action"
title="{{ btn_list|trans({}, btn_catalogue) }}"
>
<i class="fa fa-list"></i>
{{ btn_list|trans({}, btn_catalogue) }}
</a>
{% endif %}
{% if display_btn_add %}
<a href="{{ sonata_admin.field_description.associationadmin.generateUrl('create', sonata_admin.field_description.getOption('link_parameters', {})) }}"
onclick="return start_field_dialog_form_add_{{ id }}(this);"
class="btn btn-success btn-sm sonata-ba-action"
title="{{ btn_add|trans({}, btn_catalogue) }}"
>
<i class="fa fa-plus-circle"></i>
{{ btn_add|trans({}, btn_catalogue) }}
</a>
{% endif %}
</div>
{% endif %}
{% if sonata_admin.edit == 'list' and sonata_admin.field_description.associationadmin.hasRoute('delete') and sonata_admin.field_description.associationadmin.isGranted('DELETE') and btn_delete %}
<a href=""
onclick="return remove_selected_element_{{ id }}(this);"
class="btn btn-danger btn-sm sonata-ba-action"
title="{{ btn_delete|trans({}, btn_catalogue) }}"
>
<i class="fa fa-minus-circle"></i>
{{ btn_delete|trans({}, btn_catalogue) }}
</a>
{% endif %}
</div>
{% include 'SonataAdminBundle:CRUD/Association:edit_modal.html.twig' %}
</div>
{% include 'SonataAdminBundle:CRUD/Association:edit_many_script.html.twig' %}
{% endif %}

View File

@@ -0,0 +1,23 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
<div class="modal fade" id="field_dialog_{{ id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title"></h4>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,89 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{#
This code manages the one-to-many association field popup
#}
{% autoescape false %}
<!-- edit one association -->
<script type="text/javascript">
// handle the add link
var field_add_{{ id }} = function(event) {
event.preventDefault();
event.stopPropagation();
var form = jQuery(this).closest('form');
// the ajax post
jQuery(form).ajaxSubmit({
url: '{{ path('sonata_admin_append_form_element', {
'code': sonata_admin.admin.root.code,
'elementId': id,
'objectId': sonata_admin.admin.root.id(sonata_admin.admin.root.subject),
'uniqid': sonata_admin.admin.root.uniqid,
'subclass': app.request.query.get('subclass'),
} + sonata_admin.field_description.getOption('link_parameters', {})) }}',
type: "POST",
dataType: 'html',
data: { _xml_http_request: true },
success: function(html) {
if (!html.length) {
return;
}
jQuery('#field_container_{{ id }}').replaceWith(html); // replace the html
Admin.shared_setup(jQuery('#field_container_{{ id }}'));
if(jQuery('input[type="file"]', form).length > 0) {
jQuery(form).attr('enctype', 'multipart/form-data');
jQuery(form).attr('encoding', 'multipart/form-data');
}
jQuery('#sonata-ba-field-container-{{ id }}').trigger('sonata.add_element');
jQuery('#field_container_{{ id }}').trigger('sonata.add_element');
}
});
return false;
};
var field_widget_{{ id }} = false;
// this function initializes the popup
// this can be only done this way as popup can be cascaded
function start_field_retrieve_{{ id }}(link) {
link.onclick = null;
// initialize component
field_widget_{{ id }} = jQuery("#field_widget_{{ id }}");
// add the jQuery event to the a element
jQuery(link)
.click(field_add_{{ id }})
.trigger('click')
;
return false;
}
</script>
<!-- / edit one association -->
{% endautoescape %}

View File

@@ -0,0 +1,97 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% if not sonata_admin.field_description.hasassociationadmin %}
{% for element in value %}
{{ element|render_relation_element(sonata_admin.field_description) }}
{% endfor %}
{% else %}
<div id="field_container_{{ id }}" class="field-container">
<span id="field_widget_{{ id }}" >
{% if sonata_admin.edit == 'inline' %}
{% if sonata_admin.inline == 'table' %}
{% if form.children|length > 0 %}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_to_many_inline_table.html.twig' %}
{% endif %}
{% elseif form.children|length > 0 %}
{% set associationAdmin = sonata_admin.field_description.associationadmin %}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_to_many_inline_tabs.html.twig' %}
{% endif %}
{% else %}
{{ form_widget(form) }}
{% endif %}
</span>
{% set display_create_button = sonata_admin.field_description.associationadmin.hasroute('create')
and sonata_admin.field_description.associationadmin.isGranted('CREATE')
and btn_add
and (
sonata_admin.field_description.options.limit is not defined or
form.children|length < sonata_admin.field_description.options.limit
) %}
{% if sonata_admin.edit == 'inline' %}
{% if display_create_button %}
<span id="field_actions_{{ id }}" >
<a
href="{{ sonata_admin.field_description.associationadmin.generateUrl(
'create',
sonata_admin.field_description.getOption('link_parameters', {})
) }}"
onclick="return start_field_retrieve_{{ id }}(this);"
class="btn btn-success btn-sm sonata-ba-action"
title="{{ btn_add|trans({}, btn_catalogue) }}"
>
<i class="fa fa-plus-circle"></i>
{{ btn_add|trans({}, btn_catalogue) }}
</a>
</span>
{% endif %}
{# add code for the sortable options #}
{% if sonata_admin.field_description.options.sortable is defined %}
{% if sonata_admin.inline == 'table' %}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_to_many_sortable_script_table.html.twig' %}
{% else %}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_to_many_sortable_script_tabs.html.twig' %}
{% endif %}
{% endif %}
{# include association code #}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_script.html.twig' %}
{% else %}
<span id="field_actions_{{ id }}" >
{% if display_create_button %}
<a
href="{{ sonata_admin.field_description.associationadmin.generateUrl(
'create',
sonata_admin.field_description.getOption('link_parameters', {})
) }}"
onclick="return start_field_dialog_form_add_{{ id }}(this);"
class="btn btn-success btn-sm sonata-ba-action"
title="{{ btn_add|trans({}, btn_catalogue) }}"
>
<i class="fa fa-plus-circle"></i>
{{ btn_add|trans({}, btn_catalogue) }}
</a>
{% endif %}
</span>
{% include 'SonataAdminBundle:CRUD/Association:edit_modal.html.twig' %}
{% include 'SonataAdminBundle:CRUD/Association:edit_one_script.html.twig' %}
{% endif %}
</div>
{% endif %}

View File

@@ -0,0 +1,68 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
<table class="table table-bordered">
<thead>
<tr>
{% for field_name, nested_field in form.children|first.children %}
{% if field_name == '_delete' %}
<th>{{ 'action_delete'|trans({}, 'SonataAdminBundle') }}</th>
{% else %}
<th
{% if nested_field.vars['required'] %}
class="required"
{% endif %}
{% if (nested_field.vars['attr']['hidden'] is defined) and (nested_field.vars['attr']['hidden']) %}
style="display:none;"
{% endif %}
>
{{ nested_field.vars.label|trans({}, nested_field.vars['sonata_admin'].admin.translationDomain
|default(nested_field.vars.translation_domain)
) }}
</th>
{% endif %}
{% endfor %}
</tr>
</thead>
<tbody class="sonata-ba-tbody">
{% for nested_group_field_name, nested_group_field in form.children %}
<tr>
{% for field_name, nested_field in nested_group_field.children %}
<td class="
sonata-ba-td-{{ id }}-{{ field_name }}
control-group
{% if nested_field.vars.errors|length > 0 %} error sonata-ba-field-error{% endif %}
"
{% if (nested_field.vars['attr']['hidden'] is defined) and (nested_field.vars['attr']['hidden']) %}
style="display:none;"
{% endif %}
>
{% if sonata_admin.field_description.associationadmin.formfielddescriptions[field_name] is defined %}
{{ form_widget(nested_field) }}
{% set dummy = nested_group_field.setrendered %}
{% else %}
{% if field_name == '_delete' %}
{{ form_widget(nested_field, { label: false }) }}
{% else %}
{{ form_widget(nested_field) }}
{% endif %}
{% endif %}
{% if nested_field.vars.errors|length > 0 %}
<div class="help-inline sonata-ba-field-error-messages">
{{ form_errors(nested_field) }}
</div>
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>

View File

@@ -0,0 +1,63 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
<div class="sonata-ba-tabs">
{% for nested_group_field in form.children %}
<div>
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
{% for name, form_group in associationAdmin.formgroups %}
<li class="{% if loop.first %}active{% endif %}">
<a
href="#{{ associationAdmin.uniqid }}_{{ loop.parent.loop.index }}_{{ loop.index }}"
data-toggle="tab"
>
<i class="icon-exclamation-sign has-errors hide"></i>
{{ associationAdmin.trans(name, {}, form_group.translation_domain) }}
</a>
</li>
{% endfor %}
</ul>
<div class="tab-content">
{% for name, form_group in associationAdmin.formgroups %}
<div
class="tab-pane {% if loop.first %}active{% endif %}"
id="{{ associationAdmin.uniqid }}_{{ loop.parent.loop.index }}_{{ loop.index }}"
>
<fieldset>
<div class="sonata-ba-collapsed-fields">
{% for field_name in form_group.fields %}
{% set nested_field = nested_group_field.children[field_name] %}
<div class="sonata-ba-field-{{ id }}-{{ field_name }}">
{% if associationAdmin.formfielddescriptions[field_name] is defined %}
{{ form_row(nested_field, {
'inline': 'natural',
'edit' : 'inline'
}) }}
{% set dummy = nested_group_field.setrendered %}
{% else %}
{{ form_row(nested_field) }}
{% endif %}
</div>
{% endfor %}
</div>
</fieldset>
</div>
{% endfor %}
</div>
</div>
{% if nested_group_field['_delete'] is defined %}
{{ form_row(nested_group_field['_delete'], {'label': 'action_delete', 'translation_domain': 'SonataAdminBundle'}) }}
{% endif %}
</div>
{% endfor %}
</div>

View File

@@ -0,0 +1,40 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
<script type="text/javascript">
jQuery('div#field_container_{{ id }} tbody.sonata-ba-tbody').first().sortable({
axis: 'y',
opacity: 0.6,
items: '> tr',
stop: apply_position_value_{{ id }}
});
function apply_position_value_{{ id }}() {
// update the input value position
jQuery('div#field_container_{{ id }} tbody.sonata-ba-tbody td.sonata-ba-td-{{ id }}-{{ sonata_admin.field_description.options.sortable }}').each(function(index, element) {
// remove the sortable handler and put it back
jQuery('span.sonata-ba-sortable-handler', element).remove();
jQuery(element).append('<span class="sonata-ba-sortable-handler ui-icon ui-icon-grip-solid-horizontal"></span>');
jQuery('input', element).hide();
});
jQuery('div#field_container_{{ id }} tbody.sonata-ba-tbody td.sonata-ba-td-{{ id }}-{{ sonata_admin.field_description.options.sortable }} input').each(function(index, value) {
jQuery(value).val(index + 1);
});
}
// refresh the sortable option when a new element is added
jQuery('#sonata-ba-field-container-{{ id }}').bind('sonata.add_element', function() {
apply_position_value_{{ id }}();
jQuery('div#field_container_{{ id }} tbody.sonata-ba-tbody').sortable('refresh');
});
apply_position_value_{{ id }}();
</script>

View File

@@ -0,0 +1,44 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
<script type="text/javascript">
jQuery('div#field_container_{{ id }} .sonata-ba-tabs').sortable({
axis: 'y',
opacity: 0.6,
items: '> div',
stop: apply_position_value_{{ id }}
});
function apply_position_value_{{ id }}() {
// update the input value position
jQuery('div#field_container_{{ id }} .sonata-ba-tabs .sonata-ba-field-{{ id }}-{{ sonata_admin.field_description.options.sortable }}').each(function(index, element) {
// remove the sortable handler and put it back
var parent = jQuery(element).closest('.nav-tabs-custom');
var tabs = parent.find('> .nav-tabs');
jQuery('.sonata-ba-sortable-handler', tabs).remove();
$('<li class="sonata-ba-sortable-handler pull-right"></li>')
.prepend('<span class="ui-icon ui-icon-grip-solid-horizontal"></span>')
.appendTo(tabs);
jQuery('input', element).hide();
});
jQuery('div#field_container_{{ id }} .sonata-ba-tabs .sonata-ba-field-{{ id }}-{{ sonata_admin.field_description.options.sortable }} input').each(function(index, value) {
jQuery(value).val(index + 1);
});
}
// refresh the sortable option when a new element is added
jQuery('#sonata-ba-field-container-{{ id }}').bind('sonata.add_element', function() {
apply_position_value_{{ id }}();
jQuery('div#field_container_{{ id }} .sonata-ba-tabs').sortable('refresh');
});
apply_position_value_{{ id }}();
</script>

View File

@@ -0,0 +1,89 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% if not sonata_admin.field_description.hasassociationadmin%}
{{ value|render_relation_element(sonata_admin.field_description) }}
{% elseif sonata_admin.edit == 'inline' %}
{% for field_description in sonata_admin.field_description.associationadmin.formfielddescriptions %}
{{ form_row(form.children[field_description.name]) }}
{% endfor %}
{% else %}
<div id="field_container_{{ id }}" class="field-container">
{% if sonata_admin.edit == 'list' %}
<span id="field_widget_{{ id }}" class="field-short-description">
{% if sonata_admin.field_description.associationadmin.id(sonata_admin.value) %}
{{ render(path('sonata_admin_short_object_information', {
'code': sonata_admin.field_description.associationadmin.code,
'objectId': sonata_admin.field_description.associationadmin.id(sonata_admin.value),
'uniqid': sonata_admin.field_description.associationadmin.uniqid,
'linkParameters': sonata_admin.field_description.options.link_parameters
})) }}
{% elseif sonata_admin.field_description.options.placeholder is defined and sonata_admin.field_description.options.placeholder %}
<span class="inner-field-short-description">
{{ sonata_admin.field_description.options.placeholder|trans({}, 'SonataAdminBundle') }}
</span>
{% endif %}
</span>
<span style="display: none" >
{{ form_widget(form) }}
</span>
{% else %}
<span id="field_widget_{{ id }}" >
{{ form_widget(form) }}
</span>
{% endif %}
<div id="field_actions_{{ id }}" class="field-actions">
{% set display_btn_list = sonata_admin.edit == 'list' and sonata_admin.field_description.associationadmin.hasroute('list') and sonata_admin.field_description.associationadmin.isGranted('LIST') and btn_list %}
{% set display_btn_add = sonata_admin.edit != 'admin' and sonata_admin.field_description.associationadmin.hasroute('create') and sonata_admin.field_description.associationadmin.isGranted('CREATE') and btn_add %}
{% if display_btn_list or display_btn_add %}
<div class="btn-group">
{% if display_btn_list %}
<a href="{{ sonata_admin.field_description.associationadmin.generateUrl('list', sonata_admin.field_description.getOption('link_parameters', {})) }}"
onclick="return start_field_dialog_form_list_{{ id }}(this);"
class="btn btn-info btn-sm sonata-ba-action"
title="{{ btn_list|trans({}, btn_catalogue) }}"
>
<i class="fa fa-list"></i>
{{ btn_list|trans({}, btn_catalogue) }}
</a>
{% endif %}
{% if display_btn_add %}
<a href="{{ sonata_admin.field_description.associationadmin.generateUrl('create', sonata_admin.field_description.getOption('link_parameters', {})) }}"
onclick="return start_field_dialog_form_add_{{ id }}(this);"
class="btn btn-success btn-sm sonata-ba-action"
title="{{ btn_add|trans({}, btn_catalogue) }}"
>
<i class="fa fa-plus-circle"></i>
{{ btn_add|trans({}, btn_catalogue) }}
</a>
{% endif %}
</div>
{% endif %}
{% if sonata_admin.edit == 'list' and sonata_admin.field_description.associationadmin.hasRoute('delete') and sonata_admin.field_description.associationadmin.isGranted('DELETE') and btn_delete %}
<a href=""
onclick="return remove_selected_element_{{ id }}(this);"
class="btn btn-danger btn-sm sonata-ba-action"
title="{{ btn_delete|trans({}, btn_catalogue) }}"
>
<i class="fa fa-minus-circle"></i>
{{ btn_delete|trans({}, btn_catalogue) }}
</a>
{% endif %}
</div>
{% include 'SonataAdminBundle:CRUD/Association:edit_modal.html.twig' %}
</div>
{% include 'SonataAdminBundle:CRUD/Association:edit_many_script.html.twig' %}
{% endif %}

View File

@@ -0,0 +1,41 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends admin.getTemplate('base_list_field') %}
{% block field %}
{% set route_name = field_description.options.route.name %}
{% if field_description.hasassociationadmin and field_description.associationadmin.hasRoute(route_name) %}
{% for element in value %}
{%- if field_description.associationadmin.hasAccess(route_name, element) -%}
{{ block('relation_link') }}
{%- else -%}
{{ block('relation_value') }}
{%- endif -%}
{% if not loop.last %}, {% endif %}
{% endfor %}
{% else %}
{% for element in value%}
{{ block('relation_value') }}
{% if not loop.last %}, {% endif %}
{% endfor %}
{% endif %}
{% endblock %}
{%- block relation_link -%}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, element, field_description.options.route.parameters) }}">
{{- element|render_relation_element(field_description) -}}
</a>
{%- endblock -%}
{%- block relation_value -%}
{{- element|render_relation_element(field_description) -}}
{%- endblock -%}

View File

@@ -0,0 +1,29 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends admin.getTemplate('base_list_field') %}
{% block field %}
{% if value %}
{% set route_name = field_description.options.route.name %}
{% if not field_description.options.identifier|default(false) and
field_description.hasAssociationAdmin and
field_description.associationadmin.hasRoute(route_name) and
field_description.associationadmin.hasAccess(route_name, value)
%}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, value, field_description.options.route.parameters) }}">
{{ value|render_relation_element(field_description) }}
</a>
{% else %}
{{ value|render_relation_element(field_description) }}
{% endif %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,40 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends admin.getTemplate('base_list_field') %}
{% block field %}
{% set route_name = field_description.options.route.name %}
{% if field_description.hasassociationadmin and field_description.associationadmin.hasRoute(route_name) %}
{% for element in value %}
{%- if field_description.associationadmin.hasAccess(route_name, element) -%}
{{ block('relation_link') }}
{%- else -%}
{{ block('relation_value') }}
{%- endif -%}
{% if not loop.last %}, {% endif %}
{% endfor %}
{% else %}
{% for element in value %}
{{ block('relation_value') }}{% if not loop.last %}, {% endif %}
{% endfor %}
{% endif %}
{% endblock %}
{%- block relation_link -%}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, element, field_description.options.route.parameters) }}">
{{- element|render_relation_element(field_description) -}}
</a>
{%- endblock -%}
{%- block relation_value -%}
{{- element|render_relation_element(field_description) -}}
{%- endblock -%}

View File

@@ -0,0 +1,24 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends admin.getTemplate('base_list_field') %}
{% block field %}
{% set route_name = field_description.options.route.name %}
{% if field_description.hasAssociationAdmin
and field_description.associationadmin.id(value)
and field_description.associationadmin.hasRoute(route_name)
and field_description.associationadmin.hasAccess(route_name, value) %}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, value, field_description.options.route.parameters) }}">{{ value|render_relation_element(field_description) }}</a>
{% else %}
{{ value|render_relation_element(field_description) }}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,31 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{% block field %}
<ul class="sonata-ba-show-many-to-many">
{% set route_name = field_description.options.route.name %}
{% for element in value %}
<li>
{% if field_description.hasassociationadmin
and field_description.associationadmin.hasRoute(route_name)
and field_description.associationadmin.hasAccess(route_name, element) %}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, element, field_description.options.route.parameters) }}">
{{ element|render_relation_element(field_description) }}
</a>
{% else %}
{{ element|render_relation_element(field_description) }}
{% endif %}
</li>
{% endfor %}
</ul>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{% block field %}
{% if value %}
{% set route_name = field_description.options.route.name %}
{% if field_description.hasAssociationAdmin
and field_description.associationadmin.hasRoute(route_name)
and field_description.associationadmin.hasAccess(route_name, value) %}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, value, field_description.options.route.parameters) }}">
{{ value|render_relation_element(field_description) }}
</a>
{% else %}
{{ value|render_relation_element(field_description) }}
{% endif %}
{% endif %}
{% endblock %}

View File

@@ -0,0 +1,31 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{% block field %}
<ul class="sonata-ba-show-one-to-many">
{% set route_name = field_description.options.route.name %}
{% for element in value%}
{% if field_description.hasassociationadmin
and field_description.associationadmin.hasRoute(route_name)
and field_description.associationadmin.hasAccess(route_name, element) %}
<li>
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, element, field_description.options.route.parameters) }}">
{{ element|render_relation_element(field_description) }}
</a>
</li>
{% else %}
<li>{{ element|render_relation_element(field_description) }}</li>
{% endif %}
{% endfor %}
</ul>
{% endblock %}

View File

@@ -0,0 +1,26 @@
{#
This file is part of the Sonata package.
(c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
#}
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{% block field %}
{% set route_name = field_description.options.route.name %}
{% if field_description.hasAssociationAdmin
and field_description.associationadmin.id(value)
and field_description.associationadmin.hasRoute(route_name)
and field_description.associationadmin.hasAccess(route_name, value) %}
<a href="{{ field_description.associationadmin.generateObjectUrl(route_name, value, field_description.options.route.parameters) }}">
{{ value|render_relation_element(field_description) }}
</a>
{% else %}
{{ value|render_relation_element(field_description) }}
{% endif %}
{% endblock %}