N°8031 - Make all portal bricks use custom templates for all templates (#696)

Service implementation
This commit is contained in:
Benjamin Dalsass
2025-01-13 08:04:49 +01:00
committed by GitHub
parent 93dba0644d
commit 9fadbb5eb1
52 changed files with 1681 additions and 501 deletions

View File

@@ -1,5 +1,4 @@
{# itop-portal-base/portal/templates/bricks/aggregate-page/layout.html.twig #}
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
{% block pPageBodyClass %}{{ parent() }} page_aggregate_page_brick home{% endblock %}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/browse/layout.html.twig #}
{# Browse brick base layout #}
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
{% block pPageBodyClass %}{{ parent() }} page_browse_brick page_browse_brick_as_{{ sBrowseMode }}{% endblock %}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/browse/mode_list.html.twig #}
{# Browse brick list mode layout #}
{% extends 'itop-portal-base/portal/templates/bricks/browse/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick', oBrick) %}
{% block bBrowseMainContent%}
<table id="brick-content-table" class="object-list table table-striped table-bordered responsive" cellspacing="0" width="100%">
@@ -11,8 +9,8 @@
{% block pPageLiveScripts %}
{{ parent() }}
<script type="text/javascript">
<script type="text/javascript">
var sBrowseMode = '{{ sBrowseMode }}';
var sDataLoading = '{{ sDataLoading }}';
var oLevelsProperties = {{ aLevelsProperties|raw }};
@@ -22,8 +20,8 @@
var iSearchThrottle = 600;
var oKeyTimeout;
var aKeyTimeoutFilteredKeys = [9, 16, 17, 18, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40]; // Tab, Shift, Ctrl, Alt, Pause, Esc, Page Up/Down, Home, End, Left/Up/Right/Down arrows
// Show a loader inside the table
// Show a loader inside the table
var showTableLoader = function(oElem)
{
oElem.children('tbody').html('<tr><td class="datatables_overlay" colspan="100">' + $('#page_overlay').html() + '</td></tr>');
@@ -32,8 +30,8 @@
var getColumnsDefinition = function()
{
var aColumnsDefinition = [];
for(sKey in oLevelsProperties)
for (sKey in oLevelsProperties)
{
// Level main column
aColumnsDefinition.push({
@@ -189,8 +187,8 @@
},
},
});
// Level's fields columns
// Level's fields columns
if(oLevelsProperties[sKey].fields !== undefined)
{
for(var i in oLevelsProperties[sKey].fields)
@@ -231,15 +229,15 @@
}
}
}
return aColumnsDefinition;
return aColumnsDefinition;
};
$(document).ready(function()
$(document).ready(function ()
{
showTableLoader($('#brick-content-table'));
// Note : Those options should be externalized in an library so we can use them on any DataTables for the portal.
// Note : Those options should be externalized in an library so we can use them on any DataTables for the portal.
// We would just have to override / complete the necessary elements
oTable = $('#brick-content-table').DataTable({
"language": {
@@ -331,8 +329,8 @@
// Note : The '.off()' call is to unbind event from DataTables that where triggered before we could intercept anything
$('#brick-content-table_filter input').off().on('keyup', function(event){
var me = this;
// We trigger the search only if those keys where not pressed
// We trigger the search only if those keys where not pressed
if(aKeyTimeoutFilteredKeys.indexOf(event.which) < 0)
{
clearTimeout(oKeyTimeout);
@@ -348,8 +346,8 @@
showTableLoader($(this));
}
});
// Auto collapse item actions popup
// Auto collapse item actions popup
$('body').on('click', function(){
$('table .item-action-wrapper.collapse.in').collapse('hide');
});

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/browse/mode_mosaic.html.twig #}
{# Browse brick mosaic mode layout #}
{% extends 'itop-portal-base/portal/templates/bricks/browse/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick', oBrick) %}
{% block bBrowseMainContent %}
<div id="brick_content_mosaic">

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/browse/mode_tree.html.twig #}
{# Browse brick tree mode layout #}
{% extends 'itop-portal-base/portal/templates/bricks/browse/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\BrowseBrick', oBrick) %}
{#
Documentation :

View File

@@ -1,44 +0,0 @@
{# itop-portal-base/portal/templates/bricks/create/layout.html.twig #}
{# Create brick base layout #}
{% extends 'itop-portal-base/portal/templates/modal/layout.html.twig' %}
{% block pModalTitle %}
{{ sPageTitle|dict_s }}
{% endblock %}
{% block pModalBody %}
<p>{{ 'Brick:Portal:Create:ChooseType'|dict_s }}</p>
<ul id="{{ sLeafClassesListId }}">
{% for aLeafClass in aLeafClasses %}
<li><a href="#" data-target-class="{{ aLeafClass.id }}">{{ aLeafClass.name }}</a></li>
{% endfor %}
</ul>
<script type="text/javascript">
$(document).ready(function(){
$('#{{ sLeafClassesListId }} a').off('click').on('click', function(oEvent){
oEvent.preventDefault();
// Preparing target class url
var sUrl = '{{ app['url_generator'].generate('p_object_create', {sObjectClass : '-sObjectClass-'})|raw }}';
sUrl = sUrl.replace(/-sObjectClass-/, $(this).attr('data-target-class') );
sUrl = CombodoGlobalToolbox.AddParameterToUrl(sUrl, 'ar_token', '{{ ar_token }}');
// Creating a new modal
CombodoModal.OpenModal({
base_modal: {
usage: 'replace',
selector: $(this).closest('.modal'),
},
content: {
endpoint: sUrl,
},
});
});
});
</script>
{% endblock %}
{% block pModalFooter %}
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'Portal:Button:Cancel'|dict_s }}</button>
{% endblock %}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/layout.html.twig #}
{# Brick base layout #}
{% extends app['combodo.portal.instance.conf'].properties.templates.layout %}
{% extends template('page') %}
{% block pPageTitle %}
{# Overloading the default template's title to show the brick's title #}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/manage/layout-chart.html.twig #}
{# Manage brick base layout #}
{% extends 'itop-portal-base/portal/templates/bricks/manage/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) %}
{% block pPageBodyClass %}{{ parent() }} page_manage_brick{% endblock %}
@@ -8,7 +6,7 @@
{% block pMainContentHolder %}
<div class="panel panel-default">
<div class="panel-body">
{% include 'itop-portal-base/portal/templates/bricks/manage/mode-' ~ sDisplayMode ~ '.html.twig' with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
{% include template(sDisplayMode, 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
</div>
</div>
{% endblock %}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/manage/layout-table.html.twig #}
{# Manage brick base layout #}
{% extends 'itop-portal-base/portal/templates/bricks/manage/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) %}
{% block pPageBodyClass %}{{ parent() }} page_manage_brick{% endblock %}

View File

@@ -1,5 +1,4 @@
{# itop-portal-base/portal/templates/bricks/manage/layout.html.twig #}
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
{% block pMainHeaderTitle %}{{ oBrick.GetTitle()|dict_s }} {% if iCount >= 0 %} ({{ iCount }}){% endif %} {% endblock %}
@@ -9,7 +8,7 @@
{% for sDisplay in oBrick.GetAvailablesDisplayModes %}
<a href="{{ app.url_generator.generate('p_manage_brick_display_as', {'sBrickId': sBrickId, 'sDisplayMode': sDisplay}) }}{% if app['combodo.portal.instance.routes'][oBrick.GetRouteName]['hash'] is defined %}#{{ app['combodo.portal.instance.routes'][oBrick.GetRouteName]['hash'] }}{% endif %}"
id="btn_tab_for_{{ sDisplay }}"
class="btn btn-default {% if sDisplay == oBrick.GetPresentationDataForTileMode(sDisplayMode).layoutDisplayMode %}active{% endif %}">
class="btn btn-default {% if sDisplay == sDisplayMode %}active{% endif %}">
{{ ('Brick:Portal:Manage:DisplayMode:' ~ sDisplay)|dict_s }}
</a>
{% endfor %}

View File

@@ -10,9 +10,9 @@
id="brick-{{ oBrick.GetId }}"
data-brick-id="{{ oBrick.GetId }}">
<div>
<div class="tile_title"><span class="icon fas fa-{{ oBrick.GetDecorationCssClass }}"></span> {{ oBrick.GetTitle()|dict_s }}
<div class="tile_title"><span class="icon {{ oBrick.GetDecorationClassHome }}"></span> {{ oBrick.GetTitle()|dict_s }}
({{ iCount }})</span> </div>
{% include 'itop-portal-base/portal/templates/bricks/manage/mode-' ~ oBrick.GetTileMode ~ '.html.twig' with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
{% include template(oBrick.GetTileMode, 'Combodo\\iTop\\Portal\\Brick\\ManageBrick', oBrick) with {'oBrick': oBrick, 'aColumns': aColumns, 'aNames': aNames, 'aUrls': aUrls, 'aDisplayValues': aDisplayValues} %}
</div>
</a>
{% endblock %}

View File

@@ -11,7 +11,7 @@
data-brick-id="{{ oBrick.GetId }}">
<div style="background-color:#fff;padding:0.25em;">
<div class="tile_title">
<span class="icon fas fa-signal fa-rotate-270"></span> {{ oBrick.GetTitle()|dict_s }}
<span class="icon {{ oBrick.GetDecorationClassHome }}"></span> {{ oBrick.GetTitle()|dict_s }}
({{ iCount }})</span> </div>
<table class="table table-sm">
<thead>

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/object/layout.html.twig #}
{# Object brick base layout #}
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
{% extends template('page') %}
{% block pPageBodyClass %}{{ parent() }} page_object_brick page_object_brick_as_{{ sMode }}{% endblock %}
@@ -27,7 +25,7 @@
{% block pMainContentHolder%}
<div class="panel panel-default">
<div class="panel-body">
{% include 'itop-portal-base/portal/templates/bricks/object/mode_' ~ sMode ~ '.html.twig' %}
{% include template(sMode, 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
</div>
</div>
{% endblock %}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/object/modal.html.twig #}
{# Object brick base layout #}
{% extends 'itop-portal-base/portal/templates/modal/layout.html.twig' %}
{% extends template('modal') %}
{% block pModalTitle %}
{% if form.title_clipboard_text is defined %}
@@ -19,5 +17,5 @@
{% endblock %}
{% block pModalBody %}
{% include 'itop-portal-base/portal/templates/bricks/object/mode_' ~ sMode ~ '.html.twig' with {tIsModal: true} %}
{% include template(sMode, 'Combodo\\iTop\\Portal\\Controller\\ObjectController') with {tIsModal: true} %}
{% endblock %}

View File

@@ -1,5 +1,3 @@
{# itop-portal-base/portal/templates/bricks/object/mode_apply_stimulus.html.twig #}
{# Object brick apply stimulus layout #}
{% extends 'itop-portal-base/portal/templates/bricks/object/mode_create.html.twig' %}
{% extends template('mode_create', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
{# This layout is exactly the same as the mode_create.html.twig, we duplicated it in case we need to have some subtle differences #}

View File

@@ -1,5 +1,3 @@
{# itop-portal-base/portal/templates/bricks/object/mode_create.html.twig #}
{# Object brick edit layout #}
{% extends 'itop-portal-base/portal/templates/bricks/object/mode_create.html.twig' %}
{% extends template('mode_create', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
{# This layout is exactly the same as the mode_create.html.twig, we duplicated it in case we need to have some subtle differences #}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/object/mode_view.html.twig #}
{# Object brick view layout #}
{% extends 'itop-portal-base/portal/templates/bricks/object/mode_create.html.twig' %}
{% extends template('mode_create', 'Combodo\\iTop\\Portal\\Controller\\ObjectController') %}
{# This layout is exactly the same as the mode_create.html.twig, we duplicated it in case we need to have some subtle differences #}

View File

@@ -1,6 +1,4 @@
{# itop-portal-base/portal/templates/bricks/user-profile/layout.html.twig #}
{# User profile brick base layout #}
{% extends 'itop-portal-base/portal/templates/bricks/layout.html.twig' %}
{% extends template('page', 'Combodo\\iTop\\Portal\\Brick\\AbstractBrick') %}
{% if sTab == "" %}
{% set sTab = "user-info" %}

View File

@@ -0,0 +1,170 @@
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
{% block toolbar %}
{# toolbar text & icon #}
{% set icon %}
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M192 64l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM82.7 207c-15.3 8.8-20.5 28.4-11.7 43.7l32 55.4c8.8 15.3 28.4 20.5 43.7 11.7l55.4-32c15.3-8.8 20.5-28.4 11.7-43.7l-32-55.4c-8.8-15.3-28.4-20.5-43.7-11.7L82.7 207zM288 192c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zm64 160c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zM160 384l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM32 352c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0z"/></svg>
</span>
<span class="sf-toolbar-label">Portal{% if collector.GetTemplatesCount.overrides_count > 0 %} <span style=" color: var(--sf-toolbar-yellow-600);"> Overrides</span>{% endif %}</span>
{% endset %}
{# toolbar panel #}
{% set text %}
<div class="sf-toolbar-info-piece">
<b>Templates registered</b><span class="sf-toolbar-status">{{ collector.GetTemplatesCount.count }}</span>
</div>
{% if collector.GetTemplatesCount.overrides_count %}
<div class="sf-toolbar-info-piece">
<b>Templates overridden</b><span class="sf-toolbar-status">{{ collector.GetTemplatesCount.overrides_count }}</span>
</div>
{% endif %}
{% endset %}
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
{% endblock %}
{% block head %}
{{ parent() }}
<style>
.overridden_value {
color: var(--color-link);
}
.old_value {
color: grey;
text-decoration: line-through;
}
</style>
{% endblock %}
{% block menu %}
{# menu #}
<span class="label label-status-none">
<span class="icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" fill="currentColor"><path d="M192 64l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM82.7 207c-15.3 8.8-20.5 28.4-11.7 43.7l32 55.4c8.8 15.3 28.4 20.5 43.7 11.7l55.4-32c15.3-8.8 20.5-28.4 11.7-43.7l-32-55.4c-8.8-15.3-28.4-20.5-43.7-11.7L82.7 207zM288 192c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zm64 160c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0zM160 384l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0c-17.7 0-32 14.3-32 32zM32 352c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l64 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-64 0z"/></svg>
</span>
<strong>Portal</strong>
<span class="count">
{{ collector.GetTemplatesCount.count }}
</span>
</span>
{% endblock %}
{% block panel %}
{# title #}
<h2>Templates</h2>
{# metrics #}
<div class="metrics">
{# ui version #}
<div class="metric">
<span class="value">{{ collector.GetUIVersion }}</span>
<span class="label">UI Version</span>
</div>
<div class="metric-divider"></div>
{# templates #}
<div class="metric-group">
<div class="metric">
<span class="value">{{ collector.GetTemplatesCount.count }}</span>
<span class="label">Templates</span>
</div>
<div class="metric">
<span class="value">{{ collector.GetTemplatesCount.overrides_count }}</span>
<span class="label">Overridden</span>
</div>
</div>
{# additional info #}
<div class="metric-divider"></div>
<div class="metric-group">
<div class="metric">
<span class="value">{{ collector.GetTemplatesCount.extensions_count }}</span>
<span class="label">Extensions</span>
</div>
<div class="metric">
<span class="value">{{ collector.GetTemplatesCount.providers_count }}</span>
<span class="label">Providers</span>
</div>
</div>
</div>
{# Instances overloads #}
<h2>Bricks declared templates list</h2>
{# help #}
<p class="help">
Bricks overridden templates are templates defined in brick declarations.
</p>
{% if collector.GetInstancesOverriddenTemplates|length == 0 %}
No instance overridden template.
{% else %}
<table>
<thead>
<tr>
<th>Brick</th>
<th>Class</th>
<th>ID</th>
<th>Template</th>
</tr>
</thead>
{% for instance,item in collector.GetInstancesOverriddenTemplates %}
{% for id,template in item.templates %}
<tr>
<td>{{ item.info.id }}</td>
<td>{{ item.info.class }}</td>
<td>{{ id }}</td>
<td>{{ template }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
{% endif %}
{# templates list #}
<h2>Templates list</h2>
{# help #}
<p class="help">
Templates doesn't necessary covers all existing templates, only the ones that are registered in the portal.
</p>
<table>
<thead>
<tr>
<th>Provider</th>
<th>ID</th>
<th>Template</th>
<th>Alias</th>
<th>Override</th>
</tr>
</thead>
{% for provider,item in collector.GetTemplatesDefinitions %}
{% for id,template in item %}
<tr {% if template.IsOverridden %}class="overridden_value"{% endif %}>
<td>{{ provider }}</td>
<td>{{ template.Id }}</td>
<td>{{ template.path }}{% if template.IsOverridden %}
<div class="old_value">{{ template.GetPath(true) }}</div>{% endif %}</td>
<td>{{ template.Alias }}</td>
<td>{% if template.IsOverridable %}
{% if template.IsOverridden %}
Yes
{% else %}
No
{% endif %}
{% else %}
Not allowed
{% endif %}
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
{% endblock %}