Parcourir la source

Intégration de vich uploaderBundle

reduction
Fab il y a 4 ans
Parent
révision
56fdba10fa
14 fichiers modifiés avec 160 ajouts et 75 suppressions
  1. +17
    -0
      ShopBundle/Controller/Admin/AdminController.php
  2. +1
    -0
      ShopBundle/Controller/Admin/ProductFamilyController.php
  3. +26
    -0
      ShopBundle/Model/AbstractDocumentEntity.php
  4. +6
    -6
      ShopBundle/Model/PriceTrait.php
  5. +2
    -5
      ShopBundle/Model/ProductFamily.php
  6. +6
    -1
      ShopBundle/Resources/public/css/backend/custom.css
  7. +2
    -30
      ShopBundle/Resources/public/js/backend/script/default/init-list.js
  8. +6
    -0
      ShopBundle/Resources/translations/lcshop.fr.yaml
  9. +6
    -0
      ShopBundle/Resources/views/backend/default/block/vich_uploader_image.html.twig
  10. +1
    -12
      ShopBundle/Resources/views/backend/default/field_toggle.html.twig
  11. +3
    -2
      ShopBundle/Resources/views/backend/default/list.html.twig
  12. +46
    -17
      ShopBundle/Resources/views/backend/form/custom_bootstrap_4.html.twig
  13. +1
    -1
      ShopBundle/Resources/views/backend/productfamily/panel_general.html.twig
  14. +37
    -1
      ShopBundle/Twig/FrontendTwigExtension.php

+ 17
- 0
ShopBundle/Controller/Admin/AdminController.php Voir le fichier

@@ -17,7 +17,9 @@ use Lc\ShopBundle\Form\AbstractEditPositionType;
use Lc\ShopBundle\Services\Utils;
use Mailjet\MailjetSwiftMailer\SwiftMailer\MailjetTransport;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\RadioType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Security\Core\Security;
@@ -247,7 +249,22 @@ class AdminController extends EasyAdminController
$formBuilder = parent::createEntityFormBuilder($entity, $view);

$id = (null !== $entity->getId()) ? $entity->getId() : 0;

if ($entity instanceof StatusInterface) {
$formBuilder->add('status', ChoiceType::class, array(
'choices' =>array(
'field.default.statusOptions.offline' => '0',
'field.default.statusOptions.online' => '1'
),
'expanded' => true,
'required' => true,
'translation_domain'=> 'lcshop'
)
);
}

if ($entity instanceof TreeInterface) {

$formBuilder->add('parent', EntityType::class, array(
'class' => $this->entity['class'],
'query_builder' => function (EntityRepository $repo) use ($id) {

+ 1
- 0
ShopBundle/Controller/Admin/ProductFamilyController.php Voir le fichier

@@ -77,6 +77,7 @@ class ProductFamilyController extends AdminController
),
'translation_domain' => 'lcshop',
'multiple' => false,
'required'=>false,
'expanded' => true
));


+ 26
- 0
ShopBundle/Model/AbstractDocumentEntity.php Voir le fichier

@@ -8,9 +8,12 @@ use Lc\ShopBundle\Context\SluggableInterface;
use Lc\ShopBundle\Context\SortableInterface;
use Lc\ShopBundle\Context\StatusInterface;
use Lc\ShopBundle\Model\AbstractEntity;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
* @ORM\MappedSuperclass
* @Vich\Uploadable
*/
abstract class AbstractDocumentEntity extends AbstractEntity implements StatusInterface, SortableInterface, SluggableInterface
{
@@ -36,12 +39,35 @@ abstract class AbstractDocumentEntity extends AbstractEntity implements StatusIn
*/
protected $image;

/**
* @Vich\UploadableField(mapping="images", fileNameProperty="image")
* @var File
*/
protected $imageFile;

/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
protected $devAlias;


public function setImageFile(File $image = null)
{
$this->imageFile = $image;

// VERY IMPORTANT:
// It is required that at least one field changes if you are using Doctrine,
// otherwise the event listeners won't be called and the file is lost
if ($image) {
// if 'updatedAt' is not defined in your entity, use another property
$this->updatedAt = new \DateTime('now');
}
}

public function getImageFile()
{
return $this->imageFile;
}
public function getTitle(): ?string
{
return $this->title;

+ 6
- 6
ShopBundle/Model/PriceTrait.php Voir le fichier

@@ -28,12 +28,12 @@ trait PriceTrait
return $this->price;
}

public function getPriceInherited()
public function getPriceInherited(): ?float
{
return $this->getPrice() ;
}

public function getUnitInherited()
public function getUnitInherited(): ?Unit
{
return $this->getUnit() ;
}
@@ -43,17 +43,17 @@ trait PriceTrait
return $this->getTaxRate() ;
}

public function getPriceWithTax()
public function getPriceWithTax(): ?float
{
return $this->calculatePriceWithTax($this->getPriceInherited(), $this->getTaxRateInherited()->getValue()) ;
}

public function getPriceByUnitRef()
public function getPriceByUnitRef(): ?float
{
return ($this->getPriceInherited() * $this->getUnitInherited()->getCoefficient()) / $this->getQuantityInherited() ;
}

public function getPriceByUnitRefWithTax()
public function getPriceByUnitRefWithTax(): ?float
{
return $this->calculatePriceWithTax($this->getPriceByUnitRef(), $this->getTaxRateInherited()->getValue()) ;
}
@@ -89,7 +89,7 @@ trait PriceTrait
return $this;
}

