Symfony - easyAdmin changing 'list.row_actions' - symfony

Currently I'm using Symfony 3 and implementing Easy Admin backend.
By default, the label available show as something like 'list.row_actions'.
I have read the documentation for Easy Admin, and manage to edit certain label such as Edit and Delete.
But come to confusion why I cannot edit the 'list.row_actions on the list table header.
The same problem I have with the Edit page, specifically the buttons:
Here is some of the configurations I add into config.yml under easy_admin tree:
config.yml
list:
actions:
- { name: 'new', label: 'New' }
- { name: 'search', label: 'Search' }
- { name: 'edit', label: 'Edit' }
- { name: 'delete', label: 'Delete' }

After several tweaking and failures, I have found a solution, it was documented but I did not expect it to be documented there nested.
Here's the github page: Advanced Design Configuration
We will overwrite the default html.twig file by overriding the {{ block }}
Create an Overwrite Folder
First, create a folder easy_admin inside Resources\views.
Suppose you want to change list.row_actions, head over to the source file from easy-admin usually inside:
vendor\javiereguiluz\easyadmin-bundle\views\includes\ In the last version
Finding the source
Find the list.html.twig file and check out its content for a brief. If you CTRL + F (Find) for list.row_actions, it will show you directly something like this. Now copy the whole block
{% block table_head %}
<tr>
{% for field, metadata in fields %}
{% set isSortingField = metadata.property == app.request.get('sortField') %}
{% set nextSortDirection = isSortingField ? (app.request.get('sortDirection') == 'DESC' ? 'ASC' : 'DESC') : 'DESC' %}
{% set _column_label = (metadata.label ?: field|humanize)|trans(_trans_parameters) %}
{% set _column_icon = isSortingField ? (nextSortDirection == 'DESC' ? 'fa-caret-up' : 'fa-caret-down') : 'fa-sort' %}
<th data-property-name="{{ metadata.property }}" class="{{ isSortingField ? 'sorted' }} {{ metadata.virtual ? 'virtual' }} {{ metadata.dataType|lower }} {{ metadata.css_class }}">
{% if metadata.sortable %}
<a href="{{ path('easyadmin', _request_parameters|merge({ sortField: metadata.property, sortDirection: nextSortDirection })) }}">
<i class="fa {{ _column_icon }}"></i>
{{ _column_label|raw }}
</a>
{% else %}
<span>{{ _column_label|raw }}</span>
{% endif %}
</th>
{% endfor %}
{% if _list_item_actions|length > 0 %}
<th>
<span>{{ 'list.row_actions'|trans(_trans_parameters, 'EasyAdminBundle') }}</span>
</th>
{% endif %}
</tr>
{% endblock table_head %}
Pasting to Overwrite File
To paste/overwrite this, you need to create a file with exact name as the filename where you copied it. In this case, list.html.twig. Then paste it inside the file
IMPORTANT : At top of the file, include this tag -
{% extends '#EasyAdmin/default/list.html.twig' %}
{% block table_head %}
<tr>
{% for field, metadata in fields %}
...code continues...
Why overwrite?
If you edit the file from the source code, you will have trouble deploying it especially if you're using git clone and then composer update.
Overwriting make sure that the code persist even when you deploy it.

I've had the same issue. As for me, I fixed it easier.
First of all try to use this
# app/config/config.yml (Symfony3)
# config/packages/framework.yaml (Symfony4)
framework:
translator: { fallbacks: "%locale%" }
But if you want to override with your translation, create this file:
# translations/EasyAdminBundle.en.yaml
list.row_actions: "My actions"

Related

Set default value if null in twig

