app/template/admin/Product/index.twig line 1

Open in your IDE?
  1. {#
  2. This file is part of EC-CUBE
  3. Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  4. http://www.ec-cube.co.jp/
  5. For the full copyright and license information, please view the LICENSE
  6. file that was distributed with this source code.
  7. #}
  8. {% extends '@admin/default_frame.twig' %}
  9. {% set menus = ['product', 'product_master'] %}
  10. {% block title %}{{ 'admin.product.product_list'|trans }}{% endblock %}
  11. {% block sub_title %}{{ 'admin.product.product_management'|trans }}{% endblock %}
  12. {% form_theme searchForm '@admin/Form/bootstrap_4_layout.html.twig' %}
  13. {% block javascript %}
  14.     <script>
  15.         $(function() {
  16.             $('#bulkDelete').on('click', function() {
  17.                 var modal = $('#bulkDeleteModal');
  18.                 // 削除中のUI変更処理
  19.                 modal.find('button').attr('disabled', 'disabled');
  20.                 $('.modal-body p', modal).text("{{ 'admin.product.permanently_delete__in_progress'|trans }}");
  21.                 $('.progress', modal).show();
  22.                 var checkedList = $('input[type=checkbox][data-delete-url]:checked');
  23.                 var totalCount = checkedList.length;
  24.                 var currentCount = 0;
  25.                 var promises = checkedList.map(function() {
  26.                     return $.ajax({
  27.                         'url': $(this).data('delete-url'),
  28.                         'type': 'delete',
  29.                         'data': {'_token': $(this).attr('token-for-anchor')}
  30.                     }).always(function() {
  31.                         $('.progress-bar', modal).css('width', (++currentCount / totalCount * 100) + '%');
  32.                     });
  33.                 });
  34.                 var addError = function(errorMessage) {
  35.                     $('<li><span class="badge bg-danger">ERROR</span> </li>')
  36.                         .append($('<span></span>').text(errorMessage))
  37.                         .appendTo('#bulkErrors');
  38.                 };
  39.                 $.when.apply($, promises)
  40.                     .done(function() {
  41.                         // 削除できなかった場合はエラーメッセージを表示
  42.                         var args = promises.length === 1 ? [arguments[0]] : [].slice.call(arguments).map(function(result) {
  43.                             return result[0];
  44.                         });
  45.                         args.filter(function(result) {
  46.                             return result.success === false;
  47.                         }).forEach(function(result) {
  48.                             addError(result.message);
  49.                         });
  50.                     })
  51.                     .fail(function() {
  52.                         // システムエラー
  53.                         addError("{{ 'admin.product.permanently_delete__system_error'|trans }}");
  54.                     })
  55.                     .always(function() {
  56.                         $('.progress', modal).hide();
  57.                         $('.modal-body p', modal).text("{{ 'admin.product.permanently_delete__complete_message'|trans }}");
  58.                         modal.find('button').removeAttr('disabled').toggle();
  59.                     })
  60.             });
  61.             $('#bulkDeleteDone').on('click', function() {
  62.                 location.reload(true);
  63.             });
  64.             toggleBtnBulk('input[id^="check_"]', '#btn_bulk');
  65.             $('input[id^="check_"]').on('change', function() {
  66.                 $('#trigger_check_all').prop('checked', false);
  67.                 toggleBtnBulk('input[id^="check_"]', '#btn_bulk');
  68.             });
  69.             $('#trigger_check_all').on('change', function() {
  70.                 var checked = $(this).prop('checked');
  71.                 if (checked) {
  72.                     $('input[id^="check_"]').prop('checked', true);
  73.                 } else {
  74.                     $('input[id^="check_"]').prop('checked', false);
  75.                 }
  76.                 toggleBtnBulk('input[id^="check_"]', '#btn_bulk');
  77.             });
  78.             $('#form_bulk').find('.action-submit').on('click', function(event) {
  79.                 event.preventDefault();
  80.                 var form = $(this).closest('form');
  81.                 if (!form.find('input:checkbox[name^="ids"]:checked').length) {
  82.                     {# TODO: should use modal instead of alert #}
  83.                     alert('please check');
  84.                     return false;
  85.                 }
  86.                 $('<input />').attr('type', 'hidden').attr('name', '{{ constant('Eccube\\Common\\Constant::TOKEN_NAME') }}')
  87.                     .val($(this).attr('token-for-anchor'))
  88.                     .appendTo(form);
  89.                 form.attr('action', $(this).data('action')).submit();
  90.                 return false;
  91.             });
  92.             var dataClass = [];
  93.             var modalClass = $('#productClassesModal');
  94.             $('form#form_bulk').on('click', 'table.table button[data-class-url]', function() {
  95.                 var btnClass = $(this);
  96.                 btnClass.attr('disabled', true);
  97.                 var productId = btnClass.data('product-id');
  98.                 if (dataClass[productId] != undefined) {
  99.                     renderClass(dataClass[productId], btnClass);
  100.                     return;
  101.                 }
  102.                 $.ajax({
  103.                     url: btnClass.data('class-load'),
  104.                     type: 'GET',
  105.                 }).done(function(data) {
  106.                     dataClass[productId] = data;
  107.                     renderClass(dataClass[productId], btnClass);
  108.                 }).fail(function() {
  109.                     alert('Failed');
  110.                 });
  111.             });
  112.             // Append html and show popup
  113.             function renderClass(data, btnClass) {
  114.                 $('div.modal-body', modalClass).html(data);
  115.                 $('h5.modal-title', modalClass).text(btnClass.data('message'));
  116.                 $('a.btn-ec-conversion', modalClass).attr('href', btnClass.data('class-url'));
  117.                 modalClass.modal('show');
  118.                 btnClass.attr('disabled', false);
  119.             }
  120.         });
  121.     </script>
  122. {% endblock javascript %}
  123. {% block main %}
  124.     <div class="c-outsideBlock">
  125.         <form id='search_form' method="post" action="{{ url('admin_product') }}">
  126.             {{ form_widget(searchForm._token) }}
  127.             <div class="c-outsideBlock__contents">
  128.                 <div class="row justify-content-start">
  129.                     <div class="col-6">
  130.                         <div class="mb-2">
  131.                             <div style="display:none;"><label class="col-form-label" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.product.multi_search_label'|trans }}">{{ 'admin.product.multi_search_label'|trans }}<i class="fa fa-question-circle fa-lg ms-1"></i></label>
  132.                             {{ form_widget(searchForm.id) }}
  133.                             {{ form_errors(searchForm.id) }}</div>
  134.                             <label class="col-form-label" data-bs-toggle="tooltip" data-bs-placement="top" title="{{ 'tooltip.product.multi_search_label'|trans }}">商品名・検索ワード・商品ID・品番<i class="fa fa-question-circle fa-lg ms-1"></i></label>
  135.                             {{ form_widget(searchForm.word) }}
  136.                             {{ form_errors(searchForm.word) }}
  137.                         </div>
  138.                         <div class="d-inline-block mb-3" data-bs-toggle="collapse" href="#searchDetail"
  139.                              aria-expanded="false" aria-controls="searchDetail"><a><i
  140.                                         class="fa fa-plus-square-o fw-bold me-1"></i><span
  141.                                         class="fw-bold">{{ 'admin.common.search_detail'|trans }}</span></a>
  142.                         </div>
  143.                     </div>
  144.                 </div>
  145.             </div>
  146.             <div class="c-subContents collapse ec-collapse{{ has_errors ? ' show' }}" id="searchDetail">
  147.                 <div class="row mb-2">
  148.                     <div class="col-6">
  149.                         <div class="row mb-2">
  150.                             <div class="col-6">
  151.                                 <label class="col-form-label">{{ 'admin.product.category'|trans }}</label>
  152.                                 {{ form_widget(searchForm.category_id) }}
  153.                                 {{ form_errors(searchForm.category_id) }}
  154.                             </div>
  155.                         </div>
  156.                         <div class="row mb-2">
  157.                             <div class="col-12">
  158.                                 <p class="col-form-label">{{ 'admin.product.display_status'|trans }}</p>
  159.                                 {{ form_widget(searchForm.status, {'label_attr': {'class': 'checkbox-inline'}}) }}
  160.                                 {{ form_errors(searchForm.status, {'label_attr': {'class': 'checkbox-inline'}}) }}
  161.                             </div>
  162.                         </div>
  163.                         <div class="row mb-2">
  164.                             <div class="col-12">
  165.                                 <p class="col-form-label">{{ 'admin.product.stock__short'|trans }}</p>
  166.                                 {{ form_widget(searchForm.stock, {'label_attr': {'class': 'checkbox-inline'}}) }}
  167.                                 {{ form_errors(searchForm.stock) }}
  168.                             </div>
  169.                         </div>
  170.                     </div>
  171.                     <div class="col-6">
  172.                         <div class="row mb-2">
  173.                             <div class="col-6">
  174.                                 <label class="col-form-label">{{ 'admin.product.tag'|trans }}</label>
  175.                                 {{ form_widget(searchForm.tag_id) }}
  176.                                 {{ form_errors(searchForm.tag_id) }}
  177.                             </div>
  178.                         </div>
  179.                         <div class="mb-2">
  180.                             <label class="col-form-label">
  181.                                 {{ 'admin.common.create_date'|trans }}
  182.                             </label>
  183.                             <div class="row align-items-center">
  184.                                 <div class="col">
  185.                                     {# TODO: カレンダー表示の調整 #}
  186.                                     {{ form_widget(searchForm.create_datetime_start) }}
  187.                                     {{ form_errors(searchForm.create_datetime_start) }}
  188.                                 </div>
  189.                                 <div class="col-auto text-center"><span>{{ 'admin.common.separator__range'|trans }}</span>
  190.                                 </div>
  191.                                 <div class="col">
  192.                                     {{ form_widget(searchForm.create_datetime_end) }}
  193.                                     {{ form_errors(searchForm.create_datetime_end) }}
  194.                                 </div>
  195.                             </div>
  196.                         </div>
  197.                         <div class="mb-2">
  198.                             <label class="col-form-label">{{ 'admin.common.update_date'|trans }}</label>
  199.                             <div class="row align-items-center">
  200.                                 <div class="col">
  201.                                     {# TODO: カレンダー表示の調整 #}
  202.                                     {{ form_widget(searchForm.update_datetime_start) }}
  203.                                     {{ form_errors(searchForm.update_datetime_start) }}
  204.                                 </div>
  205.                                 <div class="col-auto"><span>{{ 'admin.common.separator__range'|trans }}</span></div>
  206.                                 <div class="col">
  207.                                     {{ form_widget(searchForm.update_datetime_end) }}
  208.                                     {{ form_errors(searchForm.update_datetime_end) }}
  209.                                 </div>
  210.                             </div>
  211.                         </div>
  212.                     </div>
  213.                 </div>
  214.                 {# エンティティ拡張の自動出力 #}
  215.                 {% for f in searchForm|filter(f => f.vars.eccube_form_options.auto_render) %}
  216.                     {# TODO 1項目1行になるのを改善 #}
  217.                     <div class="row mb-2">
  218.                         {% if f.vars.eccube_form_options.form_theme %}
  219.                             {% form_theme f f.vars.eccube_form_options.form_theme %}
  220.                             {{ form_row(f) }}
  221.                         {% else %}
  222.                             <div class="col">
  223.                                 <div class="mb-3">
  224.                                     <label>{{ f.vars.label|trans }}</label>
  225.                                     {{ form_widget(f) }}
  226.                                     {{ form_errors(f) }}
  227.                                 </div>
  228.                             </div>
  229.                         {% endif %}
  230.                     </div>
  231.                 {% endfor %}
  232.             </div>
  233.             <div class="c-outsideBlock__contents mb-5">
  234.                 <button class="btn btn-ec-conversion px-5" type="submit">{{ 'admin.common.search'|trans }}</button>
  235.                 {% if pagination %}
  236.                     <span class="fw-bold ms-2">{{ 'admin.common.search_result'|trans({"%count%":pagination.totalItemCount})|raw }}</span>
  237.                 {% endif %}
  238.             </div>
  239.             <div class="c-outsideBlock__contents mb-5">
  240.                 {{ include('@admin/search_items.twig', { 'form': searchForm }, ignore_missing = true) }}
  241.             </div>
  242.             {{ form_widget(searchForm.sortkey, {'attr': {'class': 'js-listSort-key'}}) }}
  243.             {{ form_widget(searchForm.sorttype, {'attr': {'class': 'js-listSort-type'}}) }}
  244.         </form>
  245.     </div>
  246.     <div class="c-contentsArea__cols">
  247.         <div class="c-contentsArea__primaryCol">
  248.             <div class="c-primaryCol">
  249.                 {% if pagination and pagination.totalItemCount %}
  250.                     <form id="form_bulk" method="POST" action="">
  251.                         <div class="row justify-content-between mb-2">
  252.                             <div class="col-6">
  253.                                 <div id="btn_bulk" class="d-none">
  254.                                     <label class="me-2">{{ 'admin.common.bulk_actions'|trans }}</label>
  255.                                     <div class="btn-group me-2" role="group">
  256.                                         <button {{ csrf_token_for_anchor() }} data-action="{{ url('admin_product_bulk_product_status', {id: constant('Eccube\\Entity\\Master\\ProductStatus::DISPLAY_SHOW')}) }}" class="btn btn-ec-regular action-submit" type="button">
  257.                                             <span>{{ 'admin.product.display_status__show'|trans }}</span>
  258.                                         </button>
  259.                                         <button {{ csrf_token_for_anchor() }} data-action="{{ url('admin_product_bulk_product_status', {id: constant('Eccube\\Entity\\Master\\ProductStatus::DISPLAY_HIDE')}) }}" class="btn btn-ec-regular action-submit" type="button">
  260.                                             <span>{{ 'admin.product.display_status__hide'|trans }}</span>
  261.                                         </button>
  262.                                     </div>
  263.                                     <button {{ csrf_token_for_anchor() }} data-action="{{ url('admin_product_bulk_product_status', {id: constant('Eccube\\Entity\\Master\\ProductStatus::DISPLAY_ABOLISHED')}) }}" class="btn btn-ec-regular me-2 action-submit">
  264.                                         {{ 'admin.product.display_status__abolished'|trans }}
  265.                                     </button>
  266.                                     <button type="button" data-bs-toggle="modal" data-bs-target="#bulkDeleteModal" class="btn btn-ec-delete">{{ 'admin.product.permanently_delete'|trans }}</button>
  267.                                 </div>
  268.                             </div>
  269.                             <div class="col-5 text-end">
  270.                                 <div class="d-inline-block me-2 align-bottom">
  271.                                     <div>
  272.                                         <select class="form-select" onchange="location = this.value;">
  273.                                             {% for pageMax in pageMaxis %}
  274.                                                 <option {% if pageMax.name == page_count %}selected=""{% endif %} value="{{ path('admin_product_page', {'page_no': 1, 'page_count': pageMax.name}) }}">{{ 'admin.common.count'|trans({ '%count%': pageMax.name }) }}</option>
  275.                                             {% endfor %}
  276.                                         </select>
  277.                                     </div>
  278.                                 </div>
  279.                                 <div class="d-inline-block">
  280.                                     <div class="btn-group" role="group">
  281.                                         <a class="btn btn-ec-regular" href="{{ url('admin_product_export') }}">
  282.                                             <i class="fa fa-cloud-download me-1 text-secondary"></i><span>{{ 'admin.common.csv_download'|trans }}</span>
  283.                                         </a>
  284.                                         <a class="btn btn-ec-regular" href="{{ url('admin_setting_shop_csv', { id : constant('\\Eccube\\Entity\\Master\\CsvType::CSV_TYPE_PRODUCT') }) }}">
  285.                                             <i class="fa fa-cog me-1 text-secondary"></i><span>{{ 'admin.setting.shop.csv_setting'|trans }}</span>
  286.                                         </a>
  287.                                     </div>
  288.                                 </div>
  289.                             </div>
  290.                         </div>
  291.                         <div class="card rounded border-0 mb-4 d-block">
  292.                             <div class="card-body p-0">
  293.                                 <table class="table table-sm">
  294.                                     <thead>
  295.                                     <tr>
  296.                                         <th class="border-top-0 ps-3 pt-2 pb-2">
  297.                                             <input type="checkbox" name="filter" value="open" id="trigger_check_all">
  298.                                         </th>
  299.                                         <th class="border-top-0 pt-2 pb-2" nowrap>{{ 'admin.product.product_id__short'|trans }}<a href="#" class="js-listSort" data-sortkey="product_id"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  300.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.product.image__short'|trans }}</th>
  301.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.product.name'|trans }}<a href="#" class="js-listSort" data-sortkey="name"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  302.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.product.product_code__short'|trans }}<a href="#" class="js-listSort" data-sortkey="product_code"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  303.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.product.price'|trans }}</th>
  304.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.product.stock'|trans }}<a href="#" class="js-listSort" data-sortkey="stock"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  305.                                         <th class="border-top-0 pt-2 pb-2 text-nowrap">{{ 'admin.product.display_status__short'|trans }}<a href="#" class="js-listSort" data-sortkey="status"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  306.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.common.create_date'|trans }}<a href="#" class="js-listSort" data-sortkey="create_date"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  307.                                         <th class="border-top-0 pt-2 pb-2">{{ 'admin.common.update_date'|trans }}<a href="#" class="js-listSort" data-sortkey="update_date"><i class="fa fa-arrow-up" aria-hidden="true"></i></a></th>
  308.                                         <th class="border-top-0 pt-2 pb-2 pe-3" colspan="3"></th>
  309.                                     </tr>
  310.                                     </thead>
  311.                                     <tbody>
  312.                                     {% for Product in pagination %}
  313.                                         <tr id="ex-product-{{ Product.id }}">
  314.                                             <td class="align-middle ps-3">
  315.                                                 <input type="checkbox" name="ids[]" value="{{ Product.id }}" id="check_{{ Product.id }}" data-delete-url="{{ url('admin_product_product_delete', { id: Product.id }) }}">
  316.                                             </td>
  317.                                             <td class="align-middle">{{ Product.id }}</td>
  318.                                             {# TODO: 画像のサイズをベタ指定しているので、styleguide側を直す #}
  319.                                             <td class="align-middle">
  320.                                                 <a href="{{ url('admin_product_product_edit', { id : Product.id }) }}">
  321.                                                     <img src="{{ asset(Product.mainFileName|no_image_product, 'save_image') }}"
  322.                                                          style="max-width: 50px">
  323.                                                 </a>
  324.                                             </td>
  325.                                             <td class="align-middle"><a
  326.                                                         href="{{ url('admin_product_product_edit', { id : Product.id }) }}">{{ Product.name }}</a>
  327.                                             </td>
  328.                                             <td class="align-middle">
  329.                                                 {{ Product.code_min }}
  330.                                                 {% if Product.code_min != Product.code_max %}{{ 'admin.common.separator__range'|trans }}{{ Product.code_max }}
  331.                                                 {% endif %}
  332.                                             </td>
  333.                                             <td class="align-middle">
  334.                                                 {{ Product.price02_min|price }}
  335.                                                 {% if Product.price02_min != Product.price02_max %}{{ 'admin.common.separator__range'|trans }}{{ Product.price02_max|price }}
  336.                                                 {% endif %}
  337.                                             </td>
  338.                                             <td class="align-middle">
  339.                                                 {% if Product.hasProductClass %}
  340.                                                     <button type="button" class="btn page-link text-dark d-inline-block"
  341.                                                             data-product-id="{{ Product.id }}"
  342.                                                             data-message="{{ 'admin.product.move_to_product_class__confirm_title'|trans({'%name%': Product.name}) }}"
  343.                                                             data-class-load="{{ url('admin_product_classes_load', { 'id' : Product.id }) }}"
  344.                                                             data-class-url="{{ url('admin_product_product_class', { 'id' : Product.id, 'return_product_list' : true }) }}">
  345.                                                         {{ 'admin.product.product_class__confirm'|trans }}
  346.                                                     </button>
  347.                                                 {% else %}
  348.                                                     {# 規格なし商品 は在庫数を表示 #}
  349.                                                     {% if Product.stockunlimited_min %}
  350.                                                         {{ 'admin.product.stock_unlimited__short'|trans }}
  351.                                                     {% else %}
  352.                                                         {{ Product.stock_min }}
  353.                                                     {% endif %}
  354.                                                 {% endif %}
  355.                                             </td>
  356.                                             <td class="align-middle">
  357.                                                 {{ Product.status.name }}
  358.                                             </td>
  359.                                             <td class="align-middle">
  360.                                                 {{ Product.create_date|date_min }}
  361.                                             </td>
  362.                                             <td class="align-middle">
  363.                                                 {{ Product.update_date|date_min }}
  364.                                             </td>
  365.                                             <td class="align-middle pe-3" colspan="3">
  366.                                                 <div class="text-end">
  367.                                                     <div class="px-1 d-inline-block text-center" data-bs-toggle="tooltip"
  368.                                                          data-bs-placement="top"
  369.                                                          title="{{ 'admin.common.display'|trans }}"><a class="btn btn-ec-actionIcon"
  370.                                                                                                        href="{{ url('product_detail', {id:Product.id}) }}"
  371.                                                                                                        target="_blank"><i
  372.                                                                     class="fa fa-eye fa-lg text-secondary"
  373.                                                                     aria-hidden="true"></i></a></div>
  374.                                                     <div class="px-1 d-inline-block text-center" data-bs-toggle="tooltip"
  375.                                                          data-bs-placement="top"
  376.                                                          title="{{ 'admin.common.copy'|trans }}">
  377.                                                         <a href="#" class="btn btn-ec-actionIcon"
  378.                                                            data-bs-toggle="modal"
  379.                                                            data-bs-target="#confirmModal-{{ Product.id }}">
  380.                                                             <i class="fa fa-files-o fa-lg text-secondary"
  381.                                                                aria-hidden="true"></i></a>
  382.                                                         <div class="modal fade" id="confirmModal-{{ Product.id }}" tabindex="-1"
  383.                                                              role="dialog"
  384.                                                              aria-labelledby="confirmModal-{{ Product.id }}" aria-hidden="true">
  385.                                                             <div class="modal-dialog" role="document">
  386.                                                                 <div class="modal-content">
  387.                                                                     <div class="modal-header">
  388.                                                                         <h5 class="modal-title fw-bold">
  389.                                                                             {{ 'admin.product.copy__confirm_title'|trans }}</h5>
  390.                                                                         <button class="btn-close" type="button"
  391.                                                                                 data-bs-dismiss="modal"
  392.                                                                                 aria-label="Close">
  393.                                                                         </button>
  394.                                                                     </div>
  395.                                                                     <div class="modal-body text-start">
  396.                                                                         <p class="text-start">
  397.                                                                             {{ 'admin.product.copy__confirm_message'|trans }}</p>
  398.                                                                     </div>
  399.                                                                     <div class="modal-footer">
  400.                                                                         <button class="btn btn-ec-sub" type="button"
  401.                                                                                 data-bs-dismiss="modal">{{ 'admin.common.cancel'|trans }}
  402.                                                                         </button>
  403.                                                                         <a
  404.                                                                                 href="{{ url('admin_product_product_copy', {'id' : Product.id}) }}"
  405.                                                                                 class="btn btn-ec-conversion"
  406.                                                                                 data-confirm="false"
  407.                                                                                 {{ csrf_token_for_anchor() }}
  408.                                                                                 data-method="post">
  409.                                                                             {{ 'admin.common.copy'|trans }}
  410.                                                                         </a>
  411.                                                                     </div>
  412.                                                                 </div>
  413.                                                             </div>
  414.                                                         </div>
  415.                                                     </div>
  416.                                                 </div>
  417.                                             </td>
  418.                                         </tr>
  419.                                     {% endfor %}
  420.                                     </tbody>
  421.                                 </table>
  422.                             </div>
  423.                             {% if pagination.totalItemCount > 0 %}
  424.                                 <div class="row justify-content-md-center mb-4 pb-4">
  425.                                     {% include "@admin/pager.twig" with { 'pages' : pagination.paginationData, 'routes' : 'admin_product_page' } %}
  426.                                 </div>
  427.                             {% endif %}
  428.                         </div>
  429.                     </form>
  430.                 {% elseif has_errors %}
  431.                     <div class="card rounded border-0">
  432.                         <div class="card-body p-4">
  433.                             <div class="text-center text-muted mb-4 h5">{{ 'admin.common.search_invalid_condition'|trans }}</div>
  434.                             <div class="text-center text-muted">{{ 'admin.common.search_try_change_condition'|trans }}</div>
  435.                         </div>
  436.                     </div>
  437.                 {% else %}
  438.                     <div class="card rounded border-0">
  439.                         <div class="card-body p-4">
  440.                             <div class="text-center text-muted mb-4 h5">{{ 'admin.common.search_no_result'|trans }}</div>
  441.                             <div class="text-center text-muted">{{ 'admin.common.search_try_change_condition'|trans }}</div>
  442.                             <div class="text-center text-muted">{{ 'admin.common.search_try_advanced_search'|trans }}</div>
  443.                         </div>
  444.                     </div>
  445.                 {% endif %}
  446.             </div>
  447.             <!-- 完全に削除の確認モーダル-->
  448.             <div class="modal fade" id="bulkDeleteModal" tabindex="-1" role="dialog" aria-labelledby="discontinuance" aria-hidden="true" data-bs-keyboard="false" data-bs-backdrop="static">
  449.                 <div class="modal-dialog" role="document">
  450.                     <div class="modal-content">
  451.                         <div class="modal-header">
  452.                             <h5 class="modal-title fw-bold">{{ 'admin.product.permanently_delete__confirm_title'|trans }}</h5>
  453.                             <button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close"></button>
  454.                         </div>
  455.                         <div class="modal-body text-start">
  456.                             <p class="text-start">{{ 'admin.product.permanently_delete__confirm_message'|trans }}</p>
  457.                             <ul id="bulkErrors"></ul>
  458.                             <div class="progress" style="display: none">
  459.                                 <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
  460.                             </div>
  461.                         </div>
  462.                         <div class="modal-footer">
  463.                             <button class="btn btn-ec-sub" type="button" data-bs-dismiss="modal">{{ 'admin.common.cancel'|trans }}</button>
  464.                             <button class="btn btn-ec-delete" type="button" id="bulkDelete">{{ 'admin.product.permanently_delete' | trans }}</button>
  465.                             <button class="btn btn-ec-regular" id="bulkDeleteDone" style="display: none" type="button" data-bs-dismiss="modal">{{ 'admin.product.permanently_delete__complete'|trans }}</button>
  466.                         </div>
  467.                     </div>
  468.                 </div>
  469.             </div>
  470.         </div>
  471.     </div>
  472.     <div class="modal fade" id="productClassesModal" tabindex="-1" role="dialog" aria-labelledby="productClassesModal" aria-hidden="true">
  473.         <div class="modal-dialog">
  474.             <div class="modal-content">
  475.                 <div class="modal-header">
  476.                     <h5 class="modal-title fw-bold">{# Title #}</h5>
  477.                     <button class="btn-close" type="button" data-bs-dismiss="modal" aria-label="Close">
  478.                     </button>
  479.                 </div>
  480.                 <div class="modal-body">
  481.                     {# Append data list #}
  482.                 </div>
  483.                 <div class="modal-footer">
  484.                     <button class="btn btn-v-sub" type="button" data-bs-dismiss="modal">
  485.                         {{ 'admin.common.cancel'|trans }}
  486.                     </button>
  487.                     <a class="btn btn-ec-conversion"
  488.                        href="#">
  489.                         {{ 'admin.product.move_to_product_class'|trans }}
  490.                     </a>
  491.                 </div>
  492.             </div><!-- /.modal-content -->
  493.         </div><!-- /.modal-dialog -->
  494.     </div><!-- /#productClassesModal -->
  495. {% endblock %}