├── .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 | 
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 |
15 | {{ $column->getLabel() }}
16 | |
17 | @endforeach
18 |
19 | @foreach ($getRows() as $row)
20 |
21 | @foreach ($getAllColumns() as $column)
22 |
23 | {{ $row[$column->getName()] }}
24 | |
25 | @endforeach
26 |
27 | @endforeach
28 |
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 |
48 | {{ $column->getLabel() }}
49 | |
50 | @endforeach
51 |
52 | @foreach ($rows as $row)
53 |
54 | @foreach ($columns as $column)
55 |
56 | {{ $row[$column->getName()] }}
57 | |
58 | @endforeach
59 |
60 | @endforeach
61 |
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 |
54 | {{ $column->getLabel() }}
55 | |
56 | @endforeach
57 |
58 | @foreach ($rows as $row)
59 |
60 | @foreach ($columns as $column)
61 |
62 | {{ $row[$column->getName()] }}
63 | |
64 | @endforeach
65 |
66 | @endforeach
67 |
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 |
--------------------------------------------------------------------------------