├── .github └── workflows │ └── tests.yml ├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── config └── filament-export.php ├── phpunit.xml ├── resources ├── css │ └── filament-export.css ├── js │ └── filament-export.js ├── lang │ ├── ar │ │ ├── export_action.php │ │ └── table_view.php │ ├── de │ │ ├── export_action.php │ │ └── table_view.php │ ├── en │ │ ├── export_action.php │ │ └── table_view.php │ ├── es │ │ ├── export_action.php │ │ └── table_view.php │ ├── fr │ │ ├── export_action.php │ │ └── table_view.php │ ├── id │ │ ├── export_action.php │ │ └── table_view.php │ ├── it │ │ ├── export_action.php │ │ └── table_view.php │ ├── ku │ │ ├── export_action.php │ │ └── table_view.php │ ├── nl │ │ ├── export_action.php │ │ └── table_view.php │ ├── pt_BR │ │ ├── export_action.php │ │ └── table_view.php │ └── tr │ │ ├── export_action.php │ │ └── table_view.php └── views │ ├── components │ └── table_view.blade.php │ ├── pdf.blade.php │ └── print.blade.php ├── src ├── Actions │ ├── Concerns │ │ ├── CanDisableAdditionalColumns.php │ │ ├── CanDisableFileName.php │ │ ├── CanDisableFileNamePrefix.php │ │ ├── CanDisableFilterColumns.php │ │ ├── CanDisableFormats.php │ │ ├── CanDisablePreview.php │ │ ├── CanDisableTableColumns.php │ │ ├── CanDownloadDirect.php │ │ ├── CanFormatStates.php │ │ ├── CanHaveExtraColumns.php │ │ ├── CanHaveExtraViewData.php │ │ ├── CanModifyWriters.php │ │ ├── CanRefreshTable.php │ │ ├── CanShowHiddenColumns.php │ │ ├── CanUseSnappy.php │ │ ├── HasAdditionalColumnsField.php │ │ ├── HasCsvDelimiter.php │ │ ├── HasDefaultFormat.php │ │ ├── HasDefaultPageOrientation.php │ │ ├── HasExportModelActions.php │ │ ├── HasFileName.php │ │ ├── HasFileNameField.php │ │ ├── HasFilterColumnsField.php │ │ ├── HasFormatField.php │ │ ├── HasPageOrientationField.php │ │ ├── HasPaginator.php │ │ ├── HasRecords.php │ │ ├── HasTimeFormat.php │ │ └── HasUniqueActionId.php │ ├── FilamentExportBulkAction.php │ └── FilamentExportHeaderAction.php ├── Components │ ├── Concerns │ │ ├── HasAction.php │ │ ├── HasRecords.php │ │ └── HasUniqueActionId.php │ └── TableView.php ├── Concerns │ ├── CanDisableTableColumns.php │ ├── CanFilterColumns.php │ ├── CanFormatStates.php │ ├── CanHaveAdditionalColumns.php │ ├── CanHaveExtraColumns.php │ ├── CanHaveExtraViewData.php │ ├── CanModifyWriters.php │ ├── CanShowHiddenColumns.php │ ├── CanUseSnappy.php │ ├── HasCsvDelimiter.php │ ├── HasData.php │ ├── HasFileName.php │ ├── HasFormat.php │ ├── HasPageOrientation.php │ ├── HasPaginator.php │ └── HasTable.php ├── FilamentExport.php └── FilamentExportServiceProvider.php └── tests ├── Pest.php ├── database ├── factories │ ├── PostFactory.php │ └── UserFactory.php └── migrations │ ├── create_posts_table.php │ └── create_users_table.php ├── routes └── web.php └── src ├── ExportTest.php ├── Filament └── Resources │ ├── PostResource.php │ ├── PostResource │ └── Pages │ │ ├── CreatePost.php │ │ ├── EditPost.php │ │ ├── ListPosts.php │ │ └── ViewPost.php │ ├── UserResource.php │ └── UserResource │ ├── Pages │ ├── CreateUser.php │ ├── EditUser.php │ ├── ListUsers.php │ └── ViewUser.php │ └── RelationManagers │ └── PostsRelationManager.php ├── Models ├── Post.php └── User.php └── TestCase.php /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: ["push"] 3 | 4 | jobs: 5 | laravel-tests: 6 | runs-on: ubuntu-latest 7 | 8 | strategy: 9 | matrix: 10 | operating-system: [ubuntu-latest] 11 | php-versions: ["8.1"] 12 | 13 | name: P${{ matrix.php-versions }} - L${{ matrix.laravel }} - ${{ matrix.operating-system}} 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Install PHP versions 18 | uses: shivammathur/setup-php@v2 19 | with: 20 | php-version: ${{ matrix.php-versions }} 21 | - name: Install Dependencies 22 | run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --ignore-platform-reqs 23 | 24 | - name: Show dir 25 | run: pwd 26 | - name: PHP Version 27 | run: php --version 28 | 29 | - name: Execute tests via PestPHP 30 | env: 31 | SESSION_DRIVER: array 32 | run: vendor/bin/pest 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | .phpunit.result.cache 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Filament Export 2 | 3 | Customizable export and print functionality for Filament Admin Panel. 4 | 5 | This package provides a bulk action and header action to export your filament tables easily. 6 | 7 | ![filament-export-3](https://user-images.githubusercontent.com/83382417/179013026-14ddd872-fedc-45d2-954a-1447005777bb.png) 8 | 9 | ## Requirements 10 | - PHP 8 11 | - [Filament 2.0](https://github.com/laravel-filament/filament) 12 | 13 | ### Dependencies 14 | - [spatie/simple-excel](https://github.com/spatie/simple-excel) 15 | - [barryvdh/laravel-dompdf](https://github.com/barryvdh/laravel-dompdf) 16 | 17 | ## Installation 18 | 19 | ```bash 20 | composer require alperenersoy/filament-export 21 | ``` 22 | 23 | ### Configuring for Standalone Table Builder (Experimental) 24 | 25 | To use this package in a standalone table builder instead of Filament Admin Panel you need to follow these steps. Otherwise, some features such as print and preview may not work properly. 26 | 27 | 1. Import `filament-export.css` in your `/resources/app.css` 28 | 29 | ```css 30 | @import '../../vendor/alperenersoy/filament-export/resources/css/filament-export.css'; 31 | ``` 32 | 33 | 2. Import `filament-export.js` in your `/resources/app.js` 34 | 35 | ```js 36 | import '../../vendor/alperenersoy/filament-export/resources/js/filament-export.js'; 37 | ``` 38 | 39 | 3. Compile your assets 40 | 41 | ```bash 42 | npm run dev 43 | ``` 44 | 45 | ## Using 46 | 47 | ### Simple Usage 48 | 49 | #### Bulk Action 50 | 51 | You can export selected rows with the bulk action. 52 | 53 | **Filament Admin Panel** 54 | 55 | ```php 56 | $table->bulkActions([ 57 | ... 58 | FilamentExportBulkAction::make('export') 59 | ... 60 | ]); 61 | ``` 62 | 63 | **Filament Table Builder** 64 | 65 | ```php 66 | protected function getTableBulkActions(): array 67 | { 68 | return [ 69 | ... 70 | FilamentExportBulkAction::make('Export'), 71 | ... 72 | ]; 73 | } 74 | ``` 75 | 76 | #### Header Action 77 | 78 | You can filter, search, sort and export your table with the header action. 79 | 80 | **Filament Admin Panel** 81 | 82 | ```php 83 | $table->headerActions([ 84 | ... 85 | FilamentExportHeaderAction::make('export') 86 | ... 87 | ]); 88 | ``` 89 | 90 | **Filament Table Builder** 91 | 92 | ```php 93 | protected function getTableHeaderActions(): array 94 | { 95 | return [ 96 | ... 97 | FilamentExportHeaderAction::make('Export'), 98 | ... 99 | ]; 100 | } 101 | ``` 102 | 103 | Since ButtonAction is deprecated you may use this action with ->button() instead. 104 | 105 | ### Full Usage 106 | 107 | Both actions provide functions for configuration. 108 | 109 | ```php 110 | FilamentExportBulkAction::make('export') 111 | ->fileName('My File') // Default file name 112 | ->timeFormat('m y d') // Default time format for naming exports 113 | ->disablePdf() // Disable PDF format for download 114 | ->disableXlsx() // Disable XLSX format for download 115 | ->disableCsv() // Disable CSV format for download 116 | ->defaultFormat('pdf') // xlsx, csv or pdf 117 | ->defaultPageOrientation('landscape') // Page orientation for pdf files. portrait or landscape 118 | ->directDownload() // Download directly without showing modal 119 | ->disableAdditionalColumns() // Disable additional columns input 120 | ->disableFilterColumns() // Disable filter columns input 121 | ->disableFileName() // Disable file name input 122 | ->disableFileNamePrefix() // Disable file name prefix 123 | ->disablePreview() // Disable export preview 124 | ->disableTableColumns() // Disable table columns in the export 125 | ->withHiddenColumns() //Show the columns which are toggled hidden 126 | ->fileNameFieldLabel('File Name') // Label for file name input 127 | ->formatFieldLabel('Format') // Label for format input 128 | ->pageOrientationFieldLabel('Page Orientation') // Label for page orientation input 129 | ->filterColumnsFieldLabel('filter columns') // Label for filter columns input 130 | ->additionalColumnsFieldLabel('Additional Columns') // Label for additional columns input 131 | ->additionalColumnsTitleFieldLabel('Title') // Label for additional columns' title input 132 | ->additionalColumnsDefaultValueFieldLabel('Default Value') // Label for additional columns' default value input 133 | ->additionalColumnsAddButtonLabel('Add Column') // Label for additional columns' add button 134 | ->withColumns([TextColumn::make('additionalModelColumn')]) // Export additional model columns that aren't visible in the table results 135 | ->csvDelimiter(',') // Delimiter for csv files 136 | ->modifyExcelWriter(fn (SimpleExcelWriter $writer) => $writer->nameCurrentSheet('Sheet')) // Modify SimpleExcelWriter before download 137 | ->modifyPdfWriter(fn (\Barryvdh\DomPDF\PDF|\Barryvdh\Snappy\PdfWrapper $writer) => $writer->setPaper('a4', 'landscape')) // Modify DomPdf or Snappy writer before download 138 | ->formatStates([ 139 | 'name' => fn (?Model $record) => strtoupper($record->name), 140 | ]) // Manually format states for a specific column 141 | ``` 142 | You can also use default bulk action and header action functions to customize actions. 143 | 144 | ## Performance Tips for Large Datasets 145 | - Since header action does server-side pagination you may choose header action over bulk action. 146 | - You may disable preview. 147 | - You may enable direct download. 148 | 149 | ## Configuration 150 | 151 | Publish configuration 152 | 153 | ```bash 154 | php artisan vendor:publish --provider="AlperenErsoy\FilamentExport\FilamentExportServiceProvider" --tag="config" 155 | ``` 156 | 157 | You can configure these settings: 158 | 159 | ```php 160 | return [ 161 | 'default_format' => 'xlsx', 162 | 'time_format' => 'M_d_Y-H_i', 163 | 'default_page_orientation' => 'portrait', 164 | 'disable_additional_columns' => false, 165 | 'disable_filter_columns' => false, 166 | 'disable_file_name' => false, 167 | 'disable_preview' => false, 168 | 'use_snappy' => false, 169 | 'action_icon' => 'heroicon-o-document-download', 170 | 'preview_icon' => 'heroicon-o-eye', 171 | 'export_icon' => 'heroicon-o-download', 172 | 'print_icon' => 'heroicon-o-printer', 173 | 'cancel_icon' => 'heroicon-o-x-circle' 174 | ]; 175 | ``` 176 | 177 | ## Overriding Views 178 | 179 | Publish views 180 | 181 | ```bash 182 | php artisan vendor:publish --provider="AlperenErsoy\FilamentExport\FilamentExportServiceProvider" --tag="views" 183 | ``` 184 | 185 | This package has two views: 186 | 187 | 1. "components\table_view.blade.php" view is used for preview. 188 | 189 | 2. "pdf.blade.php" view is used as pdf export template. 190 | 191 | 3. "print.blade.php" view is used as print template. 192 | 193 | ### Using Custom Variables In Templates 194 | 195 | ```php 196 | FilamentExportBulkAction::make('export') 197 | ->extraViewData([ 198 | 'myVariable' => 'My Variable' 199 | ]) 200 | ``` 201 | 202 | or use closures 203 | 204 | ```php 205 | FilamentExportHeaderAction::make('export') 206 | ->extraViewData(fn ($action) => [ 207 | 'recordCount' => $action->getRecords()->count() 208 | ]) 209 | ``` 210 | 211 | Then use them in the templates as regular blade variables: 212 | 213 | ```blade 214 | {{ $myVariable }} 215 | ``` 216 | 217 | ## Using Snappy 218 | 219 | By default, this package uses [dompdf](https://github.com/barryvdh/laravel-dompdf) as pdf generator. 220 | 221 | If you want to use Snappy instead you need to install **barryvdh/laravel-snappy** to your project and configure it yourself. (See [barryvdh/laravel-snappy](https://github.com/barryvdh/laravel-snappy) for more information.) 222 | 223 | To use snappy for PDF exports: 224 | 225 | 1. You can simply add ->snappy() to your actions. 226 | 227 | ```php 228 | FilamentExportBulkAction::make('export') 229 | ->snappy() 230 | ``` 231 | or 232 | ```php 233 | FilamentExportHeaderAction::make('export') 234 | ->snappy() 235 | ``` 236 | 2. You can update the config file to use it as default. 237 | ```php 238 | [ 239 | ... 240 | 'use_snappy' => true, 241 | ... 242 | ] 243 | ``` 244 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alperenersoy/filament-export", 3 | "description": "Customizable export and print functionality for Filament Admin Panel", 4 | "autoload": { 5 | "psr-4": { 6 | "AlperenErsoy\\FilamentExport\\": "src/" 7 | } 8 | }, 9 | "autoload-dev": { 10 | "psr-4": { 11 | "AlperenErsoy\\FilamentExport\\Tests\\": "tests/src/", 12 | "AlperenErsoy\\FilamentExport\\Tests\\Database\\Factories\\": "tests/database/factories/" 13 | } 14 | }, 15 | "authors": [ 16 | { 17 | "name": "alperen ersoy", 18 | "email": "ersoyalperen@gmail.com" 19 | } 20 | ], 21 | "require": { 22 | "php": "^8.0", 23 | "filament/tables": "^2.0", 24 | "barryvdh/laravel-dompdf": "^2.0", 25 | "spatie/simple-excel": "^3.0 >=3.2.0" 26 | }, 27 | "require-dev": { 28 | "orchestra/testbench": "^7.6", 29 | "pestphp/pest": "^1.21", 30 | "pestphp/pest-plugin-livewire": "^1.0", 31 | "filament/filament": "^2.0" 32 | }, 33 | "extra": { 34 | "laravel": { 35 | "providers": [ 36 | "AlperenErsoy\\FilamentExport\\FilamentExportServiceProvider" 37 | ] 38 | } 39 | }, 40 | "license": "MIT", 41 | "config": { 42 | "allow-plugins": { 43 | "pestphp/pest-plugin": true 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /config/filament-export.php: -------------------------------------------------------------------------------- 1 | 'xlsx', 5 | 'time_format' => 'M_d_Y-H_i', 6 | 'default_page_orientation' => 'portrait', 7 | 'disable_additional_columns' => false, 8 | 'disable_filter_columns' => false, 9 | 'disable_file_name' => false, 10 | 'disable_file_name_prefix' => false, 11 | 'disable_preview' => false, 12 | 'use_snappy' => false, 13 | 'action_icon' => 'heroicon-o-document-download', 14 | 'preview_icon' => 'heroicon-o-eye', 15 | 'export_icon' => 'heroicon-o-download', 16 | 'print_icon' => 'heroicon-o-printer', 17 | 'cancel_icon' => 'heroicon-o-x-circle', 18 | ]; 19 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/src 6 | 7 | 8 | 9 | 10 | ./src 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /resources/css/filament-export.css: -------------------------------------------------------------------------------- 1 | .preview-table { 2 | background: white; 3 | color: black; 4 | width: 100%; 5 | border-collapse: collapse; 6 | border-spacing: 0; 7 | } 8 | 9 | .preview-table td, 10 | .preview-table th { 11 | border-color: #ededed; 12 | border-style: solid; 13 | border-width: 1px; 14 | font-size: 13px; 15 | line-height: 2; 16 | overflow: hidden; 17 | padding-left: 6px; 18 | word-break: normal; 19 | } 20 | 21 | .preview-table th { 22 | font-weight: normal; 23 | } 24 | 25 | .preview-table-wrapper { 26 | max-height: min(500px, 80vh); 27 | overflow-y: auto; 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /resources/js/filament-export.js: -------------------------------------------------------------------------------- 1 | function onElementRemoved(element, callback) { 2 | new MutationObserver(function (mutations) { 3 | if (!document.body.contains(element)) { 4 | callback(); 5 | this.disconnect(); 6 | } 7 | }).observe(element.parentElement, { childList: true }); 8 | } 9 | 10 | function triggerInputEvent(statePath, value) { 11 | let input = document.getElementById(statePath); 12 | input.value = value; 13 | input.dispatchEvent(new Event('input', { bubbles: true })); 14 | } 15 | 16 | function printHTML(html, statePath, uniqueActionId) { 17 | let iframe = document.createElement("iframe"); 18 | 19 | let random = Math.floor(Math.random() * 99999); 20 | 21 | iframe.id = `print-${random}`; 22 | 23 | iframe.srcdoc = html; 24 | 25 | document.body.append(iframe); 26 | 27 | onElementRemoved(iframe, () => triggerInputEvent(statePath, `afterprint-${uniqueActionId}`)); 28 | 29 | iframe.contentWindow.onafterprint = () => document.getElementById(iframe.id).remove(); 30 | 31 | iframe.contentWindow.onload = () => iframe.contentWindow.print(); 32 | } 33 | 34 | window.triggerInputEvent = triggerInputEvent; 35 | 36 | window.printHTML = printHTML; -------------------------------------------------------------------------------- /resources/lang/ar/export_action.php: -------------------------------------------------------------------------------- 1 | 'تصدير', 5 | 'modal_heading' => 'تصدير', 6 | 'file_name_field_label' => 'أسم الملف', 7 | 'format_field_label' => 'التنسيق', 8 | 'page_orientation_field_label' => 'إتجاه الصفحة', 9 | 'filter_columns_field_label' => 'تصفية الأعمدة', 10 | 'additional_columns_field' => [ 11 | 'label' => 'أعمدة إضافية', 12 | 'title_field_label' => 'العنوان', 13 | 'default_value_field_label' => 'القيمة الإفتراضية', 14 | 'add_button_label' => 'إضافة عمود', 15 | ], 16 | 'export_action_label' => 'تصدير', 17 | 'print_action_label' => 'طباعة', 18 | 'preview_action_label' => 'معاينة', 19 | 'cancel_action_label' => 'إلغاء', 20 | 'page_orientation_portrait' => 'عمودي', 21 | 'page_orientation_landscape' => 'أفقي', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/ar/table_view.php: -------------------------------------------------------------------------------- 1 | 'معاينة', 5 | 'print_action_label' => 'طباعة', 6 | 'export_action_label' => 'تصدير', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/de/export_action.php: -------------------------------------------------------------------------------- 1 | 'Exportieren', 5 | 'modal_heading' => 'Exportieren', 6 | 'file_name_field_label' => 'Dateiname', 7 | 'format_field_label' => 'Format', 8 | 'page_orientation_field_label' => 'Seitenorientierung', 9 | 'filter_columns_field_label' => 'Spalten für Filterung', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Zusätzliche Spalten', 12 | 'title_field_label' => 'Titel', 13 | 'default_value_field_label' => 'Standardwert', 14 | 'add_button_label' => 'Spalte hinzufügen', 15 | ], 16 | 'export_action_label' => 'Exportieren', 17 | 'print_action_label' => 'Drucken', 18 | 'preview_action_label' => 'Vorschau', 19 | 'cancel_action_label' => 'Abbrechen', 20 | 'page_orientation_portrait' => 'Hochformat', 21 | 'page_orientation_landscape' => 'Querformat', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/de/table_view.php: -------------------------------------------------------------------------------- 1 | 'Vorschau', 5 | 'print_action_label' => 'Drucken', 6 | 'export_action_label' => 'Exportieren', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/en/export_action.php: -------------------------------------------------------------------------------- 1 | 'Export', 5 | 'modal_heading' => 'Export', 6 | 'file_name_field_label' => 'File Name', 7 | 'format_field_label' => 'Format', 8 | 'page_orientation_field_label' => 'Page Orientation', 9 | 'filter_columns_field_label' => 'Filter Columns', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Additional Columns', 12 | 'title_field_label' => 'Title', 13 | 'default_value_field_label' => 'Default Value', 14 | 'add_button_label' => 'Add Column', 15 | ], 16 | 'export_action_label' => 'Export', 17 | 'print_action_label' => 'Print', 18 | 'preview_action_label' => 'Preview', 19 | 'cancel_action_label' => 'Cancel', 20 | 'page_orientation_portrait' => 'Portrait', 21 | 'page_orientation_landscape' => 'Landscape', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/en/table_view.php: -------------------------------------------------------------------------------- 1 | 'Preview', 5 | 'print_action_label' => 'Print', 6 | 'export_action_label' => 'Export', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/es/export_action.php: -------------------------------------------------------------------------------- 1 | 'Exportar', 5 | 'modal_heading' => 'Exportar', 6 | 'file_name_field_label' => 'Nombre del archivo', 7 | 'format_field_label' => 'Formato', 8 | 'page_orientation_field_label' => 'orientación de la página', 9 | 'filter_columns_field_label' => 'Filtrar columnas', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Columnas adicionales', 12 | 'title_field_label' => 'Título', 13 | 'default_value_field_label' => 'Valor predeterminado', 14 | 'add_button_label' => 'Agregar columna', 15 | ], 16 | 'export_action_label' => 'Exportar', 17 | 'print_action_label' => 'Imprimir', 18 | 'preview_action_label' => 'Vista previa', 19 | 'cancel_action_label' => 'Cancelar', 20 | 'page_orientation_portrait' => 'Vertical', 21 | 'page_orientation_landscape' => 'Horizontal', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/es/table_view.php: -------------------------------------------------------------------------------- 1 | 'Vista previa', 5 | 'print_action_label' => 'Imprimir', 6 | 'export_action_label' => 'Exportar', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/fr/export_action.php: -------------------------------------------------------------------------------- 1 | 'Exporter', 5 | 'modal_heading' => 'Exporter', 6 | 'file_name_field_label' => 'Nom du fichier', 7 | 'format_field_label' => 'Format', 8 | 'page_orientation_field_label' => 'Orientation de la page', 9 | 'filter_columns_field_label' => 'Filtrer les colonnes', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Colonnes supplémentaires', 12 | 'title_field_label' => 'Titre', 13 | 'default_value_field_label' => 'Valeur par défaut', 14 | 'add_button_label' => 'Ajouter une colonne', 15 | ], 16 | 'export_action_label' => 'Exporter', 17 | 'print_action_label' => 'Imprimer', 18 | 'preview_action_label' => 'Prévisualisation', 19 | 'cancel_action_label' => 'Annuler', 20 | 'page_orientation_portrait' => 'Portrait', 21 | 'page_orientation_landscape' => 'Paysage', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/fr/table_view.php: -------------------------------------------------------------------------------- 1 | 'Prévisualisation', 5 | 'print_action_label' => 'Imprimer', 6 | 'export_action_label' => 'Exporter', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/id/export_action.php: -------------------------------------------------------------------------------- 1 | 'Ekspor', 5 | 'modal_heading' => 'Ekspor', 6 | 'file_name_field_label' => 'Nama File', 7 | 'format_field_label' => 'Format', 8 | 'page_orientation_field_label' => 'Orientasi Halaman', 9 | 'filter_columns_field_label' => 'Filter Kolom', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Kolom Tambahan', 12 | 'title_field_label' => 'Judul', 13 | 'default_value_field_label' => 'Nilai Bawaan', 14 | 'add_button_label' => 'Tambah Kolom', 15 | ], 16 | 'export_action_label' => 'Ekspor', 17 | 'print_action_label' => 'Cetak', 18 | 'preview_action_label' => 'Pratinjau', 19 | 'cancel_action_label' => 'Batal', 20 | 'page_orientation_portrait' => 'Potret', 21 | 'page_orientation_landscape' => 'Lanskap', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/id/table_view.php: -------------------------------------------------------------------------------- 1 | 'Pratinjau', 5 | 'print_action_label' => 'Cetak', 6 | 'export_action_label' => 'Ekspor', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/it/export_action.php: -------------------------------------------------------------------------------- 1 | 'Esporta', 5 | 'modal_heading' => 'Esporta', 6 | 'file_name_field_label' => 'Nome del file', 7 | 'format_field_label' => 'Formato', 8 | 'page_orientation_field_label' => 'Orientamento della pagina', 9 | 'filter_columns_field_label' => 'Filtra colonne', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Colonne aggiuntive', 12 | 'title_field_label' => 'Titolo', 13 | 'default_value_field_label' => 'Valore predefinito', 14 | 'add_button_label' => 'Aggiungi colonna', 15 | ], 16 | 'export_action_label' => 'Esporta', 17 | 'print_action_label' => 'Stampa', 18 | 'preview_action_label' => 'Anteprima', 19 | 'cancel_action_label' => 'Cancella', 20 | 'page_orientation_portrait' => 'Ritratto', 21 | 'page_orientation_landscape' => 'Panoramica', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/it/table_view.php: -------------------------------------------------------------------------------- 1 | 'Anteprima', 5 | 'print_action_label' => 'Stampa', 6 | 'export_action_label' => 'Esporta', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/ku/export_action.php: -------------------------------------------------------------------------------- 1 | 'ڕاپۆڕت', 5 | 'modal_heading' => 'ڕاپۆڕت', 6 | 'file_name_field_label' => 'ناوی فایل', 7 | 'format_field_label' => 'جۆر', 8 | 'page_orientation_field_label' => 'ئاڕاستەی پەڕە', 9 | 'filter_columns_field_label' => 'فلتەری خانەکان', 10 | 'additional_columns_field' => [ 11 | 'label' => 'خانەی زیادە', 12 | 'title_field_label' => 'ناوی خانە', 13 | 'default_value_field_label' => 'نرخی خانە', 14 | 'add_button_label' => 'زیادکردنی خانە', 15 | ], 16 | 'export_action_label' => 'دابەزاندن', 17 | 'print_action_label' => 'چاپکردن', 18 | 'preview_action_label' => 'بینین', 19 | 'cancel_action_label' => 'ڕەتکردنەوە', 20 | 'page_orientation_portrait' => 'پەڕگەی ستوونی', 21 | 'page_orientation_landscape' => 'پەڕگەی ئاسۆیی', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/ku/table_view.php: -------------------------------------------------------------------------------- 1 | 'بینین', 5 | 'print_action_label' => 'چاپکردن', 6 | 'export_action_label' => 'دابەزاندن', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/nl/export_action.php: -------------------------------------------------------------------------------- 1 | 'Exporteren', 5 | 'modal_heading' => 'Exporteren', 6 | 'file_name_field_label' => 'Bestandsnaam', 7 | 'format_field_label' => 'Formaat', 8 | 'page_orientation_field_label' => 'Afdrukstand', 9 | 'filter_columns_field_label' => 'Kolommen Filteren', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Bijkomende Kolommen', 12 | 'title_field_label' => 'Titel', 13 | 'default_value_field_label' => 'Standaard Waarde', 14 | 'add_button_label' => 'Kolom Toevoegen', 15 | ], 16 | 'export_action_label' => 'Exporteren', 17 | 'print_action_label' => 'Afdrukken', 18 | 'preview_action_label' => 'Voorbeeld', 19 | 'cancel_action_label' => 'Annuleren', 20 | 'page_orientation_portrait' => 'Staand', 21 | 'page_orientation_landscape' => 'Liggend', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/nl/table_view.php: -------------------------------------------------------------------------------- 1 | 'Voorbeeld', 5 | 'print_action_label' => 'Afdrukken', 6 | 'export_action_label' => 'Exporteren', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/lang/pt_BR/export_action.php: -------------------------------------------------------------------------------- 1 | 'Exportar', 5 | 'modal_heading' => 'Exportar', 6 | 'file_name_field_label' => 'Nome do Arquivo', 7 | 'format_field_label' => 'Formato', 8 | 'page_orientation_field_label' => 'Orientação da Página', 9 | 'filter_columns_field_label' => 'Filtrar colunas', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Colunas adicionais', 12 | 'title_field_label' => 'Título', 13 | 'default_value_field_label' => 'Valor predeterminado', 14 | 'add_button_label' => 'Adicionar coluna', 15 | ], 16 | 'export_action_label' => 'Exportar', 17 | 'print_action_label' => 'Imprimir', 18 | 'preview_action_label' => 'Visualizar', 19 | 'cancel_action_label' => 'Cancelar', 20 | 'page_orientation_portrait' => 'Vertical', 21 | 'page_orientation_landscape' => 'Horizontal', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/pt_BR/table_view.php: -------------------------------------------------------------------------------- 1 | 'Visualizar', 5 | 'print_action_label' => 'Imprimir', 6 | 'export_action_label' => 'Exportar', 7 | ]; -------------------------------------------------------------------------------- /resources/lang/tr/export_action.php: -------------------------------------------------------------------------------- 1 | 'Dışarı Aktar', 5 | 'modal_heading' => 'Dışarı Aktar', 6 | 'file_name_field_label' => 'Dosya Adı', 7 | 'format_field_label' => 'Dosya Türü', 8 | 'page_orientation_field_label' => 'Sayfa Yönlendirmesi', 9 | 'filter_columns_field_label' => 'Sütun Filtreleri', 10 | 'additional_columns_field' => [ 11 | 'label' => 'Ek Sütunlar', 12 | 'title_field_label' => 'Başlık', 13 | 'default_value_field_label' => 'Varsayılan Değer', 14 | 'add_button_label' => 'Sütun Ekle', 15 | ], 16 | 'export_action_label' => 'Dışarı Aktar', 17 | 'print_action_label' => 'Yazdır', 18 | 'preview_action_label' => 'Önizleme', 19 | 'cancel_action_label' => 'İptal', 20 | 'page_orientation_portrait' => 'Dikey', 21 | 'page_orientation_landscape' => 'Yatay', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/tr/table_view.php: -------------------------------------------------------------------------------- 1 | 'Önizleme', 5 | 'print_action_label' => 'Yazdır', 6 | 'export_action_label' => 'Dışarı Aktar', 7 | ]; 8 | -------------------------------------------------------------------------------- /resources/views/components/table_view.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 |
9 | 12 | 13 | @foreach ($getAllColumns() as $column) 14 | 17 | @endforeach 18 | 19 | @foreach ($getRows() as $row) 20 | 21 | @foreach ($getAllColumns() as $column) 22 | 25 | @endforeach 26 | 27 | @endforeach 28 |
15 | {{ $column->getLabel() }} 16 |
23 | {{ $row[$column->getName()] }} 24 |
29 |
30 | 31 |
32 |
33 | 34 | @foreach ($getFooterActions() as $action) 35 | {{ $action }} 36 | @endforeach 37 | 38 | @php 39 | $data = $this->mountedTableBulkAction ? $this->mountedTableBulkActionData : $this->mountedTableActionData; 40 | @endphp 41 | @if (is_array($data) && 42 | array_key_exists('table_view', $data) && 43 | $data['table_view'] == 'print-' . $getUniqueActionId()) 44 | 47 | @endif 48 | @if ($shouldRefresh()) 49 | 56 | @endif 57 |
58 | -------------------------------------------------------------------------------- /resources/views/pdf.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ $fileName }} 10 | 42 | 43 | 44 | 45 | 46 | @foreach ($columns as $column) 47 | 50 | @endforeach 51 | 52 | @foreach ($rows as $row) 53 | 54 | @foreach ($columns as $column) 55 | 58 | @endforeach 59 | 60 | @endforeach 61 |
48 | {{ $column->getLabel() }} 49 |
56 | {{ $row[$column->getName()] }} 57 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /resources/views/print.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{ $fileName ?? date()->format('d') }} 8 | 48 | 49 | 50 | 51 | 52 | @foreach ($columns as $column) 53 | 56 | @endforeach 57 | 58 | @foreach ($rows as $row) 59 | 60 | @foreach ($columns as $column) 61 | 64 | @endforeach 65 | 66 | @endforeach 67 |
54 | {{ $column->getLabel() }} 55 |
62 | {{ $row[$column->getName()] }} 63 |
68 | 69 | 70 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisableAdditionalColumns.php: -------------------------------------------------------------------------------- 1 | isAdditionalColumnsDisabled = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function isAdditionalColumnsDisabled(): bool 17 | { 18 | return $this->isAdditionalColumnsDisabled; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisableFileName.php: -------------------------------------------------------------------------------- 1 | isFileNameDisabled = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function isFileNameDisabled(): bool 17 | { 18 | return $this->isFileNameDisabled; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisableFileNamePrefix.php: -------------------------------------------------------------------------------- 1 | isFileNamePrefixDisabled = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function isFileNamePrefixDisabled(): bool 17 | { 18 | return $this->isFileNamePrefixDisabled; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisableFilterColumns.php: -------------------------------------------------------------------------------- 1 | isFilterColumnsDisabled = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function isFilterColumnsDisabled(): bool 17 | { 18 | return $this->isFilterColumnsDisabled; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisableFormats.php: -------------------------------------------------------------------------------- 1 | formats['pdf']); 14 | 15 | return $this; 16 | } 17 | 18 | public function disableXlsx(): static 19 | { 20 | unset($this->formats['xlsx']); 21 | 22 | return $this; 23 | } 24 | 25 | public function disableCsv(): static 26 | { 27 | unset($this->formats['csv']); 28 | 29 | return $this; 30 | } 31 | 32 | public function getFormats(): array 33 | { 34 | if (!empty($this->formats)) { 35 | return $this->formats; 36 | } 37 | 38 | return FilamentExport::DEFAULT_FORMATS; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisablePreview.php: -------------------------------------------------------------------------------- 1 | isPreviewDisabled = $condition; 12 | 13 | $this->modalActions($this->getExportModalActions()); 14 | 15 | return $this; 16 | } 17 | 18 | public function isPreviewDisabled(): bool 19 | { 20 | return $this->isPreviewDisabled; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDisableTableColumns.php: -------------------------------------------------------------------------------- 1 | isTableColumnsDisabled = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function isTableColumnsDisabled(): bool 17 | { 18 | return $this->isTableColumnsDisabled; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanDownloadDirect.php: -------------------------------------------------------------------------------- 1 | shouldDownloadDirect = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function shouldDownloadDirect(): bool 17 | { 18 | return $this->shouldDownloadDirect; 19 | } 20 | 21 | public function fillDefaultData(&$data) 22 | { 23 | if (! is_array($data) || count($data) == 0) { 24 | $data = [ 25 | 'file_name' => null, 26 | 'filter_columns' => [], 27 | 'additional_columns' => [], 28 | 'page_orientation' => null, 29 | ]; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanFormatStates.php: -------------------------------------------------------------------------------- 1 | formatStates = $functions; 12 | 13 | return $this; 14 | } 15 | 16 | public function getFormatStates(): array 17 | { 18 | return $this->formatStates; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanHaveExtraColumns.php: -------------------------------------------------------------------------------- 1 | withColumns = $columns; 14 | 15 | return $this; 16 | } 17 | 18 | public function getWithColumns(): array 19 | { 20 | return $this->evaluate($this->withColumns); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Actions/Concerns/CanHaveExtraViewData.php: -------------------------------------------------------------------------------- 1 | extraViewData = $extraViewData; 14 | 15 | return $this; 16 | } 17 | 18 | public function getExtraViewData(): array 19 | { 20 | return $this->evaluate($this->extraViewData); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanModifyWriters.php: -------------------------------------------------------------------------------- 1 | modifyPdfWriter = $modifyPdfWriter; 16 | 17 | return $this; 18 | } 19 | 20 | public function modifyExcelWriter(?Closure $modifyExcelWriter): static 21 | { 22 | $this->modifyExcelWriter = $modifyExcelWriter; 23 | 24 | return $this; 25 | } 26 | 27 | public function getModifyPdfWriter(): ?Closure 28 | { 29 | return $this->modifyPdfWriter; 30 | } 31 | 32 | public function getModifyExcelWriter(): ?Closure 33 | { 34 | return $this->modifyExcelWriter; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanRefreshTable.php: -------------------------------------------------------------------------------- 1 | has('updates')) { 10 | $updates = collect(request()->updates); 11 | 12 | $gotoPageCalls = $updates->filter(function ($item) { 13 | return $item['type'] === 'callMethod' && $item['payload']['method'] === 'gotoPage' || 14 | $item['type'] === 'callMethod' && $item['payload']['method'] === 'previousPage' || 15 | $item['type'] === 'callMethod' && $item['payload']['method'] === 'nextPage' || 16 | $item['type'] === 'syncInput' && $item['payload']['name'] === 'tableRecordsPerPage'; 17 | }); 18 | 19 | return $gotoPageCalls->count() > 0; 20 | } 21 | 22 | return false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanShowHiddenColumns.php: -------------------------------------------------------------------------------- 1 | shouldShowHiddenColumns = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function shouldShowHiddenColumns(): bool 17 | { 18 | return $this->shouldShowHiddenColumns; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/CanUseSnappy.php: -------------------------------------------------------------------------------- 1 | shouldUseSnappy = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function shouldUseSnappy(): bool 17 | { 18 | return $this->shouldUseSnappy; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasAdditionalColumnsField.php: -------------------------------------------------------------------------------- 1 | additionalColumnsFieldLabel = $label; 18 | 19 | return $this; 20 | } 21 | 22 | public function getAdditionalColumnsFieldLabel(): string|null 23 | { 24 | return $this->additionalColumnsFieldLabel; 25 | } 26 | 27 | public function additionalColumnsTitleFieldLabel(string|null $label = null): static 28 | { 29 | $this->additionalColumnsTitleFieldLabel = $label; 30 | 31 | return $this; 32 | } 33 | 34 | public function getAdditionalColumnsTitleFieldLabel(): string|null 35 | { 36 | return $this->additionalColumnsTitleFieldLabel; 37 | } 38 | 39 | public function additionalColumnsDefaultValueFieldLabel(string|null $label = null): static 40 | { 41 | $this->additionalColumnsDefaultValueFieldLabel = $label; 42 | 43 | return $this; 44 | } 45 | 46 | public function getAdditionalColumnsDefaultValueFieldLabel(): string|null 47 | { 48 | return $this->additionalColumnsDefaultValueFieldLabel; 49 | } 50 | 51 | public function additionalColumnsAddButtonLabel(string|null $label = null): static 52 | { 53 | $this->additionalColumnsAddButtonLabel = $label; 54 | 55 | return $this; 56 | } 57 | 58 | public function getAdditionalColumnsAddButtonLabel(): string|null 59 | { 60 | return $this->additionalColumnsAddButtonLabel; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasCsvDelimiter.php: -------------------------------------------------------------------------------- 1 | csvDelimiter = $csvDelimiter; 12 | 13 | return $this; 14 | } 15 | 16 | public function getCsvDelimiter(): string 17 | { 18 | return $this->csvDelimiter; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasDefaultFormat.php: -------------------------------------------------------------------------------- 1 | defaultFormat = $defaultFormat; 18 | 19 | return $this; 20 | } 21 | 22 | public function getDefaultFormat(): string 23 | { 24 | return $this->defaultFormat; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasDefaultPageOrientation.php: -------------------------------------------------------------------------------- 1 | defaultPageOrientation = $defaultPageOrientation; 18 | 19 | return $this; 20 | } 21 | 22 | public function getDefaultPageOrientation(): string 23 | { 24 | return $this->defaultPageOrientation; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasExportModelActions.php: -------------------------------------------------------------------------------- 1 | getUniqueActionId(); 12 | 13 | return ! $this->isPreviewDisabled() ? [ 14 | Action::make('preview') 15 | ->button() 16 | ->label(__('filament-export::export_action.preview_action_label')) 17 | ->color('success') 18 | ->icon(config('filament-export.preview_icon')) 19 | ->action("\$emit('open-preview-modal-{$uniqueActionId}')"), 20 | ] : []; 21 | } 22 | 23 | public function getExportModalActions(): array 24 | { 25 | $uniqueActionId = $this->getUniqueActionId(); 26 | 27 | $livewireCallActionName = null; 28 | 29 | if (method_exists($this, 'getLivewireSubmitActionName')) { 30 | $livewireCallActionName = $this->getLivewireSubmitActionName(); 31 | } elseif (method_exists($this, 'getLivewireCallActionName')) { 32 | $livewireCallActionName = $this->getLivewireCallActionName(); 33 | } 34 | 35 | return array_merge( 36 | $this->getPreviewAction(), 37 | [ 38 | Action::make('submit') 39 | ->button() 40 | ->label($this->getModalButtonLabel()) 41 | ->submit($livewireCallActionName) 42 | ->color($this->getColor() !== 'secondary' ? $this->getColor() : null) 43 | ->icon(config('filament-export.export_icon')), 44 | Action::make('print') 45 | ->button() 46 | ->label(__('filament-export::export_action.print_action_label')) 47 | ->color('gray') 48 | ->icon(config('filament-export.print_icon')) 49 | ->action("\$emit('print-table-{$uniqueActionId}')"), 50 | Action::make('cancel') 51 | ->button() 52 | ->label(__('filament-export::export_action.cancel_action_label')) 53 | ->cancel() 54 | ->color('secondary') 55 | ->icon(config('filament-export.cancel_icon')) 56 | ->action("\$emit('close-preview-modal-{$uniqueActionId}')"), 57 | ] 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasFileName.php: -------------------------------------------------------------------------------- 1 | fileName = $fileName; 14 | 15 | return $this; 16 | } 17 | 18 | public function getFileName(): string 19 | { 20 | if (! $this->isFileNamePrefixDisabled() && $this->getFileNamePrefix()) { 21 | return "{$this->getFileNamePrefix()}-{$this->fileName}"; 22 | } 23 | 24 | return $this->fileName; 25 | } 26 | 27 | public function fileNamePrefix(string|null $fileNamePrefix): static 28 | { 29 | $this->fileNamePrefix = $fileNamePrefix; 30 | 31 | return $this; 32 | } 33 | 34 | public function getFileNamePrefix(): string|null 35 | { 36 | return $this->fileNamePrefix; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasFileNameField.php: -------------------------------------------------------------------------------- 1 | fileNameFieldLabel = $label; 12 | 13 | return $this; 14 | } 15 | 16 | public function getFileNameFieldLabel(): string|null 17 | { 18 | return $this->fileNameFieldLabel; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasFilterColumnsField.php: -------------------------------------------------------------------------------- 1 | filterColumnsFieldLabel = $label; 12 | 13 | return $this; 14 | } 15 | 16 | public function getFilterColumnsFieldLabel(): string|null 17 | { 18 | return $this->filterColumnsFieldLabel; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasFormatField.php: -------------------------------------------------------------------------------- 1 | formatFieldLabel = $label; 12 | 13 | return $this; 14 | } 15 | 16 | public function getFormatFieldLabel(): string|null 17 | { 18 | return $this->formatFieldLabel; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasPageOrientationField.php: -------------------------------------------------------------------------------- 1 | pageOrientationFieldLabel = $label; 12 | 13 | return $this; 14 | } 15 | 16 | public function getPageOrientationFieldLabel(): string|null 17 | { 18 | return $this->pageOrientationFieldLabel; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasPaginator.php: -------------------------------------------------------------------------------- 1 | paginator = $paginator; 14 | 15 | return $this; 16 | } 17 | 18 | public function getPaginator(): ?LengthAwarePaginator 19 | { 20 | return $this->paginator; 21 | } 22 | 23 | public function hasPaginator(): bool 24 | { 25 | return $this->paginator !== null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasRecords.php: -------------------------------------------------------------------------------- 1 | getLivewire(); 15 | 16 | $model = $this->getTable()->getModel(); 17 | $query = $model::query(); 18 | 19 | if (method_exists($livewire, 'getResource')) { 20 | $query = $livewire::getResource()::getEloquentQuery(); 21 | } 22 | 23 | $reflection = new \ReflectionMethod($livewire, 'getTableQuery'); 24 | 25 | if ($reflection->isPublic()) { 26 | $query = $livewire->getTableQuery(); 27 | } 28 | 29 | $filterData = $livewire->tableFilters; 30 | 31 | if (isset($livewire->ownerRecord)) { 32 | $query->whereBelongsTo($livewire->ownerRecord); 33 | } 34 | 35 | $livewire->cacheTableFilters(); 36 | 37 | $query->where(function (Builder $query) use ($filterData, $livewire) { 38 | foreach ($livewire->getCachedTableFilters() as $filter) { 39 | $filter->apply( 40 | $query, 41 | $filterData[$filter->getName()] ?? [], 42 | ); 43 | } 44 | }); 45 | 46 | $searchQuery = $livewire->tableSearchQuery; 47 | 48 | if ($searchQuery !== '') { 49 | foreach (explode(' ', $searchQuery) as $searchQueryWord) { 50 | $query->where(function (Builder $query) use ($searchQueryWord, $livewire) { 51 | $isFirst = true; 52 | 53 | foreach ($livewire->getCachedTableColumns() as $column) { 54 | $column->applySearchConstraint($query, $searchQueryWord, $isFirst); 55 | } 56 | }); 57 | } 58 | } 59 | 60 | foreach ($livewire->getCachedTableColumns() as $column) { 61 | $column->applyEagerLoading($query); 62 | $column->applyRelationshipAggregates($query); 63 | } 64 | 65 | $this->applySortingToTableQuery($query); 66 | 67 | return $query; 68 | } 69 | 70 | protected function applySortingToTableQuery(Builder $query): Builder 71 | { 72 | $livewire = $this->getLivewire(); 73 | 74 | $columnName = $livewire->tableSortColumn; 75 | 76 | if (!$columnName) { 77 | return $query; 78 | } 79 | 80 | $direction = $livewire->tableSortDirection === 'desc' ? 'desc' : 'asc'; 81 | 82 | if ($column = $livewire->getCachedTableColumns()[$columnName]) { 83 | $column->applySort($query, $direction); 84 | 85 | return $query; 86 | } 87 | 88 | if ($columnName === $livewire->getDefaultSortColumn()) { 89 | return $query->orderBy($columnName, $direction); 90 | } 91 | 92 | return $query; 93 | } 94 | 95 | public function getRecords(): Collection 96 | { 97 | return $this 98 | ->getTableQuery() 99 | ->get(); 100 | } 101 | } -------------------------------------------------------------------------------- /src/Actions/Concerns/HasTimeFormat.php: -------------------------------------------------------------------------------- 1 | timeFormat = $timeFormat; 14 | 15 | $this->fileName(Carbon::now()->translatedFormat($this->getTimeFormat())); 16 | 17 | return $this; 18 | } 19 | 20 | public function getTimeFormat(): string 21 | { 22 | return $this->timeFormat; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Actions/Concerns/HasUniqueActionId.php: -------------------------------------------------------------------------------- 1 | uniqueActionId = $uniqueActionId; 12 | 13 | return $this; 14 | } 15 | 16 | public function getUniqueActionId(): string 17 | { 18 | return $this->uniqueActionId; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Actions/FilamentExportBulkAction.php: -------------------------------------------------------------------------------- 1 | uniqueActionId('bulk-action'); 73 | 74 | FilamentExport::setUpFilamentExportAction($this); 75 | 76 | $this 77 | ->modalHeading(static function ($action) { 78 | if ($action->shouldDownloadDirect()) { 79 | return false; 80 | } 81 | return $action; 82 | }) 83 | ->form(static function ($action, $records, $livewire): array { 84 | if ($action->shouldDownloadDirect()) { 85 | return []; 86 | } 87 | 88 | $currentPage = LengthAwarePaginator::resolveCurrentPage('exportPage'); 89 | $perPage = $livewire->tableRecordsPerPage > 0 ? $livewire->tableRecordsPerPage : $records->count(); 90 | 91 | $paginator = new LengthAwarePaginator($records->forPage($currentPage, $perPage), $records->count(), $perPage, $currentPage, [ 92 | 'pageName' => 'exportPage', 93 | ]); 94 | 95 | $action->paginator($paginator); 96 | 97 | return FilamentExport::getFormComponents($action); 98 | }) 99 | ->action(static function ($action, $records, $data): StreamedResponse { 100 | $action->fillDefaultData($data); 101 | 102 | return FilamentExport::callDownload($action, $records, $data); 103 | }); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/Actions/FilamentExportHeaderAction.php: -------------------------------------------------------------------------------- 1 | uniqueActionId('header-action'); 74 | 75 | FilamentExport::setUpFilamentExportAction($this); 76 | 77 | $this 78 | ->modalHeading(static function ($action) { 79 | if ($action->shouldDownloadDirect()) { 80 | return false; 81 | } 82 | return $action; 83 | }) 84 | ->form(static function ($action, $livewire): array { 85 | if ($action->shouldDownloadDirect()) { 86 | return []; 87 | } 88 | 89 | $paginator = $action->getTableQuery()->paginate(static function (int $total) use ($livewire): int { 90 | if ($livewire->tableRecordsPerPage > 0) { 91 | return $livewire->tableRecordsPerPage; 92 | } 93 | 94 | return $total; 95 | }, ['*'], 'exportPage'); 96 | 97 | $action->paginator($paginator); 98 | 99 | return FilamentExport::getFormComponents($action); 100 | }) 101 | ->action(static function ($action, $data): StreamedResponse { 102 | $action->fillDefaultData($data); 103 | 104 | $records = $action->getRecords(); 105 | 106 | return FilamentExport::callDownload($action, $records, $data); 107 | }); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Components/Concerns/HasAction.php: -------------------------------------------------------------------------------- 1 | action = $action; 15 | 16 | $this->getExport()->fileName($this->getAction()->getFileName()); 17 | 18 | $this->getExport()->table($this->getAction()->getTable()); 19 | 20 | return $this; 21 | } 22 | 23 | public function getAction(): FilamentExportBulkAction | FilamentExportHeaderAction 24 | { 25 | return $this->action; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Components/Concerns/HasRecords.php: -------------------------------------------------------------------------------- 1 | records = $records; 14 | 15 | $this->getExport()->data($this->getRecords()); 16 | 17 | return $this; 18 | } 19 | 20 | public function getRecords(): Collection 21 | { 22 | return $this->records; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Components/Concerns/HasUniqueActionId.php: -------------------------------------------------------------------------------- 1 | uniqueActionId = $uniqueActionId; 12 | 13 | return $this; 14 | } 15 | 16 | public function getUniqueActionId(): string 17 | { 18 | return $this->uniqueActionId; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Components/TableView.php: -------------------------------------------------------------------------------- 1 | view('filament-export::components.table_view'); 29 | } 30 | 31 | public static function make(string $name): static 32 | { 33 | $static = app(static::class); 34 | $static->name($name); 35 | $static->setUp(); 36 | 37 | return $static; 38 | } 39 | 40 | public function export(FilamentExport $export): static 41 | { 42 | $this->export = $export; 43 | 44 | return $this; 45 | } 46 | 47 | public function getExport(): FilamentExport 48 | { 49 | return $this->export; 50 | } 51 | 52 | public function fileName(string $fileName): static 53 | { 54 | $this->getExport()->fileName($fileName); 55 | 56 | return $this; 57 | } 58 | 59 | public function getFileName(): string 60 | { 61 | return $this->getExport()->getFileName(); 62 | } 63 | 64 | public function filteredColumns(array $columns): static 65 | { 66 | if (count($columns) == 0) { 67 | return $this; 68 | } 69 | 70 | $this->getExport()->filteredColumns($columns); 71 | 72 | return $this; 73 | } 74 | 75 | public function getFilteredColumns(): Collection 76 | { 77 | return $this->getExport()->getFilteredColumns(); 78 | } 79 | 80 | public function additionalColumns(array $additionalColumns): static 81 | { 82 | if (count($additionalColumns) == 0) { 83 | return $this; 84 | } 85 | 86 | $this->getExport()->additionalColumns($additionalColumns); 87 | 88 | return $this; 89 | } 90 | 91 | public function getAdditionalColumns(): Collection 92 | { 93 | return $this->getExport()->getAdditionalColumns(); 94 | } 95 | 96 | public function extraViewData(array $extraViewData): static 97 | { 98 | $this->getExport()->extraViewData($extraViewData); 99 | 100 | return $this; 101 | } 102 | 103 | public function getExtraViewData(): array 104 | { 105 | return $this->getExport()->getExtraViewData(); 106 | } 107 | 108 | public function getAllColumns(): Collection 109 | { 110 | return $this->getExport()->getAllColumns(); 111 | } 112 | 113 | public function getRows(): LengthAwarePaginator 114 | { 115 | $paginator = $this 116 | ->getExport() 117 | ->getPaginator(); 118 | 119 | $paginator->getCollection()->transform(function ($row, $key) { 120 | $data = []; 121 | 122 | foreach ($this->getAllColumns() as $column) { 123 | if (is_array($row)) { 124 | $data[$column->getName()] = data_get($row, $column->getName()); 125 | 126 | continue; 127 | } 128 | 129 | $data[$column->getName()] = FilamentExport::getColumnState($this->getExport()->getTable(), $column, $row, $key, $this->getExport()->getFormatStates()); 130 | } 131 | 132 | return $data; 133 | }); 134 | 135 | return $paginator; 136 | } 137 | 138 | public function getExportAction(): Action 139 | { 140 | return Action::make('export') 141 | ->button() 142 | ->label(__('filament-export::table_view.export_action_label')) 143 | ->submit() 144 | ->icon(config('filament-export.export_icon')); 145 | } 146 | 147 | public function getPrintAction(): Action 148 | { 149 | $uniqueActionId = $this->getUniqueActionId(); 150 | 151 | return Action::make('print') 152 | ->button() 153 | ->label(__('filament-export::table_view.print_action_label')) 154 | ->action("\$emit('print-table-$uniqueActionId')") 155 | ->color('gray') 156 | ->icon(config('filament-export.print_icon')); 157 | } 158 | 159 | public function getCancelAction(): Action 160 | { 161 | return Action::make('cancel') 162 | ->button() 163 | ->label(__('filament-export::export_action.cancel_action_label')) 164 | ->cancel() 165 | ->color('secondary') 166 | ->icon(config('filament-export.cancel_icon')); 167 | } 168 | 169 | public function getFooterActions(): array 170 | { 171 | return [ 172 | $this->getExportAction(), 173 | $this->getPrintAction(), 174 | $this->getCancelAction(), 175 | ]; 176 | } 177 | 178 | public function getPreviewModalHeading(): string 179 | { 180 | return __('filament-export::table_view.preview_modal_heading'); 181 | } 182 | 183 | public function data() 184 | { 185 | return array_merge( 186 | parent::data(), 187 | $this->getExport()->getExtraViewData() 188 | ); 189 | } 190 | 191 | public function refresh(bool $condition): static 192 | { 193 | $this->shouldRefresh = $condition; 194 | 195 | return $this; 196 | } 197 | 198 | public function shouldRefresh(): bool 199 | { 200 | return $this->shouldRefresh; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/Concerns/CanDisableTableColumns.php: -------------------------------------------------------------------------------- 1 | isTableColumnsDisabled = $condition; 14 | 15 | return $this; 16 | } 17 | 18 | public function isTableColumnsDisabled(): bool 19 | { 20 | return $this->isTableColumnsDisabled; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Concerns/CanFilterColumns.php: -------------------------------------------------------------------------------- 1 | filteredColumns = $columns; 18 | 19 | return $this; 20 | } 21 | 22 | public function getFilteredColumns(): Collection 23 | { 24 | return collect($this->filteredColumns); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Concerns/CanFormatStates.php: -------------------------------------------------------------------------------- 1 | formatStates = $functions; 12 | 13 | return $this; 14 | } 15 | 16 | public function getFormatStates(): array 17 | { 18 | return $this->formatStates; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Concerns/CanHaveAdditionalColumns.php: -------------------------------------------------------------------------------- 1 | mapWithKeys(function ($value, $key) { 19 | $name = $key.'-'.uniqid(); 20 | 21 | return [$name => \Filament\Tables\Columns\TextColumn::make(Str::snake($name))->label($key)->default($value)]; 22 | })->toArray(); 23 | 24 | $this->additionalColumns = $additionalColumns; 25 | 26 | return $this; 27 | } 28 | 29 | public function getAdditionalColumns(): Collection 30 | { 31 | return collect($this->additionalColumns); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Concerns/CanHaveExtraColumns.php: -------------------------------------------------------------------------------- 1 | withColumns = $columns; 14 | 15 | return $this; 16 | } 17 | 18 | public function getWithColumns(): Collection 19 | { 20 | return collect($this->withColumns); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Concerns/CanHaveExtraViewData.php: -------------------------------------------------------------------------------- 1 | extraViewData = $extraViewData; 16 | 17 | return $this; 18 | } 19 | 20 | public function getExtraViewData(): array 21 | { 22 | return $this->extraViewData; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Concerns/CanModifyWriters.php: -------------------------------------------------------------------------------- 1 | modifyPdfWriter = $modifyPdfWriter; 16 | 17 | return $this; 18 | } 19 | 20 | public function modifyExcelWriter(?Closure $modifyExcelWriter): static 21 | { 22 | $this->modifyExcelWriter = $modifyExcelWriter; 23 | 24 | return $this; 25 | } 26 | 27 | public function getModifyPdfWriter(): ?Closure 28 | { 29 | return $this->modifyPdfWriter; 30 | } 31 | 32 | public function getModifyExcelWriter(): ?Closure 33 | { 34 | return $this->modifyExcelWriter; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Concerns/CanShowHiddenColumns.php: -------------------------------------------------------------------------------- 1 | shouldShowHiddenColumns = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function shouldShowHiddenColumns(): bool 17 | { 18 | return $this->shouldShowHiddenColumns; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Concerns/CanUseSnappy.php: -------------------------------------------------------------------------------- 1 | shouldUseSnappy = $condition; 12 | 13 | return $this; 14 | } 15 | 16 | public function shouldUseSnappy(): bool 17 | { 18 | return $this->shouldUseSnappy; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Concerns/HasCsvDelimiter.php: -------------------------------------------------------------------------------- 1 | csvDelimiter = $csvDelimiter; 12 | 13 | return $this; 14 | } 15 | 16 | public function getCsvDelimiter(): string 17 | { 18 | return $this->csvDelimiter; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Concerns/HasData.php: -------------------------------------------------------------------------------- 1 | data = $data; 15 | 16 | return $this; 17 | } 18 | 19 | public function getData(): Collection|LengthAwarePaginator 20 | { 21 | return $this->data; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Concerns/HasFileName.php: -------------------------------------------------------------------------------- 1 | fileName = $fileName; 12 | 13 | return $this; 14 | } 15 | 16 | public function getFileName(): string 17 | { 18 | return $this->fileName; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Concerns/HasFormat.php: -------------------------------------------------------------------------------- 1 | format = $format; 18 | 19 | return $this; 20 | } 21 | 22 | public function getFormat(): string 23 | { 24 | return $this->format; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Concerns/HasPageOrientation.php: -------------------------------------------------------------------------------- 1 | pageOrientation = $pageOrientation; 18 | 19 | return $this; 20 | } 21 | 22 | public function getPageOrientation(): string 23 | { 24 | return $this->pageOrientation; 25 | } 26 | 27 | public static function getPageOrientations() 28 | { 29 | return [ 30 | 'portrait' => __('filament-export::export_action.page_orientation_portrait'), 31 | 'landscape' => __('filament-export::export_action.page_orientation_landscape'), 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Concerns/HasPaginator.php: -------------------------------------------------------------------------------- 1 | paginator = $paginator; 15 | } 16 | 17 | return $this; 18 | } 19 | 20 | public function getPaginator(): ?LengthAwarePaginator 21 | { 22 | return $this->paginator; 23 | } 24 | 25 | public function hasPaginator(): bool 26 | { 27 | return $this->paginator !== null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Concerns/HasTable.php: -------------------------------------------------------------------------------- 1 | table = $table; 14 | 15 | return $this; 16 | } 17 | 18 | public function getTable(): Table 19 | { 20 | return $this->table; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/FilamentExport.php: -------------------------------------------------------------------------------- 1 | 'XLSX', 60 | 'csv' => 'CSV', 61 | 'pdf' => 'PDF', 62 | ]; 63 | 64 | public static function make(): static 65 | { 66 | $static = app(static::class); 67 | $static->setUp(); 68 | 69 | return $static; 70 | } 71 | 72 | protected function setUp(): void 73 | { 74 | $this->fileName(Date::now()->toString()); 75 | 76 | $this->format(config('filament-export.default_format')); 77 | } 78 | 79 | public function getAllColumns(): Collection 80 | { 81 | if ($this->isTableColumnsDisabled()) { 82 | $tableColumns = []; 83 | } else { 84 | $tableColumns = $this->shouldShowHiddenColumns() ? $this->getTable()->getLivewire()->getCachedTableColumns() : $this->getTable()->getColumns(); 85 | } 86 | 87 | $columns = collect($tableColumns); 88 | 89 | if ($this->getWithColumns()->isNotEmpty()) { 90 | $columns = $columns->merge($this->getWithColumns()); 91 | } 92 | 93 | if ($this->getFilteredColumns()->isNotEmpty()) { 94 | $columns = $columns->filter(fn ($column) => $this->getFilteredColumns()->contains($column->getName())); 95 | } 96 | 97 | if ($this->getAdditionalColumns()->isNotEmpty()) { 98 | $columns = $columns->merge($this->getAdditionalColumns()); 99 | } 100 | 101 | return $columns; 102 | } 103 | 104 | public function getPdfView(): string 105 | { 106 | return 'filament-export::pdf'; 107 | } 108 | 109 | public function getViewData(): array 110 | { 111 | return array_merge( 112 | [ 113 | 'fileName' => $this->getFileName(), 114 | 'columns' => $this->getAllColumns(), 115 | 'rows' => $this->getRows(), 116 | ], 117 | $this->getExtraViewData() 118 | ); 119 | } 120 | 121 | public function download(): StreamedResponse 122 | { 123 | if ($this->getFormat() === 'pdf') { 124 | $pdf = $this->getPdf(); 125 | 126 | if ($modifyPdf = $this->getModifyPdfWriter()) { 127 | $pdf = $modifyPdf($pdf); 128 | } 129 | 130 | return response()->streamDownload(fn () => print($pdf->output()), "{$this->getFileName()}.{$this->getFormat()}"); 131 | } 132 | 133 | return response()->streamDownload(function () { 134 | $headers = $this->getAllColumns()->map(fn ($column) => ($column->getLabel() instanceof HtmlString ? strip_tags($column->getLabel()) : $column->getLabel()))->toArray(); 135 | 136 | $stream = SimpleExcelWriter::streamDownload("{$this->getFileName()}.{$this->getFormat()}", $this->getFormat(), delimiter: $this->getCsvDelimiter()); 137 | 138 | if ($modifyExcel = $this->getModifyExcelWriter()) { 139 | $stream = $modifyExcel($stream); 140 | } 141 | 142 | $stream->addHeader($headers); 143 | $stream->addRows($this->getRows()); 144 | 145 | $stream->close(); 146 | }, "{$this->getFileName()}.{$this->getFormat()}"); 147 | } 148 | 149 | public function getPdf(): \Barryvdh\DomPDF\PDF | \Barryvdh\Snappy\PdfWrapper 150 | { 151 | if ($this->shouldUseSnappy()) { 152 | return \Barryvdh\Snappy\Facades\SnappyPdf::loadView($this->getPdfView(), $this->getViewData()) 153 | ->setPaper('A4', $this->getPageOrientation()); 154 | } 155 | 156 | return \Barryvdh\DomPDF\Facade\Pdf::loadView($this->getPdfView(), $this->getViewData()) 157 | ->setPaper('A4', $this->getPageOrientation()); 158 | } 159 | 160 | public static function setUpFilamentExportAction(FilamentExportHeaderAction | FilamentExportBulkAction $action): void 161 | { 162 | $action->timeFormat(config('filament-export.time_format')); 163 | 164 | $action->defaultFormat(config('filament-export.default_format')); 165 | 166 | $action->defaultPageOrientation(config('filament-export.default_page_orientation')); 167 | 168 | $action->disableAdditionalColumns(config('filament-export.disable_additional_columns')); 169 | 170 | $action->disableFilterColumns(config('filament-export.disable_filter_columns')); 171 | 172 | $action->disableFileName(config('filament-export.disable_file_name')); 173 | 174 | $action->disableFileNamePrefix(config('filament-export.disable_file_name_prefix')); 175 | 176 | $action->disablePreview(config('filament-export.disable_preview')); 177 | 178 | $action->snappy(config('filament-export.use_snappy', false)); 179 | 180 | $action->icon(config('filament-export.action_icon')); 181 | 182 | $action->fileName(Carbon::now()->translatedFormat($action->getTimeFormat())); 183 | 184 | $action->fileNameFieldLabel(__('filament-export::export_action.file_name_field_label')); 185 | 186 | $action->filterColumnsFieldLabel(__('filament-export::export_action.filter_columns_field_label')); 187 | 188 | $action->formatFieldLabel(__('filament-export::export_action.format_field_label')); 189 | 190 | $action->pageOrientationFieldLabel(__('filament-export::export_action.page_orientation_field_label')); 191 | 192 | $action->additionalColumnsFieldLabel(__('filament-export::export_action.additional_columns_field.label')); 193 | 194 | $action->additionalColumnsTitleFieldLabel(__('filament-export::export_action.additional_columns_field.title_field_label')); 195 | 196 | $action->additionalColumnsDefaultValueFieldLabel(__('filament-export::export_action.additional_columns_field.default_value_field_label')); 197 | 198 | $action->additionalColumnsAddButtonLabel(__('filament-export::export_action.additional_columns_field.add_button_label')); 199 | 200 | $action->modalButton(__('filament-export::export_action.export_action_label')); 201 | 202 | $action->modalHeading(__('filament-export::export_action.modal_heading')); 203 | 204 | $action->modalActions($action->getExportModalActions()); 205 | } 206 | 207 | public static function getFormComponents(FilamentExportHeaderAction | FilamentExportBulkAction $action): array 208 | { 209 | $action->fileNamePrefix($action->getFileNamePrefix() ?: $action->getTable()->getHeading()); 210 | 211 | if ($action->isTableColumnsDisabled()) { 212 | $columns = []; 213 | } else { 214 | $columns = $action->shouldShowHiddenColumns() ? $action->getLivewire()->getCachedTableColumns() : $action->getTable()->getColumns(); 215 | } 216 | $columns = collect($columns); 217 | 218 | $extraColumns = collect($action->getWithColumns()); 219 | 220 | if($extraColumns->isNotEmpty()) { 221 | $columns = $columns->merge($extraColumns); 222 | } 223 | 224 | $columns = $columns 225 | ->mapWithKeys(fn ($column) => [$column->getName() => $column->getLabel()]) 226 | ->toArray(); 227 | 228 | $updateTableView = function ($component, $livewire) use ($action) { 229 | $data = $action instanceof FilamentExportBulkAction ? $livewire->mountedTableBulkActionData : $livewire->mountedTableActionData; 230 | 231 | $export = FilamentExport::make() 232 | ->filteredColumns($data['filter_columns'] ?? []) 233 | ->additionalColumns($data['additional_columns'] ?? []) 234 | ->data(collect()) 235 | ->table($action->getTable()) 236 | ->disableTableColumns($action->isTableColumnsDisabled()) 237 | ->extraViewData($action->getExtraViewData()) 238 | ->withColumns($action->getWithColumns()) 239 | ->paginator($action->getPaginator()) 240 | ->csvDelimiter($action->getCsvDelimiter()) 241 | ->formatStates($action->getFormatStates()); 242 | 243 | $component 244 | ->export($export) 245 | ->refresh($action->shouldRefreshTableView()); 246 | 247 | if ($data['table_view'] == 'print-'.$action->getUniqueActionId()) { 248 | $export->data($action->getRecords()); 249 | $action->getLivewire()->printHTML = view('filament-export::print', $export->getViewData())->render(); 250 | } elseif ($data['table_view'] == 'afterprint-'.$action->getUniqueActionId()) { 251 | $action->getLivewire()->printHTML = null; 252 | } 253 | }; 254 | 255 | $initialExport = FilamentExport::make() 256 | ->table($action->getTable()) 257 | ->disableTableColumns($action->isTableColumnsDisabled()) 258 | ->data(collect()) 259 | ->extraViewData($action->getExtraViewData()) 260 | ->withColumns($action->getWithColumns()) 261 | ->paginator($action->getPaginator()) 262 | ->csvDelimiter($action->getCsvDelimiter()) 263 | ->formatStates($action->getFormatStates()); 264 | 265 | return [ 266 | \Filament\Forms\Components\TextInput::make('file_name') 267 | ->label($action->getFileNameFieldLabel()) 268 | ->default($action->getFileName()) 269 | ->hidden($action->isFileNameDisabled()) 270 | ->rule('regex:/[a-zA-Z0-9\s_\\.\-\(\):]/') 271 | ->required(), 272 | \Filament\Forms\Components\Select::make('format') 273 | ->label($action->getFormatFieldLabel()) 274 | ->options($action->getFormats()) 275 | ->default($action->getDefaultFormat()) 276 | ->reactive(), 277 | \Filament\Forms\Components\Select::make('page_orientation') 278 | ->label($action->getPageOrientationFieldLabel()) 279 | ->options(FilamentExport::getPageOrientations()) 280 | ->default($action->getDefaultPageOrientation()) 281 | ->visible(fn ($get) => $get('format') === 'pdf'), 282 | \Filament\Forms\Components\CheckboxList::make('filter_columns') 283 | ->label($action->getFilterColumnsFieldLabel()) 284 | ->options($columns) 285 | ->columns(4) 286 | ->default(array_keys($columns)) 287 | ->hidden($action->isFilterColumnsDisabled()), 288 | \Filament\Forms\Components\KeyValue::make('additional_columns') 289 | ->label($action->getAdditionalColumnsFieldLabel()) 290 | ->keyLabel($action->getAdditionalColumnsTitleFieldLabel()) 291 | ->valueLabel($action->getAdditionalColumnsDefaultValueFieldLabel()) 292 | ->addButtonLabel($action->getAdditionalColumnsAddButtonLabel()) 293 | ->hidden($action->isAdditionalColumnsDisabled()), 294 | TableView::make('table_view') 295 | ->export($initialExport) 296 | ->uniqueActionId($action->getUniqueActionId()) 297 | ->afterStateUpdated($updateTableView) 298 | ->reactive() 299 | ->refresh($action->shouldRefreshTableView()), 300 | ]; 301 | } 302 | 303 | public static function callDownload(FilamentExportHeaderAction | FilamentExportBulkAction $action, Collection $records, array $data) 304 | { 305 | return FilamentExport::make() 306 | ->fileName($data['file_name'] ?? $action->getFileName()) 307 | ->data($records) 308 | ->table($action->getTable()) 309 | ->disableTableColumns($action->isTableColumnsDisabled()) 310 | ->filteredColumns(! $action->isFilterColumnsDisabled() ? $data['filter_columns'] : []) 311 | ->additionalColumns(! $action->isAdditionalColumnsDisabled() ? $data['additional_columns'] : []) 312 | ->format($data['format'] ?? $action->getDefaultFormat()) 313 | ->pageOrientation($data['page_orientation'] ?? $action->getDefaultPageOrientation()) 314 | ->snappy($action->shouldUseSnappy()) 315 | ->extraViewData($action->getExtraViewData()) 316 | ->withColumns($action->getWithColumns()) 317 | ->withHiddenColumns($action->shouldShowHiddenColumns()) 318 | ->csvDelimiter($action->getCsvDelimiter()) 319 | ->modifyExcelWriter($action->getModifyExcelWriter()) 320 | ->modifyPdfWriter($action->getModifyPdfWriter()) 321 | ->formatStates($action->getFormatStates()) 322 | ->download(); 323 | } 324 | 325 | public function getRows(): Collection 326 | { 327 | $records = $this->getData(); 328 | 329 | $data = self::getDataWithStates($records); 330 | 331 | return collect($data); 332 | } 333 | 334 | public function getDataWithStates(Collection|LengthAwarePaginator $records): array 335 | { 336 | $items = []; 337 | 338 | $columns = $this->getAllColumns(); 339 | 340 | $formatStates = $this->getFormatStates(); 341 | 342 | foreach ($records as $index => $record) { 343 | $item = []; 344 | 345 | foreach ($columns as $column) { 346 | $state = self::getColumnState($this->getTable(), $column, $record, $index, $formatStates); 347 | 348 | $item[$column->getName()] = (string) $state; 349 | } 350 | array_push($items, $item); 351 | } 352 | 353 | return $items; 354 | } 355 | 356 | public static function getColumnState(Table $table, Column $column, Model $record, int $index, array $formatStates): ?string 357 | { 358 | $column->rowLoop((object) [ 359 | 'index' => $index, 360 | 'iteration' => $index + 1, 361 | ]); 362 | 363 | $column->record($record); 364 | 365 | $column->table($table); 366 | 367 | if (array_key_exists($column->getName(), $formatStates) && $formatStates[$column->getName()] instanceof \Closure) { 368 | $closure = $formatStates[$column->getName()]; 369 | 370 | $dependencies = []; 371 | 372 | foreach ((new \ReflectionFunction($closure))->getParameters() as $parameter) { 373 | switch ($parameter->getName()) { 374 | case 'table': 375 | $dependencies[] = $table; 376 | break; 377 | case 'column': 378 | $dependencies[] = $column; 379 | break; 380 | case 'record': 381 | $dependencies[] = $record; 382 | break; 383 | case 'index': 384 | $dependencies[] = $index; 385 | break; 386 | } 387 | } 388 | 389 | return $closure(...$dependencies); 390 | } 391 | 392 | $state = in_array(\Filament\Tables\Columns\Concerns\CanFormatState::class, class_uses($column)) ? $column->getFormattedState() : $column->getState(); 393 | 394 | if (is_array($state)) { 395 | $state = implode(', ', $state); 396 | } elseif ($column instanceof ImageColumn) { 397 | $state = $column->getImagePath(); 398 | } elseif ($column instanceof ViewColumn) { 399 | $state = trim(preg_replace('/\s+/', ' ', strip_tags($column->render()->render()))); 400 | } 401 | 402 | return $state; 403 | } 404 | } 405 | -------------------------------------------------------------------------------- /src/FilamentExportServiceProvider.php: -------------------------------------------------------------------------------- 1 | mergeConfigFrom(__DIR__.'/../config/filament-export.php', 'filament-export'); 12 | } 13 | 14 | public function boot() 15 | { 16 | $this->loadViewsFrom(__DIR__.'/../resources/views', 'filament-export'); 17 | 18 | $this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'filament-export'); 19 | 20 | $this->publishes([ 21 | __DIR__.'/../config/filament-export.php' => config_path('filament-export.php'), 22 | ], 'config'); 23 | 24 | $this->publishes([ 25 | __DIR__.'/../resources/views' => resource_path('views/vendor/filament-export'), 26 | ], 'views'); 27 | 28 | if (class_exists('\Filament\Facades\Filament')) { 29 | \Filament\Facades\Filament::serving(function () { 30 | \Filament\Facades\Filament::registerScripts([ 31 | 'filament-export-0.3.0' => __DIR__.'/../resources/js/filament-export.js', 32 | ]); 33 | \Filament\Facades\Filament::registerStyles([ 34 | 'filament-export-0.3.0' => __DIR__.'/../resources/css/filament-export.css', 35 | ]); 36 | }); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Pest.php: -------------------------------------------------------------------------------- 1 | in('src/'); 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Expectations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | When you're writing tests, you often need to check that values meet certain conditions. The 24 | | "expect()" function gives you access to a set of "expectations" methods that you can use 25 | | to assert different things. Of course, you may extend the Expectation API at any time. 26 | | 27 | */ 28 | 29 | expect()->extend('toBeOne', function () { 30 | return $this->toBe(1); 31 | }); 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Functions 36 | |-------------------------------------------------------------------------- 37 | | 38 | | While Pest is very powerful out-of-the-box, you may have some testing code specific to your 39 | | project that you don't want to repeat in every file. Here you can also expose helpers as 40 | | global functions to help you to reduce the number of lines of code in your test files. 41 | | 42 | */ 43 | 44 | function something() 45 | { 46 | // .. 47 | } 48 | -------------------------------------------------------------------------------- /tests/database/factories/PostFactory.php: -------------------------------------------------------------------------------- 1 | User::factory(), 17 | 'content' => $this->faker->paragraph(), 18 | 'tags' => $this->faker->words(), 19 | 'title' => $this->faker->sentence(), 20 | 'rating' => $this->faker->numberBetween(1, 10), 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->name(), 17 | 'email' => $this->faker->unique()->safeEmail(), 18 | 'email_verified_at' => now(), 19 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 20 | 'remember_token' => Str::random(10), 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/database/migrations/create_posts_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->foreignId('user_id'); 14 | $table->text('content')->nullable(); 15 | $table->json('tags')->nullable(); 16 | $table->string('title'); 17 | $table->unsignedTinyInteger('rating')->default(0); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | public function down(): void 23 | { 24 | Schema::dropIfExists('posts'); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /tests/database/migrations/create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 13 | $table->string('name'); 14 | $table->string('email')->unique(); 15 | $table->timestamp('email_verified_at')->nullable(); 16 | $table->string('password'); 17 | $table->rememberToken(); 18 | $table->timestamps(); 19 | }); 20 | } 21 | 22 | public function down(): void 23 | { 24 | Schema::dropIfExists('users'); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /tests/routes/web.php: -------------------------------------------------------------------------------- 1 | group(function (): void { 8 | Route::group([], PostResource::getRoutes()); 9 | 10 | Route::group([], UserResource::getRoutes()); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/src/ExportTest.php: -------------------------------------------------------------------------------- 1 | toBe(true); 19 | }); 20 | 21 | it('can create user', function () { 22 | expect(User::factory()->create())->toBeInstanceOf(User::class); 23 | }); 24 | 25 | it('can create post', function () { 26 | expect(Post::factory()->create())->toBeInstanceOf(Post::class); 27 | }); 28 | 29 | it('can retrieve user', function () { 30 | User::factory()->create(); 31 | expect(User::latest()->first())->toBeInstanceOf(User::class); 32 | }); 33 | 34 | it('can retrieve post', function () { 35 | Post::factory()->create(); 36 | expect(Post::latest()->first())->toBeInstanceOf(Post::class); 37 | }); 38 | 39 | it('can render post resource page', function () { 40 | $this->get(PostResource::getUrl('index'))->assertSuccessful(); 41 | }); 42 | 43 | it('can list posts', function () { 44 | $posts = Post::factory()->count(10)->create(); 45 | 46 | livewire(ListPosts::class) 47 | ->assertCanSeeTableRecords($posts); 48 | }); 49 | 50 | it('can call header action', function () { 51 | $posts = Post::factory()->count(10)->create(); 52 | 53 | livewire(ListPosts::class) 54 | ->callTableAction('export') 55 | ->assertSuccessful(); 56 | }); 57 | 58 | it('can call bulk action', function () { 59 | $posts = Post::factory()->count(10)->create(); 60 | 61 | livewire(ListPosts::class) 62 | ->callTableBulkAction('export', $posts) 63 | ->assertSuccessful(); 64 | }); 65 | 66 | foreach (FilamentExport::DEFAULT_FORMATS as $format => $label) { 67 | it("can header action call $format download", function () use ($format) { 68 | $posts = Post::factory()->count(10)->create(); 69 | 70 | $livewire = new ListPosts(); 71 | 72 | $livewire->bootedInteractsWithTable(); 73 | 74 | $action = FilamentExportHeaderAction::make('export') 75 | ->table(Table::make($livewire)); 76 | 77 | expect( 78 | FilamentExport::callDownload($action, $posts, [ 79 | 'file_name' => null, 80 | 'filter_columns' => [], 81 | 'additional_columns' => [], 82 | 'format' => "$format", 83 | 'page_orientation' => null, 84 | ]) 85 | )->toBeInstanceOf(StreamedResponse::class); 86 | }); 87 | } 88 | 89 | foreach (FilamentExport::DEFAULT_FORMATS as $format => $label) { 90 | it("can bulk action call $format download", function () use ($format) { 91 | $posts = Post::factory()->count(10)->create(); 92 | 93 | $livewire = new ListPosts(); 94 | 95 | $livewire->bootedInteractsWithTable(); 96 | 97 | $action = FilamentExportBulkAction::make('export') 98 | ->table(Table::make($livewire)); 99 | 100 | expect( 101 | FilamentExport::callDownload($action, $posts, [ 102 | 'file_name' => null, 103 | 'filter_columns' => [], 104 | 'additional_columns' => [], 105 | 'format' => "$format", 106 | 'page_orientation' => null, 107 | ]) 108 | )->toBeInstanceOf(StreamedResponse::class); 109 | }); 110 | } 111 | 112 | it('can render user resource page', function () { 113 | $this->get(UserResource::getUrl('index'))->assertSuccessful(); 114 | }); 115 | 116 | it('can list users', function () { 117 | $posts = Post::factory()->count(10)->create(); 118 | 119 | livewire(ListUsers::class) 120 | ->assertCanSeeTableRecords($posts); 121 | }); 122 | 123 | it('can view user with posts relation manager', function () { 124 | $posts = Post::factory()->count(10)->create(); 125 | 126 | $this->get(PostResource::getUrl('view', [ 127 | 'record' => $posts->first()->id, 128 | ]))->assertSuccessful(); 129 | }); 130 | 131 | it('can render relation manager', function () { 132 | Post::factory()->count(10)->create(); 133 | 134 | livewire(PostsRelationManager::class, [ 135 | 'ownerRecord' => User::latest()->first(), 136 | ])->assertSuccessful(); 137 | }); 138 | 139 | it('can call header action on relation manager', function () { 140 | Post::factory()->create(); 141 | 142 | $user = User::latest()->first(); 143 | 144 | livewire(PostsRelationManager::class, [ 145 | 'ownerRecord' => $user, 146 | ]) 147 | ->callTableAction('export') 148 | ->assertSuccessful(); 149 | }); 150 | 151 | it('can call bulk action on relation manager', function () { 152 | Post::factory()->create(); 153 | 154 | $user = User::latest()->first(); 155 | 156 | livewire(PostsRelationManager::class, [ 157 | 'ownerRecord' => $user, 158 | ]) 159 | ->callTableBulkAction('export', $user->posts) 160 | ->assertSuccessful(); 161 | }); 162 | -------------------------------------------------------------------------------- /tests/src/Filament/Resources/PostResource.php: -------------------------------------------------------------------------------- 1 | schema([ 23 | Forms\Components\TextInput::make('title')->required(), 24 | Forms\Components\MarkdownEditor::make('content'), 25 | Forms\Components\BelongsToSelect::make('user_id') 26 | ->relationship('user', 'name') 27 | ->required(), 28 | Forms\Components\TagsInput::make('tags'), 29 | Forms\Components\TextInput::make('rating') 30 | ->numeric() 31 | ->required(), 32 | ]); 33 | } 34 | 35 | public static function table(Table $table): Table 36 | { 37 | return $table 38 | ->columns([ 39 | Tables\Columns\TextColumn::make('title'), 40 | Tables\Columns\TextColumn::make('user.name'), 41 | ]) 42 | ->actions([ 43 | Tables\Actions\ViewAction::make(), 44 | Tables\Actions\EditAction::make(), 45 | ]) 46 | ->headerActions([ 47 | \AlperenErsoy\FilamentExport\Actions\FilamentExportHeaderAction::make('export'), 48 | ]) 49 | ->bulkActions([ 50 | \AlperenErsoy\FilamentExport\Actions\FilamentExportBulkAction::make('export'), 51 | Tables\Actions\DeleteBulkAction::make(), 52 | ]); 53 | } 54 | 55 | public static function getPages(): array 56 | { 57 | return [ 58 | 'index' => Pages\ListPosts::route('/'), 59 | 'create' => Pages\CreatePost::route('/create'), 60 | 'view' => Pages\ViewPost::route('/{record}'), 61 | 'edit' => Pages\EditPost::route('/{record}/edit'), 62 | ]; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/src/Filament/Resources/PostResource/Pages/CreatePost.php: -------------------------------------------------------------------------------- 1 | schema([ 24 | Forms\Components\TextInput::make('name')->required(), 25 | Forms\Components\TextInput::make('email')->required(), 26 | ]); 27 | } 28 | 29 | public static function table(Table $table): Table 30 | { 31 | return $table 32 | ->columns([ 33 | Tables\Columns\TextColumn::make('name'), 34 | Tables\Columns\TextColumn::make('email'), 35 | Tables\Columns\TextColumn::make('posts_exists') 36 | ->exists('posts') 37 | ->label('Has Posts'), 38 | Tables\Columns\TextColumn::make('posts_count') 39 | ->counts('posts') 40 | ->label('# Posts'), 41 | Tables\Columns\TextColumn::make('posts_avg_rating') 42 | ->avg('posts', 'rating') 43 | ->label('Posts Avg. Rating'), 44 | Tables\Columns\TextColumn::make('posts_max_rating') 45 | ->max('posts', 'rating') 46 | ->label('Posts Max. Rating'), 47 | Tables\Columns\TextColumn::make('posts_min_rating') 48 | ->min('posts', 'rating') 49 | ->label('Posts Min. Rating'), 50 | Tables\Columns\TextColumn::make('posts_sum_rating') 51 | ->sum('posts', 'rating') 52 | ->label('Posts Rating Sum'), 53 | ]) 54 | ->actions([ 55 | Tables\Actions\ViewAction::make(), 56 | Tables\Actions\EditAction::make(), 57 | ]) 58 | ->bulkActions([ 59 | Tables\Actions\DeleteBulkAction::make(), 60 | ]); 61 | } 62 | 63 | public static function getPages(): array 64 | { 65 | return [ 66 | 'index' => Pages\ListUsers::route('/'), 67 | 'create' => Pages\CreateUser::route('/create'), 68 | 'view' => Pages\ViewUser::route('/{record}'), 69 | 'edit' => Pages\EditUser::route('/{record}/edit'), 70 | ]; 71 | } 72 | 73 | public static function getRelations(): array 74 | { 75 | return [ 76 | PostsRelationManager::class, 77 | ]; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/src/Filament/Resources/UserResource/Pages/CreateUser.php: -------------------------------------------------------------------------------- 1 | schema([ 20 | // 21 | ]); 22 | } 23 | 24 | public static function table(Table $table): Table 25 | { 26 | return $table 27 | ->columns([ 28 | Tables\Columns\TextColumn::make('title'), 29 | Tables\Columns\TextColumn::make('user.name'), 30 | ]) 31 | ->actions([ 32 | Tables\Actions\ViewAction::make(), 33 | Tables\Actions\EditAction::make(), 34 | ]) 35 | ->headerActions([ 36 | \AlperenErsoy\FilamentExport\Actions\FilamentExportHeaderAction::make('export'), 37 | ]) 38 | ->bulkActions([ 39 | \AlperenErsoy\FilamentExport\Actions\FilamentExportBulkAction::make('export'), 40 | Tables\Actions\DeleteBulkAction::make(), 41 | ]); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/src/Models/Post.php: -------------------------------------------------------------------------------- 1 | 'array', 16 | ]; 17 | 18 | protected $guarded = []; 19 | 20 | public function user(): BelongsTo 21 | { 22 | return $this->belongsTo(User::class, 'user_id'); 23 | } 24 | 25 | protected static function newFactory() 26 | { 27 | return PostFactory::new(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/src/Models/User.php: -------------------------------------------------------------------------------- 1 | hasMany(Post::class, 'user_id'); 30 | } 31 | 32 | protected static function newFactory() 33 | { 34 | return UserFactory::new(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/src/TestCase.php: -------------------------------------------------------------------------------- 1 | actingAs(User::factory()->create()); 24 | } 25 | 26 | protected function getPackageProviders($app): array 27 | { 28 | return [ 29 | BladeHeroiconsServiceProvider::class, 30 | BladeIconsServiceProvider::class, 31 | FilamentServiceProvider::class, 32 | FormsServiceProvider::class, 33 | LivewireServiceProvider::class, 34 | NotificationsServiceProvider::class, 35 | SupportServiceProvider::class, 36 | TablesServiceProvider::class, 37 | FilamentExportServiceProvider::class, 38 | \Barryvdh\DomPDF\ServiceProvider::class, 39 | ]; 40 | } 41 | 42 | protected function defineDatabaseMigrations(): void 43 | { 44 | $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); 45 | } 46 | 47 | protected function defineRoutes($router) 48 | { 49 | require __DIR__.'/../routes/web.php'; 50 | } 51 | 52 | protected function getEnvironmentSetUp($app): void 53 | { 54 | $app['config']->set('auth.providers.users.model', User::class); 55 | } 56 | } 57 | --------------------------------------------------------------------------------