I am looping my results in twig view..
{% for item in items %}
<li> {{ item.userId.firstName }} {{ item.userId.lastName }} </li>
{% endfor %}
I want to set default value 'User unknown' if the user id in database is NULL .
Like: {% if item.userId is null %} --> than set default value
Note: I am aware of using if else here but as I have this fistName - lastName in numerous palace, I wanted to avoid using if else in every part. I wanted to set that default value everywhere in case userId is null without repeating the code in every place.
How can I accomplish that?
EDIT
You can set a variable by using:
{% set name = item.userId is null ? 'User unknown' : item.userId.firstName ~ ' ' ~ item.userId.lastName %}
If by setting you mean outputting 'User unknown', a simple if else statement would do the trick
{% for item in items %}
{% if item.userId is null %}
<li>User unknown</li>
{% else %}
<li> {{ item.userId.firstName }} {{ item.userId.lastName }} </li>
{% endif %}
{% endfor %}
It may be easier to set defaults in the code that is rendering the output, where items is being sent to Twig. array_merge is often used for this - $item = array_merge($defaultItem, $item);. Here, $item overrides the value set in defaults.
Within the templates, you can also use the null-coalescing operator ?? on individual fields: {{ item.userId.firstName ?? 'unknown firstName' }}
Maybe a bit late, but Twig seems to have a filter for default values:
https://twig.symfony.com/doc/2.x/filters/default.html

KNP Menu Bundle Translation Domain

I'm using Symfony 2.3 and the KnpMenuBundle.
Is it possible to use a translation domain for menu items?
Like this:
$menu['management']->addChild(
'msg.user.list',
array(
'route' => 'user_list',
'translation_domain' => 'navigation'
)
);
According to the Symfony documentation and KnpMenuBundle documentation,you may set the translation domain (menu in my snippets), while adding menu items in your MenuBuilder class:
$menu->addChild('Home', array('route' => 'homepage'))
->setExtra('translation_domain', 'menu');
You may better want to add the translation domain into the whole menu instead:
$menu = $this->factory->createItem('root')
->setExtra('translation_domain', 'menu');
Then create a file named knp_menu.html.twig in:
app/Resources/views/menu/
and put this in it:
{% extends 'knp_menu.html.twig' %}
{% block label %}
{% if options.allow_safe_labels and item.getExtra('safe_label', false) %}
{{ item.label | raw | trans(item.getExtra('translation_params', {}), item.getExtra('translation_domain', 'menu'))}}
{% else %}
{{ item.label | trans(item.getExtra('translation_params', {}), item.getExtra('translation_domain', 'menu')) }}
{% endif %}
{% endblock %}
(If the file already exists, just replace the {% block label %}{% endblock %} part)
Be carefull to have translation files (.xliff or whatever) naming strategy like:
{translation_domain}.{locale}.{extenstion}
for example:
menu.fa.xliff
In this path:
app/Resources/translations/
The last part is:
# app/config/config.yml
knp_menu:
twig:
template: knp_menu.html.twig
Up-Vote this nice tutorial.
Have fun!

Unable to override KnpMenuBundle template

With ...MyBundle\Resources\views\Menu\knp_menu.html.twig, deleting the </li> has no effect on the rendered menu. (Removing the tag is done to remove the space between inline list elements.) I have followed the advice provided in this answer, including the {% import 'knp_menu.html.twig' as knp_menu %} mentioned toward the bottom of that post. Is this because knp_menu.html.twig already extends knp_menu_base.html.twig? Or what?
layout.html.twig:
...
{{ render(controller('VolVolBundle:Default:userMenu')) }}
...
userMenuAction:
$user = $this->getUser();
$tool = $this->container->get('vol.toolbox');
$type = $tool->getUserType($user);
return $this->render(
'VolVolBundle:Default:userMenu.html.twig', array('type' => $type)
);
userMenu.html.twig
...
{% if type is not null %}
{% set menu = "VolVolBundle:Builder:"~type~"Menu" %}
{{ knp_menu_render(menu) }}
{% endif %}
The answer was found deep in here. All that's required to do a global override of the template is to modify config.yml.
config.yml:
...
knp_menu:
twig: # use "twig: false" to disable the Twig extension and the TwigRenderer
template: VolVolBundle:Menu:knp_menu.html.twig
...

