]> _ Git - fluidbook-toolbox.git/commitdiff
wip #3753 @4
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Thu, 10 Dec 2020 19:36:09 +0000 (20:36 +0100)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Thu, 10 Dec 2020 19:36:09 +0000 (20:36 +0100)
app/Http/Controllers/Admin/Operations/FluidbookQuote/ConfirmAssignmentOperation.php
app/Models/FluidbookQuote.php
app/Models/Quiz.php
app/Widgets.php
config/backpack/crud.php
public/packages/fluidbook/toolbox/css/style.less
resources/views/vendor/backpack/crud/inc/datatables_logic.blade.php [new file with mode: 0644]
resources/views/vendor/backpack/crud/list.blade.php [new file with mode: 0644]

index 0375ca45eeda6d13e3ecfa1a15a9598595f85268..cd4bed0569f2749d4d4248fa16b1c8640fbf04b7 100644 (file)
@@ -33,6 +33,7 @@ trait ConfirmAssignmentOperation
         } else {
             Alert::add('error', __('Une erreur s\'est produite.'))->flash();
         }
-        return Redirect::to('/fluidbook-quote');
+
+        return Redirect::to(session('_previous', ['url' => backpack_url('fluidbook-quote')])['url']);
     }
 }
index 0af3b07c6447b3259d09b2a587226a9b98e031a3..0c52895983e49df966ad37e0d4a469fa4a999026 100644 (file)
@@ -43,7 +43,13 @@ class FluidbookQuote extends CubistMagicAbstractModel
         $this->addField('links', 'Hidden');
         $this->addField('langs', 'Hidden');
 
-        $this->addField('user', 'SelectFromModel', __('Utilisateur'), ['optionsmodel' => User::class, 'attribute' => 'companyWithName', 'column' => true,]);
+        $this->addField('user', 'SelectFromModel', __('Utilisateur'),
+            ['optionsmodel' => User::class,
+                'attribute' => 'companyWithName',
+                'column_attribute' => 'CompanyWithNameOnTwoLines',
+                'column' => true,
+                'can_write' => 'fluidbook-quote:admin',
+            ]);
 
         $this->addField(['name' => 'created_at',
             'label' => __('Date'),
@@ -51,7 +57,8 @@ class FluidbookQuote extends CubistMagicAbstractModel
             'filter' => true,
             'column' => true,
             'column_type' => 'date',
-            'column_format' => null]);
+            'column_format' => null,
+            'can_write' => 'fluidbook-quote:admin']);
 
         $this->addField('contact_type', 'SelectFromArray', __('Type de client'), ['options' => [
             'agency' => __('Agence de communication'),
@@ -60,7 +67,10 @@ class FluidbookQuote extends CubistMagicAbstractModel
             'other' => __('Autre'),
         ]]);
 
-        $this->addField('message', 'Textarea', __('Message'));
+        $this->addField('message', 'Textarea', __('Message'), [
+                'can_write' => 'fluidbook-quote:admin'
+            ]
+        );
 
         $this->addField('gclid', 'Text', 'Google Adwords ID (gclid)', ['can' => 'fluidbook-quote:admin',]);
 
@@ -75,9 +85,9 @@ class FluidbookQuote extends CubistMagicAbstractModel
 
         $this->addField('status', 'SelectFromArray', __('Status'), ['options' => [
             0 => __('Non traitée'),
-            1 => __('En attente de traitement'),
+            1 => __('En attente'),
             2 => __('Traitée'),
-        ], 'column' => true, 'filter' => true]);
+        ], 'column' => true, 'filter' => true, 'can_write' => 'fluidbook-quote:admin']);
 
         $this->addField('conversion', 'SelectFromArray', __('Conversion'), ['options' => [
             0 => __('Pas de réponse'),
@@ -85,7 +95,7 @@ class FluidbookQuote extends CubistMagicAbstractModel
             2 => __('Devis refusé'),
             3 => __('Projet validé'),
             4 => __('Déjà client'),
-        ], 'column' => true, 'can' => 'fluidbook-quote:admin', 'filter' => true]);
+        ], 'column' => true, 'filter' => true]);
 
         $this->addField('origin_column', FluidbookQuoteOrigin::class, __('Origine'), ['column' => true, 'filter' => true]);
         $this->addField('fluidbooks', 'ModelAttribute', __('Fluidbooks'), ['column' => true, 'column_label' => '<img width="20" src="/images/icons/icon-fluidbook.svg">', 'attribute' => 'user.e1_ws_count']);