private function calculatePriceWithTax($priceWithoutTax, $taxRateValue)
private function calculatePriceWithTax($priceWithoutTax, $taxRateValue): ?float
{
$price = floatval($priceWithoutTax) * ($taxRateValue/100 + 1) ;
$price = round(( ($price * 100)) / 100, 2) ;

+ 2
- 5
ShopBundle/Model/ProductFamily.php Voir le fichier

@@ -6,13 +6,10 @@ use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Lc\ShopBundle\Context\FilterMerchantInterface;
use Lc\ShopBundle\Context\GlobalParamInterface;
use Lc\ShopBundle\Context\PriceInterface;
use Lc\ShopBundle\Context\ProductInterface;
use Lc\ShopBundle\Context\ProductPropertyInterface;
use Lc\ShopBundle\Services\Price;
use Lc\ShopBundle\Services\Utils;
use League\Flysystem\Util;


/**
* @ORM\MappedSuperclass()
@@ -251,7 +248,7 @@ abstract class ProductFamily extends AbstractDocumentEntity implements ProductPr
public function getProductCategoryChild()
{
$productCategories = $this->getProductCategories() ;
foreach($productCategories as $productCategory) {
if($productCategory->getParent()) {
return $productCategory ;

+ 6
- 1
ShopBundle/Resources/public/css/backend/custom.css Voir le fichier

@@ -9,13 +9,17 @@
.table.datatable-simple .highlight{background: var(--teal);}
.datatable-field-search.small{width: 50px;}

.dataTables_length, .dataTables_filter{padding: .75rem 1.25rem 0.25rem;}

table.fixedHeader-floating{margin-top: 0px !important;}
table th.sorting_asc, table th.sorting_desc{border-top:3px solid var(--success);}
table th.filtered{border-top:3px solid var(--primary);}

td.actions{white-space: nowrap; text-align: right;}


.table td, .table th{padding: 0.35rem;}
.delivery-field .form-group{display: inline-block; margin-bottom: 0px; margin-right: 15px;}
.delivery-field .form-group .form-control{width: 150px;}
/************************ form error *********************/

.form-sent .form-control:invalid{border-color: #dc3545; padding-right: 2.25rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E");background-repeat: no-repeat;background-position: center right calc(.375em + .1875rem); background-size: calc(.75em + .375rem) calc(.75em + .375rem);}
@@ -67,6 +71,7 @@ td.actions{white-space: nowrap; text-align: right;}
padding: 0.250rem .75rem ;
}

.col-form-label{font-weight: bold;}

#toast-container.toast-top-right{top:60px}


+ 2
- 30
ShopBundle/Resources/public/js/backend/script/default/init-list.js Voir le fichier

@@ -36,16 +36,9 @@ function initDataTable() {
}
});
} else if ($(this).data('searchable') == 'select' ){
$(this).html('<select class="list"><option value="all">Tout afficher</option></select>'); //LC_TRAD
$(this).html('<select data-allow-clear="false" class="list"><option value="all">Tout afficher</option></select>'); //LC_TRAD
} else if ($(this).data('searchable') == 'select-text') {
$(this).html('<select class="list-text"><option value="all">Tout afficher</option></select>'); //LC_TRAD
} else if ($(this).data('searchable') == 'toggle') {
$(this).html('<select class="toggle">' +
'<option value="all">Tout afficher</option>' +
'<option value="checked">Oui</option>' +
'<option value="unchecked"> Non</option>' +
'</select>'); //LC_TRAD

$(this).html('<select data-allow-clear="false" class="list-text"><option value="all">Tout afficher</option></select>'); //LC_TRAD
} else {
$(this).html('')
}
@@ -63,27 +56,6 @@ function initDataTable() {
this.api().columns().every( function (i) {
var column = this;
var select = false;
toggle = $('.table.datatable-simple thead tr:eq(1) th:eq('+i+') select.toggle')
if(toggle.length) {
setSelect2(toggle);
toggle.on( 'change', function () {
var val = $.fn.dataTable.util.escapeRegex($(this).val());
if(val=="all"){
column.search('').draw();
}else {
var niche = table.column('2');
log(column.cell('4').data());
/*
val = "bootstrap-switch-on";
column.data().each(function(d){
log(d)
});
//filter in column 5, with an regex, no smart filtering, not case sensitive
column.search( val ? '^'+val+'$' : '', true, false ).draw();*/
}
} );

}
if($('.table.datatable-simple thead tr:eq(1) th:eq('+i+') select.list-text').length) {
select = $('.table.datatable-simple thead tr:eq(1) th:eq(' + i + ') select.list-text');
}

+ 6
- 0
ShopBundle/Resources/translations/lcshop.fr.yaml Voir le fichier

@@ -36,11 +36,15 @@ group:
note: Note interne
None: Aucune valeur
label.form.empty_value: Choisissez une option
form.label.delete: Supprimer l'image
field:
default:
placeholder: Choisissez une option
id: Id
status: En ligne
statusOptions:
offline: <span class="badge badge-danger">Hors ligne</span>
online: <span class="badge badge-success">En ligne</span>
position: Position
createdAt: Date de création
supplier: Producteur
@@ -48,6 +52,7 @@ field:
titleHelp: Ceci est une texte d'aide, utilises <i>le nom du champ</i>Help pour en ajouter un
subtitle: Sous-titre
kmsHub: Nombre de kilomètres depuis le dépôt
imageFile: Image
image: Image
description: Description
type: Type
@@ -63,6 +68,7 @@ field:
siret: N° SIRET
tva: N° TVA
price: Prix de vente
priceWithTax: Prix de vente TTC
username: Nom d'utilisateur
email: E-mail
plainPassword: Mot de passe

+ 6
- 0
ShopBundle/Resources/views/backend/default/block/vich_uploader_image.html.twig Voir le fichier

@@ -0,0 +1,6 @@
<a href="#" class="easyadmin-thumbnail" data-featherlight="#easyadmin-lightbox-{{ item.id }}" data-featherlight-close-on-click="anywhere">
{# the second parameter is the name of the property with the UploadableField annotation #}

<img src="{{ lc_liip(value, 'mini_list') }}">
</a>


+ 1
- 12
ShopBundle/Resources/views/backend/default/field_toggle.html.twig Voir le fichier

@@ -1,18 +1,7 @@
{% trans_default_domain 'EasyAdminBundle' %}
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Toggle this custom switch element</label>
</div>
{% if view == 'show' or ('edit' in backend_config.disabled_actions) %}

{% if value == true %}
<span class="badge badge-success">{{ 'label.true'|trans }}</span>
{% else %}
<span class="badge badge-danger">{{ 'label.false'|trans }}</span>
{% endif %}
{% else %}
<div class="custom-control custom-switch custom-switch-off-danger custom-switch-on-success" data-propertyname="{{ field_options.property }}">
<input class="custom-control-input" type="checkbox" {{ value == true ? 'checked' }}>
<label class="custom-control-label" ></label>

</div>
{% endif %}

+ 3
- 2
ShopBundle/Resources/views/backend/default/list.html.twig Voir le fichier

@@ -106,7 +106,7 @@
{% endblock new_action %}
{% endif %}
</div>
<div class="card-body">
<div class="card-body p-0">

<table class="table datatable-simple table-bordered table-hover table-striped">

@@ -124,6 +124,7 @@
{% set _column_icon = isSortingField ? (nextSortDirection == 'DESC' ? 'fa-arrow-up' : 'fa-arrow-down') : 'fa-sort' %}

{% set searchable = ''%}

{% if metadata.type == 'integer' or metadata.type =="string" %}
{% set searchable = 'input'%}
{% elseif metadata.type == 'association' %}
@@ -131,7 +132,7 @@
{% elseif metadata.type == 'text' %}
{% set searchable= "select-text" %}
{% elseif metadata.type=="toggle" %}
{% set searchable= "toggle" %}
{% set searchable= "select" %}
{% endif %}

{#<th class="{{ isSortingField ? 'sorted' }} {{ metadata.virtual ? 'virtual' }} {{ metadata.dataType|lower }} {{ metadata.css_class }}" >#}

+ 46
- 17
ShopBundle/Resources/views/backend/form/custom_bootstrap_4.html.twig Voir le fichier

@@ -72,22 +72,24 @@
{% import '@LcShop/backend/default/block/macros.html.twig' as macros %}
{% for group_name, group_config in easyadmin_form_groups|filter(group_config => not group_config.form_tab or group_config.form_tab == tab_name) %}
{{ macros.startCard(group_config.columns|default('12'), group_config.label, 'primary') }}
{% for field in form|filter(field => 'hidden' not in field.vars.block_prefixes and field.vars.easyadmin.form_group == group_name) %}
{% if not field.vars.easyadmin.form_tab or field.vars.easyadmin.form_tab == tab_name %}
<div class="col-{{ field.vars.easyadmin.field.columns|default('12') }} {{ field.vars.easyadmin.field.css_class|default('') }}">
{{ form_row(field) }}
</div>
{% endif %}
{% endfor %}
{{ macros.endCard() }}
{% else %}

{{ macros.startCard(8) }}
{% for field in form|filter(field => 'hidden' not in field.vars.block_prefixes and (not field.vars.easyadmin.form_tab or field.vars.easyadmin.form_tab == tab_name)) %}
{% for field in form|filter(field => 'hidden' not in field.vars.block_prefixes and field.vars.easyadmin.form_group == group_name) %}

{% if not field.vars.easyadmin.form_tab or field.vars.easyadmin.form_tab == tab_name %}
<div class="col-{{ field.vars.easyadmin.field.columns|default('12') }} {{ field.vars.easyadmin.field.css_class|default('') }}">
{{ form_row(field) }}
</div>
{% endfor %}
{% endif %}
{% endfor %}
{{ macros.endCard() }}
{% else %}

{{ macros.startCard(8) }}
{% for field in form|filter(field => 'hidden' not in field.vars.block_prefixes and (not field.vars.easyadmin.form_tab or field.vars.easyadmin.form_tab == tab_name)) %}
<div class="col-{{ field.vars.easyadmin.field.columns|default('12') }} {{ field.vars.easyadmin.field.css_class|default('') }}">
{{ form_row(field) }}
</div>
{% endfor %}
{{ macros.endCard() }}
{% endfor %}
{% endblock easyadmin_widget_groups %}
@@ -122,8 +124,18 @@
{%- endblock form_label %}

{% block easyadmin_rest %}
{{- form_rest(form) -}}


{% if form.status is defined %}
<div class="card">
<div class="card-footer field-status-inline">

{{ form_row(form.status) }}

</div>
</div>
{% endif %}
{{- form_rest(form) -}}
<div class="card">
<div class="card-footer">
{{- block('item_actions') -}}
@@ -167,12 +179,29 @@
{{ widget|raw }}
<span class="checkmark"></span>

{# {% if translation_domain == 'lcshop' %}
{{ name|lc_trad(easyadmin['entity']['name'], 'field') }}
{% else %}#}
{{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain)) -}}
{# {% if translation_domain == 'lcshop' %}
{{ name|lc_trad(easyadmin['entity']['name'], 'field') }}
{% else %}#}
{{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain))|raw -}}
{#{% endif %}#}
{{- form_errors(form) -}}
</label>
{%- endif -%}
{%- endblock checkbox_radio_label %}


{% block vich_image_widget %}
{% spaceless %}
<div class="vich-image">
{{ form_widget(form.file) }}
{% if form.delete is defined %}
{{ form_row(form.delete) }}
{% endif %}

{% if image_uri %}
<img src="{{ lc_liip(image_uri, 'tile') }}" alt=""/></a>
{% endif %}

</div>
{% endspaceless %}
{% endblock %}

+ 1
- 1
ShopBundle/Resources/views/backend/productfamily/panel_general.html.twig Voir le fichier

@@ -14,7 +14,7 @@
{{ form_row(form.subtitle) }}
</div>
<div class="col-12">
{{ form_row(form.image) }}
{{ form_row(form.imageFile) }}
</div>
<div class="col-12">
{{ form_row(form.description) }}

+ 37
- 1
ShopBundle/Twig/FrontendTwigExtension.php Voir le fichier

@@ -11,6 +11,8 @@ use Lc\ShopBundle\Context\ProductCategoryInterface;
use Lc\ShopBundle\Context\ProductFamilyInterface;
use Lc\ShopBundle\Form\Frontend\NewsletterType;
use Lc\ShopBundle\Repository\ProductCategoryRepository;
use Liip\ImagineBundle\Imagine\Cache\CacheManager;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security;
@@ -28,9 +30,12 @@ class FrontendTwigExtension extends AbstractExtension
protected $productCategoryRepository ;
protected $merchantRepository ;
protected $productFamilyRepository ;
protected $liipCacheHelper ;
protected $parameterBag ;

public function __construct(EntityManagerInterface $em, Security $security, GlobalParamInterface $globalParam,
FormFactoryInterface $formFactory, RequestStack $requestStack)
FormFactoryInterface $formFactory, RequestStack $requestStack, CacheManager $liipCacheHelper,
ParameterBagInterface $parameterBag)
{
$this->em = $em ;
$this->security = $security ;
@@ -40,6 +45,8 @@ class FrontendTwigExtension extends AbstractExtension
$this->productCategoryRepository = $this->em->getRepository($this->em->getClassMetadata(ProductCategoryInterface::class)->getName()) ;
$this->merchantRepository = $this->em->getRepository($this->em->getClassMetadata(MerchantInterface::class)->getName()) ;
$this->productFamilyRepository = $this->em->getRepository($this->em->getClassMetadata(ProductFamilyInterface::class)->getName()) ;
$this->liipCacheHelper = $liipCacheHelper;
$this->parameterBag = $parameterBag;
}

public function getFunctions()
@@ -48,6 +55,8 @@ class FrontendTwigExtension extends AbstractExtension
new TwigFunction('get_product_categories', [$this, 'getProductCategories']),
new TwigFunction('get_form_newsletter', [$this, 'getFormNewsletter']),
new TwigFunction('get_merchants', [$this, 'getMerchants']),
new TwigFunction('lc_liip', [$this, 'lcLiip']),
new TwigFunction('get_file_manager_folder', [$this, 'getFileManagerFolder']),
);
}

@@ -55,9 +64,36 @@ class FrontendTwigExtension extends AbstractExtension
{
return [
new TwigFilter('format_price', [$this, 'formatPrice']),
new TwigFilter('lc_liip', [$this, 'lcLiip']),
];
}

public function lcLiip($path, $thumb = 'tile', $default = 'default.jpg')
{

if(strpos($path, $this->getFileManagerFolder())===false){
$path = $this->getFileManagerFolder() .'/'. $path;
}

if ($path) {

return $this->liipCacheHelper->getBrowserPath($path, $thumb);
} else {

return $this->liipCacheHelper->getBrowserPath('assets/img/frontend/'.$default, $thumb);
}
}

/**
* Retourne le chemin vers le dossier d'uploads de responsiveFilemanager
*
* @return string
*/
public function getFileManagerFolder(){
return $this->parameterBag->get('app.path.images');
}


public function getProductCategories()
{
$categories = $this->productCategoryRepository->findAllParents($this->globalParam->getCurrentMerchant()) ;

Chargement…
Annuler
Enregistrer