Compare commits

...

9 Commits

Author SHA1 Message Date
David
d64e9c00be Fixing some examples 2025-05-03 01:57:26 -04:00
David
9f12bc28d0 Refactor table components to use GenericTableSettings and remove deprecated classes 2025-04-25 01:19:30 -04:00
David
7466083798 New column filters examples updated 2025-04-05 00:52:34 -04:00
David
585c32d0cd Examples updated 2025-04-02 04:54:28 -04:00
David
63779f8bad Added an example with two tables in the same parent component 2025-03-31 01:19:15 -04:00
David
69a87b3a5c #FEAT
+ Added EMPTY flag to be used by column settings
2025-03-26 06:11:38 -04:00
David
be561527f7 Update custom-loader.blade.php 2025-03-18 13:41:18 -04:00
David
6319343a76 Added a condition in the "IconColumn" class 2025-03-18 02:24:12 -04:00
David
25c6b316bd #FEAT
+ Added new example about the new feature: custom column
2025-03-17 22:33:11 -04:00
35 changed files with 2630 additions and 189 deletions

17
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"C:\\xampp\\htdocs\\generic_table_examples": "${workspaceFolder}",
}
}
]
}

View File

@@ -7,8 +7,6 @@ use Livewire\Component;
class FrameComponent extends Component class FrameComponent extends Component
{ {
public function render() public function render()
{ {
return view('livewire.examples.frame-component') return view('livewire.examples.frame-component')

View File

@@ -1,18 +0,0 @@
<?php
namespace App\Livewire\Examples;
use App\Tables\TableWithMySettings;
use Livewire\Component;
class MyCustomSettingsTableComponent extends Component
{
public function render()
{
return view('livewire.examples.my-custom-settings-table-component', [
'table' => TableWithMySettings::class
])
->extends('components.layouts.app')
->section('content');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace App\Livewire\Examples;
use App\Tables\TableWithCustomColumn;
use Livewire\Component;
class TableWithCustomColumnComponent extends Component
{
public function render()
{
return view('livewire.examples.custom-tables-component',[
'table' => TableWithCustomColumn::class
])->extends('components.layouts.app')
->section('content');
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Livewire\Examples;
use App\Tables\DepartmentTable;
use App\Tables\SubDepartmentsTable;
use App\Tables\TableWithDragDropOrdering;
use Livewire\Component;
class WithTwoTablesComponent extends Component
{
public function render()
{
return view('livewire.examples.with-two-tables-component', [
'products' => TableWithDragDropOrdering::class,
'departments' => DepartmentTable::class,
'subDepartments' => SubDepartmentsTable::class
])
->extends('components.layouts.app')
->section('content');
}
public function showModal()
{
$this->dispatch('showModal');
}
}

View File

@@ -3,8 +3,12 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Department extends Model class Department extends Model
{ {
// public function group() : BelongsTo
{
return $this->belongsTo(DepartmentGroup::class, 'department_group_id');
}
} }

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class DepartmentGroup extends Model
{
//
}

View File

@@ -5,6 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Product extends Model class Product extends Model
{ {
@@ -19,4 +20,9 @@ class Product extends Model
{ {
return $this->belongsTo(SubDepartment::class); return $this->belongsTo(SubDepartment::class);
} }
public function settings() : HasOne
{
return $this->hasOne(ProductSetting::class);
}
} }

View File

@@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProductSetting extends Model
{
//
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Tables;
use App\Models\Department;
use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IDragDropReordering;
use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\GenericTableSettings;
class DepartmentTable implements IGenericTable, IDragDropReordering
{
public GenericTableSettings $tableSettings;
public string $orderingColumn = 'order';
public function __construct()
{
$columns = new ColumnCollection();
$columns->add(new Column("Id"));
$columns->add(new Column("Name"));
$columns->add(new Column("Tags"));
$columns->add(new Column("Status"));
$columns->add(new Column("Order")->sortable()->defaultSortDesc());
$this->tableSettings = new GenericTableSettings(new Department(), $columns);
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace App\Tables\Extensions;
use Closure;
use Mmt\GenericTable\Attributes\MappedRoute;
use Mmt\GenericTable\Interfaces\ICellData;
use Mmt\GenericTable\Interfaces\IColumn;
use Mmt\GenericTable\Interfaces\IColumnRenderer;
use Mmt\GenericTable\Interfaces\IRowData;
use Str;
class IconColumn implements IColumn, IColumnRenderer
{
public int $settings = 0;
public ?MappedRoute $mappedRoute = null;
public ?string $databaseColumnName = 'status';
public string $columnTitle = 'Status';
private Closure $setIconCallback;
public int $columnIndex;
public function __construct()
{
if($this->databaseColumnName == null)
$this->databaseColumnName = Str::snake($this->columnTitle);
}
public function renderCell(ICellData $cell, IRowData $row): string|null
{
$icon = 'bi bi-arrow-up-right-circle-fill';
if(isset($this->setIconCallback))
$icon = $this->setIconCallback->call($this, $row);
return <<<HTML
<div class = "w-100 d-flex justify-content-start">
<i class = "$icon me-2"></i>
</div>
HTML;
}
public function route(MappedRoute $route)
{
$this->mappedRoute = $route;
return $this;
}
public function setIconIf(Closure $callback)
{
$this->setIconCallback = $callback;
return $this;
}
public function isRelationship(): bool
{
return false;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Tables;
use App\Models\SubDepartment;
use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IDragDropReordering;
use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\GenericTableSettings;
class SubDepartmentsTable implements IGenericTable
{
public GenericTableSettings $tableSettings;
public function __construct()
{
$columns = new ColumnCollection();
$columns->add(new Column("Id", 'id as uid'));
$columns->add(new Column("Sub Department Name", 'name'));
$columns->add(new Column("Status"));
$columns->add(new Column("Department Name", 'department.name'));
$this->tableSettings = new GenericTableSettings(new SubDepartment(), $columns);
}
}

View File

@@ -3,30 +3,19 @@
namespace App\Tables; namespace App\Tables;
use App\Models\Product;
use App\Tables\Traits\WithExportableProductColumns; use App\Tables\Traits\WithExportableProductColumns;
use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Interfaces\IActionColumn; use Mmt\GenericTable\Interfaces\IActionColumn;
use Mmt\GenericTable\Interfaces\IEvent;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\EventArgs; use Mmt\GenericTable\Interfaces\IRowData;
class TableWithActionColumn implements IGenericTable, IActionColumn, IEvent class TableWithActionColumn implements IGenericTable, IActionColumn
{ {
use WithExportableProductColumns; use WithExportableProductColumns;
public Model|string $model = Product::class; public int $actionColumnIndex = 2;
public int $actionColumnIndex = -1; public function actionView(IRowData $row): \Illuminate\View\View
public function actionView(Model $item): \Illuminate\View\View
{ {
return view("tables_action_views.edit_delete_details", ['productId' => $item->id]); return view("tables_action_views.edit_delete_details", ['productId' => $row->get('name')]);
}
public function dispatchCallback(EventArgs $arguments): void
{
} }
} }

View File

@@ -2,19 +2,23 @@
namespace App\Tables; namespace App\Tables;
use App\Tables\Traits\WithColumnFormatter; use App\Models\Product;
use Mmt\GenericTable\Attributes\MappedRoute; use Mmt\GenericTable\Attributes\MappedRoute;
use Mmt\GenericTable\Components\Column; use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IDragDropReordering;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\GenericTableSettings;
class TableWithBindedRoutes implements IGenericTable class TableWithBindedRoutes implements IGenericTable, IDragDropReordering
{ {
use WithColumnFormatter; public GenericTableSettings $tableSettings;
public string $orderingColumn;
public function __construct() public function __construct()
{ {
$this->columns = ColumnCollection::make( $columns = ColumnCollection::make(
new Column('Id'), new Column('Id'),
new Column('Name'), new Column('Name'),
new Column('Description') new Column('Description')
@@ -22,6 +26,11 @@ class TableWithBindedRoutes implements IGenericTable
new Column('Price'), new Column('Price'),
new Column('Stock'), new Column('Stock'),
new Column('SubDepartment', 'subDepartment.name'), new Column('SubDepartment', 'subDepartment.name'),
new Column('Order')->hide()
);
$this->tableSettings = new GenericTableSettings(
Product::class, $columns
); );
} }
} }

View File

@@ -3,7 +3,6 @@
namespace App\Tables; namespace App\Tables;
use App\Models\Product; use App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Components\Column; use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IBulkAction; use Mmt\GenericTable\Interfaces\IBulkAction;
@@ -12,20 +11,17 @@ use Mmt\GenericTable\Support\BulkAction;
use Mmt\GenericTable\Support\BulkActionCollection; use Mmt\GenericTable\Support\BulkActionCollection;
use Mmt\GenericTable\Support\BulkActionGroup; use Mmt\GenericTable\Support\BulkActionGroup;
use Mmt\GenericTable\Support\BulkActionSettings; use Mmt\GenericTable\Support\BulkActionSettings;
use Mmt\GenericTable\Support\GenericTableSettings;
class TableWithBulkActions implements IGenericTable, IBulkAction class TableWithBulkActions implements IGenericTable, IBulkAction
{ {
public Model|string $model; public GenericTableSettings $tableSettings;
public ColumnCollection $columns;
public BulkActionCollection $bulkActionCollection; public BulkActionCollection $bulkActionCollection;
public function __construct() public function __construct()
{ {
$this->model = new Product(); $columns = ColumnCollection::make(
$this->columns = ColumnCollection::make(
new Column('Id'), new Column('Id'),
new Column('Description'), new Column('Description'),
new Column('Price'), new Column('Price'),
@@ -48,6 +44,8 @@ class TableWithBulkActions implements IGenericTable, IBulkAction
) )
) )
); );
$this->tableSettings = new GenericTableSettings(Product::class, $columns);
} }

View File

@@ -3,9 +3,17 @@
namespace App\Tables; namespace App\Tables;
use App\Tables\Traits\WithColumnFormatter; use App\Tables\Traits\WithColumnFormatter;
use Mmt\GenericTable\Interfaces\IExportable;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
class TableWithColumnFormatter implements IGenericTable class TableWithColumnFormatter implements IGenericTable, IExportable
{ {
use WithColumnFormatter; use WithColumnFormatter;
public function onExport(\Mmt\GenericTable\Support\ExportEventArgs $args): \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse
{
$args->useStripTags = true;
$args->query->take(5);
return $args->export();
}
} }

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Tables;
use App\Models\Product;
use App\Tables\Extensions\IconColumn;
use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Interfaces\IRowData;
use Mmt\GenericTable\Support\GenericTableSettings;
class TableWithCustomColumn implements IGenericTable
{
public GenericTableSettings $tableSettings;
public function __construct()
{
$icons = require_once('Extensions/bootstrap_icons.php');
$columns = new ColumnCollection();
$columns->add(new Column('Id'));
$columns->add(new Column('Name'));
$columns->add(new Column('Description'));
$columns->add(new IconColumn()->setIconIf(function(IRowData $rowModel) use($icons) {
if($rowModel->get('status') == 'discontinued') {
return $icons['bag-check'] . ' text-success';
}
else {
return $icons['bag-x'] . ' text-danger';
}
}));
$this->tableSettings = new GenericTableSettings(new Product(), $columns);
}
}

View File

@@ -3,18 +3,44 @@
namespace App\Tables; namespace App\Tables;
use App\Models\Product; use App\Models\Product;
use App\Tables\Traits\WithColumnFormatter; use Mmt\GenericTable\Components\Column;
use Illuminate\Database\Eloquent\Model; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Enums\ColumnSettingFlags;
use Mmt\GenericTable\Interfaces\IColumnFilter;
use Mmt\GenericTable\Interfaces\IDragDropReordering; use Mmt\GenericTable\Interfaces\IDragDropReordering;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\FilterCollection;
use Mmt\GenericTable\Support\GenericTableSettings;
use Mmt\GenericTable\Support\SingleFilter;
class TableWithDragDropOrdering implements IGenericTable, IDragDropReordering class TableWithDragDropOrdering implements IGenericTable, IDragDropReordering, IColumnFilter
{ {
use WithColumnFormatter; public GenericTableSettings $tableSettings;
public string $Order;
public Model|string $model = Product::class;
public string $orderingColumn = 'order'; public string $orderingColumn = 'order';
public FilterCollection $filters;
public bool $useBuilder;
public function __construct()
{
$columns = ColumnCollection::make(
new Column('Id'),
new Column('Name'),
new Column('Description'),
new Column('Price'),
new Column('Stock'),
new Column('Order')->withSettings(ColumnSettingFlags::DEFAULT_SORT_DESC)
);
$this->tableSettings = new GenericTableSettings(Product::class, $columns);
$this->filters = new FilterCollection(
SingleFilter::make('name', [
'Yes' => 'yes',
'No' => 'No',
])
);
}
} }

View File

@@ -3,23 +3,55 @@
namespace App\Tables; namespace App\Tables;
use App\Models\Product; use App\Models\Product;
use App\Tables\Traits\WithExportableProductColumns;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Mmt\GenericTable\Attributes\CellFormatter;
use Mmt\GenericTable\Components\Cell;
use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Enums\ColumnSettingFlags;
use Mmt\GenericTable\Interfaces\IExportable; use Mmt\GenericTable\Interfaces\IExportable;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\ExportEventArgs; use Mmt\GenericTable\Support\ExportEventArgs;
use Mmt\GenericTable\Support\ExportSettings; use Mmt\GenericTable\Support\GenericTableSettings;
use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\BinaryFileResponse;
class TableWithExport implements IGenericTable, IExportable class TableWithExport implements IGenericTable, IExportable
{ {
use WithExportableProductColumns; public GenericTableSettings $tableSettings;
public function __construct()
{
$columns = ColumnCollection::make(
new Column('Name')->withSettings(ColumnSettingFlags::EXPORTABLE),
new Column('Description')->withSettings(ColumnSettingFlags::EXPORTABLE),
new Column('Price')->withSettings(ColumnSettingFlags::EXPORTABLE),
new Column('Stock')->withSettings(ColumnSettingFlags::EXPORTABLE)
);
$this->tableSettings = new GenericTableSettings(
Product::class,
$columns
);
}
public function onExport(ExportEventArgs $args) : BinaryFileResponse|Response public function onExport(ExportEventArgs $args) : BinaryFileResponse|Response
{ {
$args->query->take(5);
$args->settings->useFormatters = true;
$args->settings->fileName = 'products'; $args->settings->fileName = 'products';
$args->useStripTags = true;
return $args->export(); return $args->export();
} }
#[CellFormatter('price')]
public function priceFormatter(Cell $cell)
{
return '$'.$cell->value;
}
#[CellFormatter('name')]
public function nameFormatter(Cell $cell)
{
return '<i>La</i> ' . $cell->value;
}
} }

View File

@@ -4,34 +4,31 @@ namespace App\Tables;
use App\Models\Product; use App\Models\Product;
use Illuminate\Database\Eloquent\Model; use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Enums\CommonDateFilter; use Mmt\GenericTable\Enums\CommonDateFilter;
use Mmt\GenericTable\Interfaces\IColumnFilter;
use Mmt\GenericTable\Interfaces\IDateRangeFilter; use Mmt\GenericTable\Interfaces\IDateRangeFilter;
use Mmt\GenericTable\Interfaces\IDragDropReordering; use Mmt\GenericTable\Interfaces\IDragDropReordering;
use Mmt\GenericTable\Interfaces\IEvent; use Mmt\GenericTable\Interfaces\IEvent;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Interfaces\ILoadingIndicator; use Mmt\GenericTable\Interfaces\ILoadingIndicator;
use Mmt\GenericTable\Interfaces\IMultiSelectionFilter; use Mmt\GenericTable\Interfaces\IRowData;
use Mmt\GenericTable\Interfaces\ISingleSelectionFilter;
use Mmt\GenericTable\Support\DatabaseEvent; use Mmt\GenericTable\Support\DatabaseEvent;
use Mmt\GenericTable\Support\DateFilterSettings; use Mmt\GenericTable\Support\DateFilterSettings;
use Mmt\GenericTable\Support\EventArgs; use Mmt\GenericTable\Support\EventArgs;
use Mmt\GenericTable\Support\SelectionFilterSettings; use Mmt\GenericTable\Support\FilterCollection;
use Mmt\GenericTable\Support\GenericTableSettings;
use Mmt\GenericTable\Support\MultiFilter;
use Mmt\GenericTable\Support\SingleFilter;
class TableWithFilters implements IGenericTable, IEvent, IDateRangeFilter, ISingleSelectionFilter, IMultiSelectionFilter, IDragDropReordering, ILoadingIndicator class TableWithFilters implements IGenericTable, IEvent, IDateRangeFilter, IColumnFilter, IDragDropReordering, ILoadingIndicator
{ {
public Model|string $model = Product::class; public GenericTableSettings $tableSettings;
public ColumnCollection $columns;
public DateFilterSettings $dateFilterSettings; public DateFilterSettings $dateFilterSettings;
public SelectionFilterSettings $singleSelectionFilterSettings; public FilterCollection $filters;
public SelectionFilterSettings $multiSelectionFilterSettings;
public bool $isTableLoaderEnabled = true;
public string $orderingColumn = 'order'; public string $orderingColumn = 'order';
@@ -43,15 +40,32 @@ class TableWithFilters implements IGenericTable, IEvent, IDateRangeFilter, ISing
CommonDateFilter::LAST_3_MONTHS CommonDateFilter::LAST_3_MONTHS
); );
$this->singleSelectionFilterSettings = new SelectionFilterSettings('status') $columns = ColumnCollection::make(
->add('Out of stock', 'out_of_stock') new Column('Id')->hookFormatter(fn(IRowData $row) => '#'.$row->get('id')),
->add('Discontinued', 'discontinued') new Column('Order')->sortable()->defaultSort(),
->add('Available', 'available'); new Column('Name'),
new Column('Price'),
new Column('Status')->hide()
);
$this->multiSelectionFilterSettings = new SelectionFilterSettings('name') $this->filters = new FilterCollection(
->add('Be a man', 'quod 36840466')
->add('Do the right', 'blanditiis 469800') SingleFilter::make('status', [
->add('Things happens', 'tempore 71086'); 'Out of stock' => 'out_of_stock',
'Discontinued' => 'discontinued',
'Available' => 'available',
]),
MultiFilter::make('name', [
'Client-1' => 'laborum 505',
'Client-2' => 'atque 38829',
'Client-3' => 'rem 61603388',
])
);
$this->tableSettings = new GenericTableSettings(
Product::class, $columns
);
} }
@@ -68,8 +82,8 @@ class TableWithFilters implements IGenericTable, IEvent, IDateRangeFilter, ISing
public function tableLoadingIndicatorView(): \Illuminate\View\View public function tableLoadingIndicatorView(string $id): \Illuminate\View\View
{ {
return view('custom-loader'); return view('custom-loader', ['genericId' => $id]);
} }
} }

View File

@@ -1,54 +0,0 @@
<?php
namespace App\Tables;
use App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Date;
use Mmt\GenericTable\Attributes\BulkAction;
use Mmt\GenericTable\Attributes\Column;
use Mmt\GenericTable\Attributes\ColumnFilter;
use Mmt\GenericTable\Attributes\ColumnSettings;
use Mmt\GenericTable\Attributes\MappedColumn;
use Mmt\GenericTable\Enums\ColumnSettingFlags;
use Mmt\GenericTable\Enums\CommonDateFilter;
use Mmt\GenericTable\Enums\FilterType;
use Mmt\GenericTable\Interfaces\IDateRangeFilter;
use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\DateFilterSettings;
class TableWithMySettings implements IGenericTable
{
public Model|string $model = Product::class;
public DateFilterSettings $dateRanges;
#[MappedColumn]
public int $Id;
#[MappedColumn]
public string $Name;
#[MappedColumn('subDepartment.department.name')]
public string $Department;
#[MappedColumn]
public string $CreatedAt;
// #[ColumnFilter('created_at', FilterType::DATE_RANGE)]
// public function sijsjm()
// {
// return setFlags(
// CommonDateFilter::LAST_3_MONTHS,
// CommonDateFilter::LAST_3_MONTHS,
// CommonDateFilter::LAST_3_MONTHS
// );
// }
}

View File

@@ -2,10 +2,7 @@
namespace App\Tables; namespace App\Tables;
use App\Models\Product;
use App\Tables\Traits\WithColumnFormatter; use App\Tables\Traits\WithColumnFormatter;
use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Enums\PaginationRack;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Interfaces\IPaginationRack; use Mmt\GenericTable\Interfaces\IPaginationRack;
use Mmt\GenericTable\Interfaces\IRowsPerPage; use Mmt\GenericTable\Interfaces\IRowsPerPage;
@@ -13,17 +10,4 @@ use Mmt\GenericTable\Interfaces\IRowsPerPage;
class TableWithPaginationSettings implements IGenericTable, IPaginationRack, IRowsPerPage class TableWithPaginationSettings implements IGenericTable, IPaginationRack, IRowsPerPage
{ {
use WithColumnFormatter; use WithColumnFormatter;
public Model|string $model = Product::class;
public int $paginationRack = 0;
public int $rowsPerPage = 10;
public array $rowsPerPageOptions = [10,20,40,60,80];
public function __construct()
{
PaginationRack::addFlags($this->paginationRack, PaginationRack::TOP, PaginationRack::BOTTOM);
}
} }

View File

@@ -3,27 +3,39 @@
namespace App\Tables; namespace App\Tables;
use App\Models\Product; use App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Components\Column; use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IExportable;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\GenericTableSettings;
class TableWithRelationships implements IGenericTable class TableWithRelationships implements IGenericTable, IExportable
{ {
public Model|string $model; public GenericTableSettings $tableSettings;
public ColumnCollection $columns;
public function __construct() public function __construct()
{ {
$this->model = new Product(); $columns = ColumnCollection::make(
new Column('Product Name', 'name')
->searchable()
->sortable(),
$this->columns = new ColumnCollection()->add( new Column('Department Name', 'subDepartment.department.name')
new Column('Name'), ->searchable()
new Column('Department', 'subDepartment.department.name'), ->sortable(),
new Column('SubDepartment', 'subDepartment.name'),
new Column('SubDepartment Name', 'subDepartment.name')
->searchable()
->exportable()
->sortable(),
); );
$this->tableSettings = new GenericTableSettings(new Product(), $columns);
} }
public function onExport(\Mmt\GenericTable\Support\ExportEventArgs $args): \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse
{
$args->query->take(5);
return $args->export();
}
} }

View File

@@ -6,10 +6,16 @@ use App\Models\Product;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Interfaces\IGenericTable; use Mmt\GenericTable\Interfaces\IGenericTable;
use Mmt\GenericTable\Support\GenericTableSettings;
class TableWithnNoSettings implements IGenericTable class TableWithnNoSettings implements IGenericTable
{ {
public Model|string $model = Product::class; public GenericTableSettings $tableSettings;
public ColumnCollection $columns; public function __construct()
{
$this->tableSettings = new GenericTableSettings(
Product::class
);
}
} }

View File

@@ -3,41 +3,56 @@
namespace App\Tables\Traits; namespace App\Tables\Traits;
use App\Models\Product; use App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Attributes\CellFormatter; use Mmt\GenericTable\Attributes\CellFormatter;
use Mmt\GenericTable\Attributes\MappedColumn;
use Mmt\GenericTable\Components\Column; use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Enums\PaginationRack;
use Mmt\GenericTable\Interfaces\ICellData;
use Mmt\GenericTable\Interfaces\IRowData;
use Mmt\GenericTable\Support\GenericTableSettings;
trait WithColumnFormatter trait WithColumnFormatter
{ {
public Model|string $model = Product::class; public GenericTableSettings $tableSettings;
public ColumnCollection $columns; public int $paginationRack = 0;
public int $rowsPerPage = 10;
public array $rowsPerPageOptions = [10,20,40,60,80];
public function __construct() public function __construct()
{ {
$this->columns = ColumnCollection::make( $columns = ColumnCollection::make(
new Column('Id'), new Column('Id'),
new Column('Name'), new Column('Name'),
new Column('Description'), new Column('Description'),
new Column('Price'), new Column('Price'),
new Column('Stock'), new Column('Stock'),
new Column('SubDepartment', 'subDepartment.name'), new Column('SubDepartment', 'subDepartment.name'),
new Column('Empty Column')->empty(),
new Column('Empty Hook')->empty()->hookFormatter(fn(IRowData $row) => $this->emptyCol($row)),
); );
$this->tableSettings = new GenericTableSettings(Product::class, $columns);
PaginationRack::addFlags($this->paginationRack, PaginationRack::TOP, PaginationRack::BOTTOM);
} }
public function emptyCol(IRowData $row)
{
return '<i class = "text-danger">'.$row->get('id').'</i>';
}
#[CellFormatter('price')] #[CellFormatter('price')]
public function priceFormatter(Model $modelItem) public function priceFormatter(ICellData $cell, IRowData $row)
{ {
return "<b class = 'text-primary'>\$</b> {$modelItem->price}"; return "<b class = 'text-primary'>\$</b> {$cell->value}";
} }
#[CellFormatter('id')] #[CellFormatter('id')]
public function idFormatter(Model $modelItem) public function idFormatter(ICellData $cell, IRowData $row)
{ {
return '<b class = "text-primary">#</b> '.$modelItem->id; return '<b class = "text-primary">#</b> '.$cell->value;
} }
} }

View File

@@ -3,24 +3,27 @@
namespace App\Tables\Traits; namespace App\Tables\Traits;
use App\Models\Product; use App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use Mmt\GenericTable\Components\Column; use Mmt\GenericTable\Components\Column;
use Mmt\GenericTable\Components\ColumnCollection; use Mmt\GenericTable\Components\ColumnCollection;
use Mmt\GenericTable\Enums\ColumnSettingFlags; use Mmt\GenericTable\Enums\ColumnSettingFlags;
use Mmt\GenericTable\Support\GenericTableSettings;
trait WithExportableProductColumns trait WithExportableProductColumns
{ {
public Model|string $model = Product::class; public GenericTableSettings $tableSettings;
public ColumnCollection $columns;
public function __construct() public function __construct()
{ {
$this->columns = ColumnCollection::make( $columns = ColumnCollection::make(
new Column('Name')->withSettings(ColumnSettingFlags::EXPORTABLE), new Column('Name')->withSettings(ColumnSettingFlags::EXPORTABLE),
new Column('Description')->withSettings(ColumnSettingFlags::EXPORTABLE), new Column('Description')->withSettings(ColumnSettingFlags::EXPORTABLE),
new Column('Price')->withSettings(ColumnSettingFlags::EXPORTABLE), new Column('Price')->withSettings(ColumnSettingFlags::EXPORTABLE),
new Column('Stock')->withSettings(ColumnSettingFlags::EXPORTABLE) new Column('Stock')->withSettings(ColumnSettingFlags::EXPORTABLE)
); );
$this->tableSettings = new GenericTableSettings(
Product::class,
$columns
);
} }
} }

View File

@@ -10,11 +10,15 @@
"laravel/framework": "^11.31", "laravel/framework": "^11.31",
"laravel/tinker": "^2.9", "laravel/tinker": "^2.9",
"livewire/livewire": "^3.5", "livewire/livewire": "^3.5",
"maatwebsite/excel": "^3.1" "maatwebsite/excel": "^3.1",
"mmt/generic_table": "dev-main"
}, },
"repositories": [{ "repositories": [{
"type":"path", "type":"path",
"url": "packages/mmt/generic_table" "url": "packages/mmt/generic_table",
"options": {
"symlink": true
}
}], }],
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.14", "barryvdh/laravel-debugbar": "^3.14",
@@ -74,6 +78,6 @@
"php-http/discovery": true "php-http/discovery": true
} }
}, },
"minimum-stability": "stable", "minimum-stability": "dev",
"prefer-stable": true "prefer-stable": true
} }