index 95e428d59baa1cd926745a8d5b09cf01fc9e9b63..5afed8393ad828e49c35b04cc289126089cea9be 100644 (file)
@@ -97,7 +97,7 @@ class Quiz extends CubistMagicAbstractModel
             'type' => User::class,
             'column' => true,
             'can' => 'toolbox:quiz:edit_ownership',
-            'attribute' => 'companyWithName',
+            'attribute' => 'companyWithNameOnTwoLines',
             'tab' => __('Projet')]);
 
         $this->addField(['name' => 'title',
index 7be3359415586a8f60fb96f973dd20aec0e1ec44..7ae3158ac0c1a0b9fc30a214aac3d29026c03b41 100644 (file)
@@ -19,7 +19,7 @@ class Widgets
                     'class' => 'alert alert-dark mb-2',
                     'heading' => __('Des demandes de devis n\'ont pas été traitées'),
                     'content' => __(':awaiting demandes de devis doivent être traitées', ['awaiting' => $nottreated]) . '. <p><a class="btn btn-primary" href="' . backpack_url('fluidbook-quote?status=0') . '">' . __('Voir toutes les demandes en attente') . '</a></p>',
-                    'close_button' => true, // show close button or not
+                    'close_button' => false, // show close button or not
                 ]);
             }
         }
@@ -31,7 +31,7 @@ class Widgets
                 'class' => 'alert alert-danger mb-2',
                 'heading' => __('Des demandes de devis sont en attente'),
                 'content' => __(':awaiting demandes de devis sont actuellement en attente', ['awaiting' => $awaiting]) . '. <p><a class="btn btn-warning" href="' . backpack_url('fluidbook-quote?status=1') . '">' . __('Voir toutes les demandes en attente') . '</a></p>',
-                'close_button' => true, // show close button or not
+                'close_button' => false, // show close button or not
             ]);
         }
     }