Activity Log in dashboard sonata admin

I'm trying to implement activity log in the dashboard i.e. a notification in each row that says which entities have a change since the last login of a user.
To do it I'm thinking about overwrite the class AdminListBlockService and the template block_admin_list.html.twig
but i don't have yet clear how do it.
someone know a better way to do it? if that is the better way, how can I achieve it?
thanks a lot!
ok
I found a better way... i have overwritten only the block_admin_list.html.twig so:
//config.yml
sonata_admin:
templates:
list_block: AdminBundle:Block:block_admin_list.html.twig
note the diference "SonataAdminBundle" and "AdminBundle"
next step add in the template:
{% if admin.activityLog() is defined and admin.isGranted('LIST') %}
<a class="btn btn-link" href="{{ admin.generateUrl('list')>admin.activityLog</a>
{% endif %}
and finally create the logic for each Entity where i want the notification
//in the exempleAdmin
public function activityLog(){
// custom code $activity= ....
return $activity;
}
if someone know a better way to do it, please let me know, thanks
Well what you can do is override the template like this:
In your admin class:
// Configure our custom roles for this entity
public function configure() {
parent::configure();
$this->setTemplate('list', 'MyAdminBundle:CRUD:list-myentity.html.twig');
}
Then in your template you can do something like:
{# The default template which provides batch and action cells, with the valid colspan computation #}
{% extends 'SonataAdminBundle:CRUD:list.html.twig' %}
{% block table_body %}
<tbody>
{% for object in admin.datagrid.results %}
<style>
table tr.green-color td {background-color: #2BFF5D !important; }
</style>
<tr {% if changed %} class="green-color" {% endif %}>
{% include admin.getTemplate('inner_list_row') %}
</tr>
{% endfor %}
</tbody>
{% endblock %}

Symfony2: How to display admin-account name while impersonating user-account?

I want to display something like that:
Case 1: "logged in as USER"
# UserName [ logout ]
No problems here, i just do:
# {{ app.user.username}} [ logout ]
Case 2: "logged in as ADMIN"
# AdminName [ logout ]
The same works here:
# {{ app.user.username}} [ logout ]
Case 3: "logged in as ADMIN impersonating a USER"
AdminName # UserName [ return ]
Now thats a problem:
{{ ??..what here..?? }} # {{ app.user.username}} [ return ]
This is the only solution I know... it seems a lot of code for a sipmle displaying username :/
{# iterating through user roles to find ROLE_PREVIOUS_ADMIN #}
{% for role in app.security.token.roles %}
{% if role.source is defined %}
{{ role.source.user.username }}
{% endif %}
{% endfor %}
# {{ app.user.username }} [ return ]
Is there any other way? I need a pure TWIG solution -> this is supposed to be part of my main twig template (that is extended by all other templates) -> I can't add controller code to all actions, just to display username.
With the idea you have proposed above,.. can you not just create a custom twig extension that encompasses your logic from your twig template so that you can just call myCustomTwigFunction within your twig template and it will output the original users name?
See http://symfony.com/doc/current/cookbook/templating/twig_extension.html for more info about custom twig extensions
The code you'd have in your Twig extension file would be...
$roles = $this->container->get('security.context')->getToken()->getRoles();
foreach ($roles as $role) {
if (method_exists($role, 'getSource')) {
return ($role->getSource()->getUser()->getUsername());
}
}
Where $container is a class variable of the DI Container on your twig extension class
For anyone looking for a solution for Symfony 4.3/4.4/5.0:
{% if is_granted('ROLE_PREVIOUS_ADMIN') %}
{% for role in app.token.roles %}
{% if role.role == 'ROLE_PREVIOUS_ADMIN' %}
Admin username is {{ role.source.user.username }}
{% endif %}
{% endfor %}
{% endif %}
From Symfony 5.1 onwards, use IS_IMPERSONATOR in place of ROLE_PREVIOUS_ADMIN.

Resources