49
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "f01bce9daeec532ed6677dff2f53a64a", "content-hash": "cbca1116f23b7ddc2f9838738429a903",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@@ -2569,6 +2569,47 @@
}, },
"time": "2022-12-02T22:17:43+00:00" "time": "2022-12-02T22:17:43+00:00"
}, },
{
"name": "mmt/generic_table",
"version": "dev-main",
"dist": {
"type": "path",
"url": "packages/mmt/generic_table",
"reference": "bcc861502469bcad624f3b2c16ef482cca81825c"
},
"require": {
"illuminate/support": "^11.0",
"livewire/livewire": "^3.5",
"php": ">=8.4"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Mmt\\GenericTable\\ServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Mmt\\GenericTable\\": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "David",
"email": "75149259+TitanDvd@users.noreply.github.com"
}
],
"description": "Generic table for Livewire + Laravel",
"transport-options": {
"symlink": true,
"relative": true
}
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "3.8.1", "version": "3.8.1",
@@ -9835,8 +9876,10 @@
} }
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "dev",
"stability-flags": {}, "stability-flags": {
"mmt/generic_table": 20
},
"prefer-stable": true, "prefer-stable": true,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {

View File

@@ -6,6 +6,7 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title> <title>Document</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
</head> </head>
<body> <body>
<div class="container"> <div class="container">
@@ -20,6 +21,8 @@
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
@yield('js')
</body> </body>
</html> </html>

View File

@@ -1,4 +1,4 @@
<div class="position-absolute top-0 start-0 w-100 h-100" style="display:none; background: rgba(0, 0, 0, 0.5)" id = "generic_table_loader"> <div class="position-absolute top-0 start-0 w-100 h-100" style="display:none; background: rgba(0, 0, 0, 0.5); z-index: 100;" id = "{{ $genericId }}_loading_indicator">
<div class="d-flex h-100"> <div class="d-flex h-100">
<div class="m-auto d-flex flex-column"> <div class="m-auto d-flex flex-column">
<div class="spinner-border mx-auto text-primary" role="status"></div> <div class="spinner-border mx-auto text-primary" role="status"></div>

View File

@@ -0,0 +1,3 @@
<div>
@generic_table($table)
</div>

View File

@@ -15,6 +15,8 @@
<li><a href="{{ route('with_drag_drop_ordering') }}">Drag and Drop Ordering</a></li> <li><a href="{{ route('with_drag_drop_ordering') }}">Drag and Drop Ordering</a></li>
<li><a href="{{ route('with_bulk_actions') }}">Bulk Actions</a></li> <li><a href="{{ route('with_bulk_actions') }}">Bulk Actions</a></li>
<li><a href="{{ route('with_relationships') }}">Relationships</a></li> <li><a href="{{ route('with_relationships') }}">Relationships</a></li>
<li><a href="{{ route('with_custom_column') }}">Custom Column</a></li>
<li><a href="{{ route('many_tables') }}">Many Tables</a></li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,56 @@
<div>
<div class="modal fade" tabindex="-1" id = "subDepartments" wire:ignore.self>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Sub Departamentos</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
@generic_table($subDepartments)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<div class="row g-3">
<div class="col-12">
<button class="btn btn-primary" wire:click = "showModal">See sub departments</button>
</div>
<div class="col-7">
<div class="card">
<div class="card-body p-0">
@generic_table($products)
</div>
</div>
</div>
<div class="col-5">
<div class="card">
<div class="card-body p-0">
@generic_table($departments)
</div>
</div>
</div>
</div>
{{-- @script --}}
{{-- @endscript --}}
</div>
@section('js')
<script>
document.addEventListener('livewire:initialized', () => {
@this.on('showModal', () => {
const myModal = new bootstrap.Modal('#subDepartments');
myModal.show();
})
})
</script>
@endsection

View File

@@ -6,12 +6,14 @@ use App\Livewire\Examples\TableWithActionColumnComponent;
use App\Livewire\Examples\TableWithBindedRoutesComponent; use App\Livewire\Examples\TableWithBindedRoutesComponent;
use App\Livewire\Examples\TableWithBulkActionsComponent; use App\Livewire\Examples\TableWithBulkActionsComponent;
use App\Livewire\Examples\TableWithColumnFormatterComponent; use App\Livewire\Examples\TableWithColumnFormatterComponent;
use App\Livewire\Examples\TableWithCustomColumnComponent;
use App\Livewire\Examples\TableWithDragDropOrderingComponent; use App\Livewire\Examples\TableWithDragDropOrderingComponent;
use App\Livewire\Examples\TableWithExportComponent; use App\Livewire\Examples\TableWithExportComponent;
use App\Livewire\Examples\TableWithFiltersComponent; use App\Livewire\Examples\TableWithFiltersComponent;
use App\Livewire\Examples\TableWithNoSettingsComponent; use App\Livewire\Examples\TableWithNoSettingsComponent;
use App\Livewire\Examples\TableWithPaginationSettingsComponent; use App\Livewire\Examples\TableWithPaginationSettingsComponent;
use App\Livewire\Examples\TableWithRelationshipsComponent; use App\Livewire\Examples\TableWithRelationshipsComponent;
use App\Livewire\Examples\WithTwoTablesComponent;
use App\Livewire\Test\ParentComponent; use App\Livewire\Test\ParentComponent;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@@ -27,6 +29,8 @@ Route::get('/with_pagination_settings', TableWithPaginationSettingsComponent::cl
Route::get('/with_drag_drop_ordering', TableWithDragDropOrderingComponent::class)->name('with_drag_drop_ordering'); Route::get('/with_drag_drop_ordering', TableWithDragDropOrderingComponent::class)->name('with_drag_drop_ordering');
Route::get('/with_bulk_actions', TableWithBulkActionsComponent::class)->name('with_bulk_actions'); Route::get('/with_bulk_actions', TableWithBulkActionsComponent::class)->name('with_bulk_actions');
Route::get('/with_relationships', TableWithRelationshipsComponent::class)->name('with_relationships'); Route::get('/with_relationships', TableWithRelationshipsComponent::class)->name('with_relationships');
Route::get('/with_custom_column', TableWithCustomColumnComponent::class)->name('with_custom_column');
Route::get('/many_tables', WithTwoTablesComponent::class)->name('many_tables');
Route::get('test', ParentComponent::class); Route::get('test', ParentComponent::class);