index bcccd1c5b5999ffaac541fa3f313577baaac0662..bedb94af80ba35eadfae2e5e45573eaa6910c0b8 100644 (file)
@@ -39,7 +39,7 @@ return [
             // How many items should be shown by default by the Datatable?
             // This value can be overwritten on a specific CRUD by calling
             // $this->crud->setDefaultPageLength(50);
-            'defaultPageLength' => 10,
+            'defaultPageLength' => 100,
 
             // A 1D array of options which will be used for both the displayed option and the value, or
             // A 2D array in which the first array is used to define the value options and the second array the displayed options
index 0621c8d39a5da03df295d2c3bbd5667419a35f15..cd4f73ca0ed8361c00357ef61cb2176c9a36191a 100644 (file)
@@ -245,3 +245,56 @@ a, a.btn-link {
 [data-fluidbook-quote-status="1"] {
     color: #a00;
 }
+
+.btn-link {
+    .la {
+        position: relative;
+        top: 4px;
+        left: -4px;
+        font-size: 180%;
+    }
+}
+
+.app-body {
+    overflow-x: visible;
+}
+
+#crudTable {
+    box-shadow: none;
+    position: relative;
+
+    thead {
+        tr {
+            background-color: #fafafa;
+        }
+    }
+
+    &.has-hidden-columns {
+        .btn-link {
+            max-width: 35px;
+            overflow: hidden;
+        }
+    }
+
+    &.test-hidden-columns {
+        .btn-link {
+            max-width: none !important;
+        }
+    }
+
+    td {
+        padding: 0.4em 0.5em 0.4em 0.3em;
+    }
+
+    th {
+        padding-left: 0.3em;
+
+    }
+
+    th, td {
+        &:first-child, &:nth-child(2), &:nth-child(3), &:last-child {
+            width: 1px;
+        }
+    }
+
+}
diff --git a/resources/views/vendor/backpack/crud/inc/datatables_logic.blade.php b/resources/views/vendor/backpack/crud/inc/datatables_logic.blade.php
new file mode 100644 (file)
index 0000000..7906ebd
--- /dev/null
@@ -0,0 +1,331 @@
+<!-- DATA TABLES SCRIPT -->
+<script type="text/javascript" src="{{ asset('packages/datatables.net/js/jquery.dataTables.min.js') }}"></script>
+<script type="text/javascript"
+        src="{{ asset('packages/datatables.net-bs4/js/dataTables.bootstrap4.min.js') }}"></script>
+<script type="text/javascript"
+        src="{{ asset('packages/datatables.net-responsive/js/dataTables.responsive.min.js') }}"></script>
+<script type="text/javascript"
+        src="{{ asset('packages/datatables.net-responsive-bs4/js/responsive.bootstrap4.min.js') }}"></script>
+<script type="text/javascript"
+        src="{{ asset('packages/datatables.net-fixedheader/js/dataTables.fixedHeader.min.js') }}"></script>
+<script type="text/javascript"
+        src="{{ asset('packages/datatables.net-fixedheader-bs4/js/fixedHeader.bootstrap4.min.js') }}"></script>
+
+<script>
+    @if ($crud->getPersistentTable())
+
+    var saved_list_url = localStorage.getItem('{{ Str::slug($crud->getRoute()) }}_list_url');
+
+    //check if saved url has any parameter or is empty after clearing filters.
+
+    if (saved_list_url && saved_list_url.indexOf('?') < 1) {
+        var saved_list_url = false;
+    } else {
+        var persistentUrl = saved_list_url + '&persistent-table=true';
+    }
+
+    var arr = window.location.href.split('?');
+    //check if url has parameters.
+    if (arr.length > 1 && arr[1] !== '') {
+        // IT HAS! Check if it is our own persistence redirect.
+        if (window.location.search.indexOf('persistent-table=true') < 1) {
+            // IF NOT: we don't want to redirect the user.
+            saved_list_url = false;
+        }
+    }
+
+    @if($crud->getPersistentTableDuration())
+    var saved_list_url_time = localStorage.getItem('{{ Str::slug($crud->getRoute()) }}_list_url_time');
+
+    if (saved_list_url_time) {
+        var $current_date = new Date();
+        var $saved_time = new Date(parseInt(saved_list_url_time));
+        $saved_time.setMinutes($saved_time.getMinutes() + {{$crud->getPersistentTableDuration()}});
+
+        //if the save time is not expired we force the filter redirection.
+        if ($saved_time > $current_date) {
+            if (saved_list_url && persistentUrl != window.location.href) {
+                window.location.href = persistentUrl;
+            }
+        } else {
+            //persistent table expired, let's not redirect the user
+            saved_list_url = false;
+        }
+    }
+
+    @endif
+    if (saved_list_url && persistentUrl != window.location.href) {
+        window.location.href = persistentUrl;
+    }
+    @endif
+
+    var crud = {
+        exportButtons: JSON.parse('{!! json_encode($crud->get('list.export_buttons')) !!}'),
+        functionsToRunOnDataTablesDrawEvent: [],
+        addFunctionToDataTablesDrawEventQueue: function (functionName) {
+            if (this.functionsToRunOnDataTablesDrawEvent.indexOf(functionName) == -1) {
+                this.functionsToRunOnDataTablesDrawEvent.push(functionName);
+            }
+        },
+        responsiveToggle: function (dt) {
+            $(dt.table().header()).find('th').toggleClass('all');
+            dt.responsive.rebuild();
+            dt.responsive.recalc();
+        },
+        executeFunctionByName: function (str, args) {
+            var arr = str.split('.');
+            var fn = window[arr[0]];
+
+            for (var i = 1; i < arr.length; i++) {
+                fn = fn[arr[i]];
+            }
+            fn.apply(window, args);
+        },
+        updateUrl: function (new_url) {
+            url_start = "{{ url($crud->route) }}";
+            url_end = new_url.replace(url_start, '');
+            url_end = url_end.replace('/search', '');
+            new_url = url_start + url_end;
+
+            window.history.pushState({}, '', new_url);
+            localStorage.setItem('{{ Str::slug($crud->getRoute()) }}_list_url', new_url);
+        },
+        dataTableConfiguration: {
+
+            @if ($crud->getResponsiveTable())
+            responsive: {
+                details: {
+                    display: $.fn.dataTable.Responsive.display.modal({
+                        header: function (row) {
+                            // show the content of the first column
+                            // as the modal header
+                            // var data = row.data();
+                            // return data[0];
+                            return '';
+                        }
+                    }),
+                    renderer: function (api, rowIdx, columns) {
+
+                        var data = $.map(columns, function (col, i) {
+                            var columnHeading = crud.table.columns().header()[col.columnIndex];
+
+                            // hide columns that have VisibleInModal false
+                            if ($(columnHeading).attr('data-visible-in-modal') == 'false') {
+                                return '';
+                            }
+
+                            return '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' +
+                                '<td style="vertical-align:top; border:none;"><strong>' + col.title.trim() + ':' + '<strong></td> ' +
+                                '<td style="padding-left:10px;padding-bottom:10px; border:none;">' + col.data + '</td>' +
+                                '</tr>';
+                        }).join('');
+
+                        return data ?
+                            $('<table class="table table-striped mb-0">').append('<tbody>' + data + '</tbody>') :
+                            false;
+                    },
+                }
+            },
+            fixedHeader: false,
+            @else
+            responsive: false,
+            scrollX: true,
+            @endif
+
+                @if ($crud->getPersistentTable())
+            stateSave: true,
+            /*
+                if developer forced field into table 'visibleInTable => true' we make sure when saving datatables state
+                that it reflects the developer decision.
+            */
+
+            stateSaveParams: function (settings, data) {
+
+                localStorage.setItem('{{ Str::slug($crud->getRoute()) }}_list_url_time', data.time);
+
+                data.columns.forEach(function (item, index) {
+                    var columnHeading = crud.table.columns().header()[index];
+                    if ($(columnHeading).attr('data-visible-in-table') == 'true') {
+                        return item.visible = true;
+                    }
+                });
+            },
+            @if($crud->getPersistentTableDuration())
+            stateLoadParams: function (settings, data) {
+                var $saved_time = new Date(data.time);
+                var $current_date = new Date();
+
+                $saved_time.setMinutes($saved_time.getMinutes() + {{$crud->getPersistentTableDuration()}});
+
+                //if the save time as expired we force datatabled to clear localStorage
+                if ($saved_time < $current_date) {
+                    if (localStorage.getItem('{{ Str::slug($crud->getRoute())}}_list_url')) {
+                        localStorage.removeItem('{{ Str::slug($crud->getRoute()) }}_list_url');
+                    }
+                    if (localStorage.getItem('{{ Str::slug($crud->getRoute())}}_list_url_time')) {
+                        localStorage.removeItem('{{ Str::slug($crud->getRoute()) }}_list_url_time');
+                    }
+                    return false;
+                }
+            },
+            @endif
+                @endif
+            autoWidth: false,
+            pageLength: {{ $crud->getDefaultPageLength() }},
+            lengthMenu: @json($crud->getPageLengthMenu()),
+            /* Disable initial sort */
+            aaSorting: [],
+            language: {
+                "emptyTable": "{{ trans('backpack::crud.emptyTable') }}",
+                "info": "{{ trans('backpack::crud.info') }}",
+                "infoEmpty": "{{ trans('backpack::crud.infoEmpty') }}",
+                "infoFiltered": "{{ trans('backpack::crud.infoFiltered') }}",
+                "infoPostFix": "{{ trans('backpack::crud.infoPostFix') }}",
+                "thousands": "{{ trans('backpack::crud.thousands') }}",
+                "lengthMenu": "{{ trans('backpack::crud.lengthMenu') }}",
+                "loadingRecords": "{{ trans('backpack::crud.loadingRecords') }}",
+                "processing": "<img src='{{ asset('packages/backpack/crud/img/ajax-loader.gif') }}' alt='{{ trans('backpack::crud.processing') }}'>",
+                "search": "_INPUT_",
+                "searchPlaceholder": "{{ trans('backpack::crud.search') }}...",
+                "zeroRecords": "{{ trans('backpack::crud.zeroRecords') }}",
+                "paginate": {
+                    "first": "{{ trans('backpack::crud.paginate.first') }}",
+                    "last": "{{ trans('backpack::crud.paginate.last') }}",
+                    "next": ">",
+                    "previous": "<"
+                },
+                "aria": {
+                    "sortAscending": "{{ trans('backpack::crud.aria.sortAscending') }}",
+                    "sortDescending": "{{ trans('backpack::crud.aria.sortDescending') }}"
+                },
+                "buttons": {
+                    "copy": "{{ trans('backpack::crud.export.copy') }}",
+                    "excel": "{{ trans('backpack::crud.export.excel') }}",
+                    "csv": "{{ trans('backpack::crud.export.csv') }}",
+                    "pdf": "{{ trans('backpack::crud.export.pdf') }}",
+                    "print": "{{ trans('backpack::crud.export.print') }}",
+                    "colvis": "{{ trans('backpack::crud.export.column_visibility') }}"
+                },
+            },
+            processing: true,
+            serverSide: true,
+            searching: @json($crud->getOperationSetting('searchableTable') ?? true),
+            ajax: {
+                "url": "{!! url($crud->route.'/search').'?'.Request::getQueryString() !!}",
+                "type": "POST"
+            },
+            dom:
+                "<'row hidden'<'col-sm-6'i><'col-sm-6 d-print-none'f>>" +
+                "<'row'<'col-sm-12'tr>>" +
+                "<'row mt-2 d-print-none '<'col-sm-12 col-md-4'l><'col-sm-0 col-md-4 text-center'B><'col-sm-12 col-md-4 'p>>",
+        }
+    }
+</script>
+
+@include('crud::inc.export_buttons')
+
+<script type="text/javascript">
+    jQuery(document).ready(function ($) {
+
+        crud.table = $("#crudTable").DataTable(crud.dataTableConfiguration);
+
+        // move search bar
+        $("#crudTable_filter").appendTo($('#datatable_search_stack'));
+        $("#crudTable_filter input").removeClass('form-control-sm');
+
+        // move "showing x out of y" info to header
+        $("#datatable_info_stack").html($('#crudTable_info')).css('display', 'inline-flex').addClass('animated fadeIn');
+
+        @if($crud->getOperationSetting('resetButton') ?? true)
+        // create the reset button
+        var crudTableResetButton = '<a href="{{url($crud->route)}}" class="ml-1" id="crudTable_reset_button">{{ trans('backpack::crud.reset') }}</a>';
+
+        $('#datatable_info_stack').append(crudTableResetButton);
+
+        // when clicking in reset button we clear the localStorage for datatables.
+        $('#crudTable_reset_button').on('click', function () {
+
+            //clear the filters
+            if (localStorage.getItem('{{ Str::slug($crud->getRoute())}}_list_url')) {
+                localStorage.removeItem('{{ Str::slug($crud->getRoute()) }}_list_url');
+            }
+            if (localStorage.getItem('{{ Str::slug($crud->getRoute())}}_list_url_time')) {
+                localStorage.removeItem('{{ Str::slug($crud->getRoute()) }}_list_url_time');
+            }
+
+            //clear the table sorting/ordering/visibility
+            if (localStorage.getItem('DataTables_crudTable_/{{ $crud->getRoute() }}')) {
+                localStorage.removeItem('DataTables_crudTable_/{{ $crud->getRoute() }}');
+            }
+        });
+        @endif
+
+        // move the bottom buttons before pagination
+        $("#bottom_buttons").insertBefore($('#crudTable_wrapper .row:last-child'));
+
+        // override ajax error message
+        $.fn.dataTable.ext.errMode = 'none';
+        $('#crudTable').on('error.dt', function (e, settings, techNote, message) {
+            new Noty({
+                type: "error",
+                text: "<strong>{{ trans('backpack::crud.ajax_error_title') }}</strong><br>{{ trans('backpack::crud.ajax_error_text') }}"
+            }).show();
+        });
+
+        // make sure AJAX requests include XSRF token
+        $.ajaxPrefilter(function (options, originalOptions, xhr) {
+            var token = $('meta[name="csrf_token"]').attr('content');
+
+            if (token) {
+                return xhr.setRequestHeader('X-XSRF-TOKEN', token);
+            }
+        });
+
+        // on DataTable draw event run all functions in the queue
+        // (eg. delete and details_row buttons add functions to this queue)
+        $('#crudTable').on('draw.dt', function () {
+            crud.functionsToRunOnDataTablesDrawEvent.forEach(function (functionName) {
+                crud.executeFunctionByName(functionName);
+            });
+        }).dataTable();
+
+        // when datatables-colvis (column visibility) is toggled
+        // rebuild the datatable using the datatable-responsive plugin
+        $('#crudTable').on('column-visibility.dt', function (event) {
+            crud.table.responsive.rebuild();
+        }).dataTable();
+
+        @if ($crud->getResponsiveTable())
+        // when columns are hidden by reponsive plugin,
+        // the table should have the has-hidden-columns class
+        crud.table.on('responsive-resize', function (e, datatable, columns) {
+            if (crud.table.responsive.hasHidden()) {
+                $("#crudTable").addClass('has-hidden-columns');
+                crud.table.responsive.recalc();
+            }
+        });
+        @else
+        // make sure the column headings have the same width as the actual columns
+        // after the user manually resizes the window
+        var resizeTimer;
+
+        function resizeCrudTableColumnWidths() {
+            clearTimeout(resizeTimer);
+            resizeTimer = setTimeout(function () {
+                // Run code here, resizing has "stopped"
+                crud.table.columns.adjust();
+            }, 250);
+        }
+
+        $(window).on('resize', function (e) {
+            resizeCrudTableColumnWidths();
+        });
+        $('.sidebar-toggler').click(function () {
+            resizeCrudTableColumnWidths();
+        });
+        @endif
+
+    });
+</script>
+
+@include('crud::inc.details_row_logic')
diff --git a/resources/views/vendor/backpack/crud/list.blade.php b/resources/views/vendor/backpack/crud/list.blade.php
new file mode 100644 (file)
index 0000000..3662fd9
--- /dev/null
@@ -0,0 +1,173 @@
+@extends(backpack_view('blank'))
+
+@php
+    $defaultBreadcrumbs = [
+      trans('backpack::crud.admin') => url(config('backpack.base.route_prefix'), 'dashboard'),
+      $crud->entity_name_plural => url($crud->route),
+      trans('backpack::crud.list') => false,
+    ];
+
+    // if breadcrumbs aren't defined in the CrudController, use the default breadcrumbs
+    $breadcrumbs = $breadcrumbs ?? $defaultBreadcrumbs;
+@endphp
+
+@section('header')
+    <div class="container-fluid">
+        <h2>
+            <span class="text-capitalize">{!! $crud->getHeading() ?? $crud->entity_name_plural !!}</span>
+            <small id="datatable_info_stack">{!! $crud->getSubheading() ?? '' !!}</small>
+        </h2>
+    </div>
+@endsection
+
+@section('content')
+    <!-- Default box -->
+    <div class="row">
+
+        <!-- THE ACTUAL CONTENT -->
+        <div class="{{ $crud->getListContentClass() }}">
+
+            <div class="row mb-0">
+                <div class="col-sm-6">
+                    @if ( $crud->buttons()->where('stack', 'top')->count() ||  $crud->exportButtons())
+                        <div class="d-print-none {{ $crud->hasAccess('create')?'with-border':'' }}">
+
+                            @include('crud::inc.button_stack', ['stack' => 'top'])
+
+                        </div>
+                    @endif
+                </div>
+                <div class="col-sm-6">
+                    <div id="datatable_search_stack" class="mt-sm-0 mt-2 d-print-none"></div>
+                </div>
+            </div>
+
+            {{-- Backpack List Filters --}}
+            @if ($crud->filtersEnabled())
+                @include('crud::inc.filters_navbar')
+            @endif
+
+            <table id="crudTable"
+                   class="bg-white table table-striped table-hover nowrap rounded shadow-xs border-xs mt-2"
+                   cellspacing="0">
+                <thead>
+                <tr>
+                    {{-- Table columns --}}
+                    @foreach ($crud->columns() as $column)
+                        <th data-column-name="{{$column['name']}}"
+                            data-column-type="{{$column['type']}}"
+                            data-orderable="{{ var_export($column['orderable'], true) }}"
+                            data-priority="{{ $column['priority'] }}"
+                            {{--
+
+                               data-visible-in-table => if developer forced field in table with 'visibleInTable => true'
+                               data-visible => regular visibility of the field
+                               data-can-be-visible-in-table => prevents the column to be loaded into the table (export-only)
+                               data-visible-in-modal => if column apears on responsive modal
+                               data-visible-in-export => if this field is exportable
+                               data-force-export => force export even if field are hidden
+
+                           --}}
+
+                            {{-- If it is an export field only, we are done. --}}
+                            @if(isset($column['exportOnlyField']) && $column['exportOnlyField'] === true)
+                            data-visible="false"
+                            data-visible-in-table="false"
+                            data-can-be-visible-in-table="false"
+                            data-visible-in-modal="false"
+                            data-visible-in-export="true"
+                            data-force-export="true"
+                            @else
+                            data-visible-in-table="{{var_export($column['visibleInTable'] ?? false)}}"
+                            data-visible="{{var_export($column['visibleInTable'] ?? true)}}"
+                            data-can-be-visible-in-table="true"
+                            data-visible-in-modal="{{var_export($column['visibleInModal'] ?? true)}}"
+                            @if(isset($column['visibleInExport']))
+                            @if($column['visibleInExport'] === false)
+                            data-visible-in-export="false"
+                            data-force-export="false"
+                            @else
+                            data-visible-in-export="true"
+                            data-force-export="true"
+                            @endif
+                            @else
+                            data-visible-in-export="true"
+                            data-force-export="false"
+                            @endif
+                            @endif
+                        >
+                            {!! $column['label'] !!}
+                        </th>
+                    @endforeach
+
+                    @if ( $crud->buttons()->where('stack', 'line')->count() )
+                        <th data-column-type="actions"
+                            data-orderable="false"
+                            data-priority="{{ $crud->getActionsColumnPriority() }}"
+                            data-visible-in-export="false"
+                        >{{ trans('backpack::crud.actions') }}</th>
+                    @endif
+                </tr>
+                </thead>
+                <tbody>
+                </tbody>
+                <tfoot>
+                <tr>
+                    {{-- Table columns --}}
+                    @foreach ($crud->columns() as $column)
+                        <th>{!! $column['label'] !!}</th>
+                    @endforeach
+
+                    @if ( $crud->buttons()->where('stack', 'line')->count() )
+                        <th>{{ trans('backpack::crud.actions') }}</th>
+                    @endif
+                </tr>
+                </tfoot>
+            </table>
+
+            @if ( $crud->buttons()->where('stack', 'bottom')->count() )
+                <div id="bottom_buttons" class="d-print-none text-center text-sm-left">
+                    @include('crud::inc.button_stack', ['stack' => 'bottom'])
+
+                    <div id="datatable_button_stack" class="float-right text-right hidden-xs"></div>
+                </div>
+            @endif
+
+        </div>
+
+    </div>
+
+@endsection
+
+@section('after_styles')
+    <!-- DATA TABLES -->
+    <link rel="stylesheet" type="text/css"
+          href="{{ asset('packages/datatables.net-bs4/css/dataTables.bootstrap4.min.css') }}">
+    <link rel="stylesheet" type="text/css"
+          href="{{ asset('packages/datatables.net-fixedheader-bs4/css/fixedHeader.bootstrap4.min.css') }}">
+    <link rel="stylesheet" type="text/css"
+          href="{{ asset('packages/datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css') }}">
+
+    <link rel="stylesheet"
+          href="{{ asset('packages/backpack/crud/css/crud.css').'?v='.config('backpack.base.cachebusting_string') }}">
+    <link rel="stylesheet"
+          href="{{ asset('packages/backpack/crud/css/form.css').'?v='.config('backpack.base.cachebusting_string') }}">
+    <link rel="stylesheet"
+          href="{{ asset('packages/backpack/crud/css/list.css').'?v='.config('backpack.base.cachebusting_string') }}">
+
+    <!-- CRUD LIST CONTENT - crud_list_styles stack -->
+    @stack('crud_list_styles')
+@endsection
+
+@section('after_scripts')
+    @include('crud::inc.datatables_logic')
+    <script
+        src="{{ asset('packages/backpack/crud/js/crud.js').'?v='.config('backpack.base.cachebusting_string') }}"></script>
+    <script
+        src="{{ asset('packages/backpack/crud/js/form.js').'?v='.config('backpack.base.cachebusting_string') }}"></script>
+    <script
+        src="{{ asset('packages/backpack/crud/js/list.js').'?v='.config('backpack.base.cachebusting_string') }}"></script>
+
+    <!-- CRUD LIST CONTENT - crud_list_scripts stack -->
+    @stack('crud_list_scripts')
+@endsection