diff --git a/CHANGELOG.md b/CHANGELOG.md index 5adab2fbc..8b412b286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to `laravel-livewire-tables` will be documented in this file +## [v3.4.17] - 2024-09-01 +### New Features +- Add hide table option by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1914 +- Add column select session methods by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1913 +- Save filter selection to session (BETA) by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1910 + +### Tweaks +- Use Core Attribute Bag by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1916 +- Use Core HasTheme Methods by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1915 + ## [v3.4.16] - 2024-08-27 ### New Features - Add icon column by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1902 diff --git a/docs/filters/available-methods.md b/docs/filters/available-methods.md index 5dd8c42f5..f8845dbaf 100644 --- a/docs/filters/available-methods.md +++ b/docs/filters/available-methods.md @@ -182,6 +182,30 @@ public function configure(): void } ``` +### storeFiltersInSessionEnabled + +Optional behaviour - stores filter values in the session (specific to table - based on the table name) + +#### Exercise Caution +If re-using the same Livewire Table Component multiple times in your site, with the same table name, this may cause clashes in filter values + +```php +public function configure(): void +{ + $this->storeFiltersInSessionEnabled(); +} +``` +### storeFiltersInSessionDisabled + +Default behaviour - does not store filters in the session + +```php +public function configure(): void +{ + $this->storeFiltersInSessionDisabled(); +} +``` + ---- diff --git a/docs/misc/hiding-the-table.md b/docs/misc/hiding-the-table.md new file mode 100644 index 000000000..b607ff52b --- /dev/null +++ b/docs/misc/hiding-the-table.md @@ -0,0 +1,78 @@ +--- +title: Hiding The Table (beta) +weight: 8 +--- + +You may wish to hide the table on load. To do so, you should use the following in the mount method. Note that this is in mount, not boot nor configure! + +```php + public function mount() + { + $this->setShouldBeHidden(); + } +``` + +### Using Events To Display/Hide + +For example, you may have a "Sales" table that you wish to hide by default: +```php +class SalesTable extends DataTableComponent +{ + public string $tableName = 'sales'; // Required to keep the call specific + + public function mount() + { + $this->setShouldBeHidden(); // Defaults the table to be hidden, note that this is in MOUNT and not CONFIGURE + } + + // Configure/Columns/Filters etc +} +``` + +The Table allows for different approaches, out-of-the-box it supports the more efficient client-side listeners. + +However - should you wish to use Livewire listeners in your table component, for example if you wish to pass more detail into the Table then you can: + +```php + #[On('showTable.{tableName}')] + public function showTable(): void + { + $this->setShouldBeDisplayed(); + } + + #[On('hideTable.{tableName}')] + public function hideTable(): void + { + $this->setShouldBeHidden(); + } +``` + + +### Secondary Table +Below are the two approaches. Note that you can customise the Livewire "On" to pass additional details should you wish. + +#### Using Client Side Listeners +```php + Column::make('Show') + ->label( + fn($row, Column $column) => "" + )->html(), + Column::make('Hide') + ->label( + fn($row, Column $column) => "" + )->html(), +``` + + +#### Using Livewire "On" Style Listeners: +```php + Column::make('Show') + ->label( + fn($row, Column $column) => "" + )->html(), + Column::make('Hide') + ->label( + fn($row, Column $column) => "" + )->html(), + +``` \ No newline at end of file diff --git a/resources/js/laravel-livewire-tables.js b/resources/js/laravel-livewire-tables.js index 306c3857d..6177ea37f 100644 --- a/resources/js/laravel-livewire-tables.js +++ b/resources/js/laravel-livewire-tables.js @@ -2,7 +2,13 @@ document.addEventListener('alpine:init', () => { - Alpine.data('laravellivewiretable', (wire, showBulkActionsAlpine, tableID, primaryKeyName) => ({ + Alpine.data('laravellivewiretable', (wire) => ({ + tableId: '', + showBulkActionsAlpine: false, + primaryKeyName: '', + shouldBeDisplayed: wire.entangle('shouldBeDisplayed'), + tableName: wire.entangle('tableName'), + dataTableFingerprint: wire.entangle('dataTableFingerprint'), listeners: [], childElementOpen: false, filtersOpen: wire.entangle('filterSlideDownDefaultVisible'), @@ -67,7 +73,7 @@ document.addEventListener('alpine:init', () => { element.classList.remove("laravel-livewire-table-dragging"); let originalPosition = element.rowIndex; let newPosition = target.rowIndex; - let table = document.getElementById(tableID); + let table = document.getElementById(this.tableId); let loopStart = originalPosition; if (event.offsetY > (target.getBoundingClientRect().height / 2)) { parent.insertBefore(element, target.nextSibling); @@ -123,17 +129,17 @@ document.addEventListener('alpine:init', () => { }, updateOrderedItems() { - let table = document.getElementById(tableID); + let table = document.getElementById(this.tableId); let orderedRows = []; for (let i = 1, row; row = table.rows[i]; i++) { - orderedRows.push({ [primaryKeyName]: row.getAttribute('rowpk'), [this.defaultReorderColumn]: i }); + orderedRows.push({ [this.primaryKeyName]: row.getAttribute('rowpk'), [this.defaultReorderColumn]: i }); } wire.storeReorder(orderedRows); }, setupEvenOddClasses() { if (this.evenNotInOdd.length === undefined || this.evenNotInOdd.length == 0 || this.oddNotInEven.length === undefined || this.oddNotInEven.length == 0) { - let tbody = document.getElementById(tableID).getElementsByTagName('tbody')[0]; + let tbody = document.getElementById(this.tableId).getElementsByTagName('tbody')[0]; let evenRowClassArray = []; let oddRowClassArray = []; @@ -149,7 +155,7 @@ document.addEventListener('alpine:init', () => { } }, toggleSelectAll() { - if (!showBulkActionsAlpine) { + if (!this.showBulkActionsAlpine) { return; } @@ -168,14 +174,14 @@ document.addEventListener('alpine:init', () => { } }, setAllItemsSelected() { - if (!showBulkActionsAlpine) { + if (!this.showBulkActionsAlpine) { return; } this.selectAllStatus = true; this.selectAllOnPage(); }, setAllSelected() { - if (!showBulkActionsAlpine) { + if (!this.showBulkActionsAlpine) { return; } if (this.delaySelectAll) @@ -189,14 +195,14 @@ document.addEventListener('alpine:init', () => { } }, clearSelected() { - if (!showBulkActionsAlpine) { + if (!this.showBulkActionsAlpine) { return; } this.selectAllStatus = false; wire.clearSelected(); }, selectAllOnPage() { - if (!showBulkActionsAlpine) { + if (!this.showBulkActionsAlpine) { return; } @@ -207,6 +213,36 @@ document.addEventListener('alpine:init', () => { } this.selectedItems = [...new Set(tempSelectedItems)]; }, + setTableId(tableId) + { + this.tableId = tableId; + }, + setAlpineBulkActions(showBulkActionsAlpine) + { + this.showBulkActionsAlpine = showBulkActionsAlpine; + }, + setPrimaryKeyName(primaryKeyName) + { + this.primaryKeyName = primaryKeyName; + }, + showTable(event) + { + let eventTableName = event.detail.tableName ?? ''; + let eventTableFingerprint = event.detail.tableFingerpint ?? ''; + + if (((eventTableName ?? '') != '' && eventTableName === this.tableName) || (eventTableFingerprint != '' && eventTableFingerpint === this.dataTableFingerprint)) { + this.shouldBeDisplayed = true; + } + }, + hideTable(event) + { + let eventTableName = event.detail.tableName ?? ''; + let eventTableFingerprint = event.detail.tableFingerpint ?? ''; + + if ((eventTableName != '' && eventTableName === this.tableName) || (eventTableFingerprint != '' && eventTableFingerpint === this.dataTableFingerprint)) { + this.shouldBeDisplayed = false; + } + }, destroy() { this.listeners.forEach((listener) => { listener(); @@ -373,6 +409,7 @@ document.addEventListener('alpine:init', () => { Alpine.data('tableWrapper', (wire, showBulkActionsAlpine) => ({ + shouldBeDisplayed: wire.entangle('shouldBeDisplayed'), listeners: [], childElementOpen: false, filtersOpen: wire.entangle('filterSlideDownDefaultVisible'), diff --git a/resources/js/laravel-livewire-tables.min.js b/resources/js/laravel-livewire-tables.min.js index 35cecdd4f..a4fb93695 100644 --- a/resources/js/laravel-livewire-tables.min.js +++ b/resources/js/laravel-livewire-tables.min.js @@ -1 +1 @@ -document.addEventListener("alpine:init",()=>{Alpine.data("laravellivewiretable",(e,t,l,i)=>({listeners:[],childElementOpen:!1,filtersOpen:e.entangle("filterSlideDownDefaultVisible"),paginationCurrentCount:e.entangle("paginationCurrentCount"),paginationTotalItemCount:e.entangle("paginationTotalItemCount"),paginationCurrentItems:e.entangle("paginationCurrentItems"),selectedItems:e.entangle("selected"),selectAllStatus:e.entangle("selectAll"),delaySelectAll:e.entangle("delaySelectAll"),hideBulkActionsWhenEmpty:e.entangle("hideBulkActionsWhenEmpty"),dragging:!1,reorderEnabled:!1,sourceID:"",targetID:"",evenRowClasses:"",oddRowClasses:"",currentlyHighlightedElement:"",evenRowClassArray:{},oddRowClassArray:{},evenNotInOdd:{},oddNotInEven:{},orderedRows:[],defaultReorderColumn:e.get("defaultReorderColumn"),reorderStatus:e.entangle("reorderStatus"),currentlyReorderingStatus:e.entangle("currentlyReorderingStatus"),hideReorderColumnUnlessReorderingStatus:e.entangle("hideReorderColumnUnlessReorderingStatus"),reorderDisplayColumn:e.entangle("reorderDisplayColumn"),dragStart(e){this.$nextTick(()=>{this.setupEvenOddClasses()}),this.sourceID=e.target.id,e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",e.target.id),e.target.classList.add("laravel-livewire-tables-dragging")},dragOverEvent(e){"object"==typeof this.currentlyHighlightedElement&&this.currentlyHighlightedElement.classList.remove("laravel-livewire-tables-highlight-bottom","laravel-livewire-tables-highlight-top");let t=e.target.closest("tr");this.currentlyHighlightedElement=t,e.offsetYt.getBoundingClientRect().height/2?i.insertBefore(s,t.nextSibling):i.insertBefore(s,t),r{this.setupEvenOddClasses()})},cancelReorder(){this.hideReorderColumnUnlessReorderingStatus&&(this.reorderDisplayColumn=!1),e.disableReordering()},updateOrderedItems(){let t=document.getElementById(l),s=[];for(let a=1,r;r=t.rows[a];a++)s.push({[i]:r.getAttribute("rowpk"),[this.defaultReorderColumn]:a});e.storeReorder(s)},setupEvenOddClasses(){if(void 0===this.evenNotInOdd.length||0==this.evenNotInOdd.length||void 0===this.oddNotInEven.length||0==this.oddNotInEven.length){let e=document.getElementById(l).getElementsByTagName("tbody")[0],t=[],i=[];void 0!==e.rows[0]&&void 0!==e.rows[1]&&(t=Array.from(e.rows[0].classList),i=Array.from(e.rows[1].classList),this.evenNotInOdd=t.filter(e=>!i.includes(e)),this.oddNotInEven=i.filter(e=>!t.includes(e)),t=[],i=[])}},toggleSelectAll(){t&&(this.paginationTotalItemCount===this.selectedItems.length?(this.clearSelected(),this.selectAllStatus=!1):this.delaySelectAll?this.setAllItemsSelected():this.setAllSelected())},setAllItemsSelected(){t&&(this.selectAllStatus=!0,this.selectAllOnPage())},setAllSelected(){t&&(this.delaySelectAll?(this.selectAllStatus=!0,this.selectAllOnPage()):e.setAllSelected())},clearSelected(){t&&(this.selectAllStatus=!1,e.clearSelected())},selectAllOnPage(){if(!t)return;let e=this.selectedItems,l=this.paginationCurrentItems.values();for(let i of l)e.push(i.toString());this.selectedItems=[...new Set(e)]},destroy(){this.listeners.forEach(e=>{e()})}})),Alpine.data("booleanFilter",(e,t,l,i)=>({switchOn:!1,value:e.entangle("filterComponents."+t).live,init(){this.switchOn=!1,void 0!==this.value&&(this.switchOn=Boolean(Number(this.value))),this.listeners.push(Livewire.on("filter-was-set",e=>{e.tableName==l&&e.filterKey==t&&(this.switchOn=e.value??i)}))}})),Alpine.data("numberRangeFilter",(e,t,l,i,s)=>({allFilters:e.entangle("filterComponents",!1),originalMin:0,originalMax:100,filterMin:0,filterMax:100,currentMin:0,currentMax:100,hasUpdate:!1,wireValues:e.entangle("filterComponents."+t,!1),defaultMin:i.minRange,defaultMax:i.maxRange,restrictUpdates:!1,initialiseStyles(){let e=document.getElementById(l);e.style.setProperty("--value-a",this.wireValues.min??this.filterMin),e.style.setProperty("--text-value-a",JSON.stringify(this.wireValues.min??this.filterMin)),e.style.setProperty("--value-b",this.wireValues.max??this.filterMax),e.style.setProperty("--text-value-b",JSON.stringify(this.wireValues.max??this.filterMax))},updateStyles(e,t){let i=document.getElementById(l);i.style.setProperty("--value-a",e),i.style.setProperty("--text-value-a",JSON.stringify(e)),i.style.setProperty("--value-b",t),i.style.setProperty("--text-value-b",JSON.stringify(t))},setupWire(){void 0!==this.wireValues?(this.filterMin=this.originalMin=void 0!==this.wireValues.min?this.wireValues.min:this.defaultMin,this.filterMax=this.originalMax=void 0!==this.wireValues.max?this.wireValues.max:this.defaultMax):(this.filterMin=this.originalMin=this.defaultMin,this.filterMax=this.originalMax=this.defaultMax),this.updateStyles(this.filterMin,this.filterMax)},allowUpdates(){this.updateWire()},updateWire(){let e=parseInt(this.filterMin),t=parseInt(this.filterMax);(e!=this.originalMin||t!=this.originalMax)&&(tthis.setupWire())}})),Alpine.data("flatpickrFilter",(e,t,l,i,s)=>({wireValues:e.entangle("filterComponents."+t),flatpickrInstance:flatpickr(i,{mode:"range",altFormat:l.altFormat??"F j, Y",altInput:l.altInput??!1,allowInput:l.allowInput??!1,allowInvalidPreload:l.allowInvalidPreload??!0,ariaDateFormat:l.ariaDateFormat??"F j, Y",clickOpens:!0,dateFormat:l.dateFormat??"Y-m-d",defaultDate:l.defaultDate??null,defaultHour:l.defaultHour??12,defaultMinute:l.defaultMinute??0,enableTime:l.enableTime??!1,enableSeconds:l.enableSeconds??!1,hourIncrement:l.hourIncrement??1,locale:l.locale??"en",minDate:l.earliestDate??null,maxDate:l.latestDate??null,minuteIncrement:l.minuteIncrement??5,shorthandCurrentMonth:l.shorthandCurrentMonth??!1,time_24hr:l.time_24hr??!1,weekNumbers:l.weekNumbers??!1,onOpen:function(){window.childElementOpen=!0},onChange:function(l,i,s){if(l.length>1){var a=i.split(" "),r={};window.childElementOpen=!1,window.filterPopoverOpen=!1,r={minDate:a[0],maxDate:void 0===a[2]?a[0]:a[2]},e.set("filterComponents."+t,r)}}}),changedValue:function(l){l.length<5&&(this.flatpickrInstance.setDate([]),e.set("filterComponents."+t,{}))},setupWire(){if(void 0!==this.wireValues){if(void 0!==this.wireValues.minDate&&void 0!==this.wireValues.maxDate){let e=[this.wireValues.minDate,this.wireValues.maxDate];this.flatpickrInstance.setDate(e)}else this.flatpickrInstance.setDate([])}else this.flatpickrInstance.setDate([])},init(){this.setupWire(),this.$watch("wireValues",e=>this.setupWire())}})),Alpine.data("tableWrapper",(e,t)=>({listeners:[],childElementOpen:!1,filtersOpen:e.entangle("filterSlideDownDefaultVisible"),paginationCurrentCount:e.entangle("paginationCurrentCount"),paginationTotalItemCount:e.entangle("paginationTotalItemCount"),paginationCurrentItems:e.entangle("paginationCurrentItems"),selectedItems:e.entangle("selected"),selectAllStatus:e.entangle("selectAll"),delaySelectAll:e.entangle("delaySelectAll"),hideBulkActionsWhenEmpty:e.entangle("hideBulkActionsWhenEmpty"),toggleSelectAll(){t&&(this.paginationTotalItemCount===this.selectedItems.length?(this.clearSelected(),this.selectAllStatus=!1):this.delaySelectAll?this.setAllItemsSelected():this.setAllSelected())},setAllItemsSelected(){t&&(this.selectAllStatus=!0,this.selectAllOnPage())},setAllSelected(){t&&(this.delaySelectAll?(this.selectAllStatus=!0,this.selectAllOnPage()):e.setAllSelected())},clearSelected(){t&&(this.selectAllStatus=!1,e.clearSelected())},selectAllOnPage(){if(!t)return;let e=this.selectedItems,l=this.paginationCurrentItems.values();for(let i of l)e.push(i.toString());this.selectedItems=[...new Set(e)]},destroy(){this.listeners.forEach(e=>{e()})}})),Alpine.data("reorderFunction",(e,t,l)=>({dragging:!1,reorderEnabled:!1,sourceID:"",targetID:"",evenRowClasses:"",oddRowClasses:"",currentlyHighlightedElement:"",evenRowClassArray:{},oddRowClassArray:{},evenNotInOdd:{},oddNotInEven:{},orderedRows:[],defaultReorderColumn:e.get("defaultReorderColumn"),reorderStatus:e.get("reorderStatus"),currentlyReorderingStatus:e.entangle("currentlyReorderingStatus"),hideReorderColumnUnlessReorderingStatus:e.entangle("hideReorderColumnUnlessReorderingStatus"),reorderDisplayColumn:e.entangle("reorderDisplayColumn"),dragStart(e){this.$nextTick(()=>{this.setupEvenOddClasses()}),this.sourceID=e.target.id,e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",e.target.id),e.target.classList.add("laravel-livewire-tables-dragging")},dragOverEvent(e){"object"==typeof this.currentlyHighlightedElement&&this.currentlyHighlightedElement.classList.remove("laravel-livewire-tables-highlight-bottom","laravel-livewire-tables-highlight-top");let t=e.target.closest("tr");this.currentlyHighlightedElement=t,e.offsetYl.getBoundingClientRect().height/2?i.insertBefore(s,l.nextSibling):i.insertBefore(s,l),r{this.setupEvenOddClasses()}),this.currentlyReorderingStatus?e.disableReordering():(this.setupEvenOddClasses(),this.hideReorderColumnUnlessReorderingStatus&&(this.reorderDisplayColumn=!0),e.enableReordering())},cancelReorder(){this.hideReorderColumnUnlessReorderingStatus&&(this.reorderDisplayColumn=!1),e.disableReordering()},updateOrderedItems(){let i=document.getElementById(t),s=[];for(let a=1,r;r=i.rows[a];a++)s.push({[l]:r.getAttribute("rowpk"),[this.defaultReorderColumn]:a});e.storeReorder(s)},setupEvenOddClasses(){if(void 0===this.evenNotInOdd.length||0==this.evenNotInOdd.length||void 0===this.oddNotInEven.length||0==this.oddNotInEven.length){let e=document.getElementById(t).getElementsByTagName("tbody")[0],l=[],i=[];void 0!==e.rows[0]&&void 0!==e.rows[1]&&(l=Array.from(e.rows[0].classList),i=Array.from(e.rows[1].classList),this.evenNotInOdd=l.filter(e=>!i.includes(e)),this.oddNotInEven=i.filter(e=>!l.includes(e)),l=[],i=[])}},init(){}}))}); \ No newline at end of file +document.addEventListener("alpine:init",()=>{Alpine.data("laravellivewiretable",e=>({tableId:"",showBulkActionsAlpine:!1,primaryKeyName:"",shouldBeDisplayed:e.entangle("shouldBeDisplayed"),tableName:e.entangle("tableName"),dataTableFingerprint:e.entangle("dataTableFingerprint"),listeners:[],childElementOpen:!1,filtersOpen:e.entangle("filterSlideDownDefaultVisible"),paginationCurrentCount:e.entangle("paginationCurrentCount"),paginationTotalItemCount:e.entangle("paginationTotalItemCount"),paginationCurrentItems:e.entangle("paginationCurrentItems"),selectedItems:e.entangle("selected"),selectAllStatus:e.entangle("selectAll"),delaySelectAll:e.entangle("delaySelectAll"),hideBulkActionsWhenEmpty:e.entangle("hideBulkActionsWhenEmpty"),dragging:!1,reorderEnabled:!1,sourceID:"",targetID:"",evenRowClasses:"",oddRowClasses:"",currentlyHighlightedElement:"",evenRowClassArray:{},oddRowClassArray:{},evenNotInOdd:{},oddNotInEven:{},orderedRows:[],defaultReorderColumn:e.get("defaultReorderColumn"),reorderStatus:e.entangle("reorderStatus"),currentlyReorderingStatus:e.entangle("currentlyReorderingStatus"),hideReorderColumnUnlessReorderingStatus:e.entangle("hideReorderColumnUnlessReorderingStatus"),reorderDisplayColumn:e.entangle("reorderDisplayColumn"),dragStart(e){this.$nextTick(()=>{this.setupEvenOddClasses()}),this.sourceID=e.target.id,e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",e.target.id),e.target.classList.add("laravel-livewire-tables-dragging")},dragOverEvent(e){"object"==typeof this.currentlyHighlightedElement&&this.currentlyHighlightedElement.classList.remove("laravel-livewire-tables-highlight-bottom","laravel-livewire-tables-highlight-top");let t=e.target.closest("tr");this.currentlyHighlightedElement=t,e.offsetYt.getBoundingClientRect().height/2?l.insertBefore(i,t.nextSibling):l.insertBefore(i,t),a{this.setupEvenOddClasses()})},cancelReorder(){this.hideReorderColumnUnlessReorderingStatus&&(this.reorderDisplayColumn=!1),e.disableReordering()},updateOrderedItems(){let t=document.getElementById(this.tableId),l=[];for(let i=1,s;s=t.rows[i];i++)l.push({[this.primaryKeyName]:s.getAttribute("rowpk"),[this.defaultReorderColumn]:i});e.storeReorder(l)},setupEvenOddClasses(){if(void 0===this.evenNotInOdd.length||0==this.evenNotInOdd.length||void 0===this.oddNotInEven.length||0==this.oddNotInEven.length){let e=document.getElementById(this.tableId).getElementsByTagName("tbody")[0],t=[],l=[];void 0!==e.rows[0]&&void 0!==e.rows[1]&&(t=Array.from(e.rows[0].classList),l=Array.from(e.rows[1].classList),this.evenNotInOdd=t.filter(e=>!l.includes(e)),this.oddNotInEven=l.filter(e=>!t.includes(e)),t=[],l=[])}},toggleSelectAll(){this.showBulkActionsAlpine&&(this.paginationTotalItemCount===this.selectedItems.length?(this.clearSelected(),this.selectAllStatus=!1):this.delaySelectAll?this.setAllItemsSelected():this.setAllSelected())},setAllItemsSelected(){this.showBulkActionsAlpine&&(this.selectAllStatus=!0,this.selectAllOnPage())},setAllSelected(){this.showBulkActionsAlpine&&(this.delaySelectAll?(this.selectAllStatus=!0,this.selectAllOnPage()):e.setAllSelected())},clearSelected(){this.showBulkActionsAlpine&&(this.selectAllStatus=!1,e.clearSelected())},selectAllOnPage(){if(!this.showBulkActionsAlpine)return;let e=this.selectedItems,t=this.paginationCurrentItems.values();for(let l of t)e.push(l.toString());this.selectedItems=[...new Set(e)]},setTableId(e){this.tableId=e},setAlpineBulkActions(e){this.showBulkActionsAlpine=e},setPrimaryKeyName(e){this.primaryKeyName=e},showTable(e){let t=e.detail.tableName??"",l=e.detail.tableFingerpint??"";((t??"")!=""&&t===this.tableName||""!=l&&eventTableFingerpint===this.dataTableFingerprint)&&(this.shouldBeDisplayed=!0)},hideTable(e){let t=e.detail.tableName??"",l=e.detail.tableFingerpint??"";(""!=t&&t===this.tableName||""!=l&&eventTableFingerpint===this.dataTableFingerprint)&&(this.shouldBeDisplayed=!1)},destroy(){this.listeners.forEach(e=>{e()})}})),Alpine.data("booleanFilter",(e,t,l,i)=>({switchOn:!1,value:e.entangle("filterComponents."+t).live,init(){this.switchOn=!1,void 0!==this.value&&(this.switchOn=Boolean(Number(this.value))),this.listeners.push(Livewire.on("filter-was-set",e=>{e.tableName==l&&e.filterKey==t&&(this.switchOn=e.value??i)}))}})),Alpine.data("numberRangeFilter",(e,t,l,i,s)=>({allFilters:e.entangle("filterComponents",!1),originalMin:0,originalMax:100,filterMin:0,filterMax:100,currentMin:0,currentMax:100,hasUpdate:!1,wireValues:e.entangle("filterComponents."+t,!1),defaultMin:i.minRange,defaultMax:i.maxRange,restrictUpdates:!1,initialiseStyles(){let e=document.getElementById(l);e.style.setProperty("--value-a",this.wireValues.min??this.filterMin),e.style.setProperty("--text-value-a",JSON.stringify(this.wireValues.min??this.filterMin)),e.style.setProperty("--value-b",this.wireValues.max??this.filterMax),e.style.setProperty("--text-value-b",JSON.stringify(this.wireValues.max??this.filterMax))},updateStyles(e,t){let i=document.getElementById(l);i.style.setProperty("--value-a",e),i.style.setProperty("--text-value-a",JSON.stringify(e)),i.style.setProperty("--value-b",t),i.style.setProperty("--text-value-b",JSON.stringify(t))},setupWire(){void 0!==this.wireValues?(this.filterMin=this.originalMin=void 0!==this.wireValues.min?this.wireValues.min:this.defaultMin,this.filterMax=this.originalMax=void 0!==this.wireValues.max?this.wireValues.max:this.defaultMax):(this.filterMin=this.originalMin=this.defaultMin,this.filterMax=this.originalMax=this.defaultMax),this.updateStyles(this.filterMin,this.filterMax)},allowUpdates(){this.updateWire()},updateWire(){let e=parseInt(this.filterMin),t=parseInt(this.filterMax);(e!=this.originalMin||t!=this.originalMax)&&(tthis.setupWire())}})),Alpine.data("flatpickrFilter",(e,t,l,i,s)=>({wireValues:e.entangle("filterComponents."+t),flatpickrInstance:flatpickr(i,{mode:"range",altFormat:l.altFormat??"F j, Y",altInput:l.altInput??!1,allowInput:l.allowInput??!1,allowInvalidPreload:l.allowInvalidPreload??!0,ariaDateFormat:l.ariaDateFormat??"F j, Y",clickOpens:!0,dateFormat:l.dateFormat??"Y-m-d",defaultDate:l.defaultDate??null,defaultHour:l.defaultHour??12,defaultMinute:l.defaultMinute??0,enableTime:l.enableTime??!1,enableSeconds:l.enableSeconds??!1,hourIncrement:l.hourIncrement??1,locale:l.locale??"en",minDate:l.earliestDate??null,maxDate:l.latestDate??null,minuteIncrement:l.minuteIncrement??5,shorthandCurrentMonth:l.shorthandCurrentMonth??!1,time_24hr:l.time_24hr??!1,weekNumbers:l.weekNumbers??!1,onOpen:function(){window.childElementOpen=!0},onChange:function(l,i,s){if(l.length>1){var a=i.split(" "),n={};window.childElementOpen=!1,window.filterPopoverOpen=!1,n={minDate:a[0],maxDate:void 0===a[2]?a[0]:a[2]},e.set("filterComponents."+t,n)}}}),changedValue:function(l){l.length<5&&(this.flatpickrInstance.setDate([]),e.set("filterComponents."+t,{}))},setupWire(){if(void 0!==this.wireValues){if(void 0!==this.wireValues.minDate&&void 0!==this.wireValues.maxDate){let e=[this.wireValues.minDate,this.wireValues.maxDate];this.flatpickrInstance.setDate(e)}else this.flatpickrInstance.setDate([])}else this.flatpickrInstance.setDate([])},init(){this.setupWire(),this.$watch("wireValues",e=>this.setupWire())}})),Alpine.data("tableWrapper",(e,t)=>({shouldBeDisplayed:e.entangle("shouldBeDisplayed"),listeners:[],childElementOpen:!1,filtersOpen:e.entangle("filterSlideDownDefaultVisible"),paginationCurrentCount:e.entangle("paginationCurrentCount"),paginationTotalItemCount:e.entangle("paginationTotalItemCount"),paginationCurrentItems:e.entangle("paginationCurrentItems"),selectedItems:e.entangle("selected"),selectAllStatus:e.entangle("selectAll"),delaySelectAll:e.entangle("delaySelectAll"),hideBulkActionsWhenEmpty:e.entangle("hideBulkActionsWhenEmpty"),toggleSelectAll(){t&&(this.paginationTotalItemCount===this.selectedItems.length?(this.clearSelected(),this.selectAllStatus=!1):this.delaySelectAll?this.setAllItemsSelected():this.setAllSelected())},setAllItemsSelected(){t&&(this.selectAllStatus=!0,this.selectAllOnPage())},setAllSelected(){t&&(this.delaySelectAll?(this.selectAllStatus=!0,this.selectAllOnPage()):e.setAllSelected())},clearSelected(){t&&(this.selectAllStatus=!1,e.clearSelected())},selectAllOnPage(){if(!t)return;let e=this.selectedItems,l=this.paginationCurrentItems.values();for(let i of l)e.push(i.toString());this.selectedItems=[...new Set(e)]},destroy(){this.listeners.forEach(e=>{e()})}})),Alpine.data("reorderFunction",(e,t,l)=>({dragging:!1,reorderEnabled:!1,sourceID:"",targetID:"",evenRowClasses:"",oddRowClasses:"",currentlyHighlightedElement:"",evenRowClassArray:{},oddRowClassArray:{},evenNotInOdd:{},oddNotInEven:{},orderedRows:[],defaultReorderColumn:e.get("defaultReorderColumn"),reorderStatus:e.get("reorderStatus"),currentlyReorderingStatus:e.entangle("currentlyReorderingStatus"),hideReorderColumnUnlessReorderingStatus:e.entangle("hideReorderColumnUnlessReorderingStatus"),reorderDisplayColumn:e.entangle("reorderDisplayColumn"),dragStart(e){this.$nextTick(()=>{this.setupEvenOddClasses()}),this.sourceID=e.target.id,e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",e.target.id),e.target.classList.add("laravel-livewire-tables-dragging")},dragOverEvent(e){"object"==typeof this.currentlyHighlightedElement&&this.currentlyHighlightedElement.classList.remove("laravel-livewire-tables-highlight-bottom","laravel-livewire-tables-highlight-top");let t=e.target.closest("tr");this.currentlyHighlightedElement=t,e.offsetYl.getBoundingClientRect().height/2?i.insertBefore(s,l.nextSibling):i.insertBefore(s,l),n{this.setupEvenOddClasses()}),this.currentlyReorderingStatus?e.disableReordering():(this.setupEvenOddClasses(),this.hideReorderColumnUnlessReorderingStatus&&(this.reorderDisplayColumn=!0),e.enableReordering())},cancelReorder(){this.hideReorderColumnUnlessReorderingStatus&&(this.reorderDisplayColumn=!1),e.disableReordering()},updateOrderedItems(){let i=document.getElementById(t),s=[];for(let a=1,n;n=i.rows[a];a++)s.push({[l]:n.getAttribute("rowpk"),[this.defaultReorderColumn]:a});e.storeReorder(s)},setupEvenOddClasses(){if(void 0===this.evenNotInOdd.length||0==this.evenNotInOdd.length||void 0===this.oddNotInEven.length||0==this.oddNotInEven.length){let e=document.getElementById(t).getElementsByTagName("tbody")[0],l=[],i=[];void 0!==e.rows[0]&&void 0!==e.rows[1]&&(l=Array.from(e.rows[0].classList),i=Array.from(e.rows[1].classList),this.evenNotInOdd=l.filter(e=>!i.includes(e)),this.oddNotInEven=i.filter(e=>!l.includes(e)),l=[],i=[])}},init(){}}))}); \ No newline at end of file diff --git a/resources/views/components/table.blade.php b/resources/views/components/table.blade.php index 0b92e6f39..4a8f14985 100644 --- a/resources/views/components/table.blade.php +++ b/resources/views/components/table.blade.php @@ -21,6 +21,7 @@ {{ $attributes->merge($customAttributes['table']) ->class(['min-w-full divide-y divide-gray-200 dark:divide-none' => $customAttributes['table']['default'] ?? true]) ->except('default') }} + > merge($customAttributes['thead']) diff --git a/resources/views/datatable.blade.php b/resources/views/datatable.blade.php index 6cf84f2ce..594272a70 100644 --- a/resources/views/datatable.blade.php +++ b/resources/views/datatable.blade.php @@ -6,7 +6,7 @@ @php($isBootstrap4 = $this->isBootstrap4) @php($isBootstrap5 = $this->isBootstrap5) -
+
getTopLevelAttributes() }}> @if($this->hasActions && !$this->showActionsInToolbar) diff --git a/src/Traits/ComponentUtilities.php b/src/Traits/ComponentUtilities.php index d065b25ed..11625c8de 100644 --- a/src/Traits/ComponentUtilities.php +++ b/src/Traits/ComponentUtilities.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Str; +use Livewire\Attributes\Locked; use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException; use Rappasoft\LaravelLivewireTables\Traits\Configuration\ComponentConfiguration; use Rappasoft\LaravelLivewireTables\Traits\Helpers\ComponentHelpers; @@ -15,8 +16,6 @@ trait ComponentUtilities public array $table = []; - public ?string $theme = null; - protected Builder $builder; protected $model; @@ -27,7 +26,8 @@ trait ComponentUtilities protected string $tableName = 'table'; - protected ?string $dataTableFingerprint; + #[Locked] + public ?string $dataTableFingerprint; protected bool $offlineIndicatorStatus = true; @@ -58,9 +58,11 @@ abstract public function configure(): void; public function mountComponentUtilities(): void { // Sets the Theme - tailwind/bootstrap - if (is_null($this->theme)) { - $this->setTheme(); + if (! isset($this->theme) || is_null($this->theme)) { + $this->setTheme(config('livewire-tables.theme', 'tailwind')); } + $this->generateDataTableFingerprint(); + } /** @@ -81,7 +83,7 @@ public function bootedComponentUtilities(): void // Make sure a primary key is set if (! $this->hasPrimaryKey()) { - throw new DataTableConfigurationException('You must set a primary key using setPrimaryKey in the configure method.'); + throw new DataTableConfigurationException('You must set a primary key using setPrimaryKey in the configure method, or configuring/configured lifecycle hooks'); } } diff --git a/src/Traits/Configuration/ColumnSelectConfiguration.php b/src/Traits/Configuration/ColumnSelectConfiguration.php index baf47e693..1622149d2 100644 --- a/src/Traits/Configuration/ColumnSelectConfiguration.php +++ b/src/Traits/Configuration/ColumnSelectConfiguration.php @@ -29,7 +29,7 @@ public function setColumnSelectDisabled(): self public function setRememberColumnSelectionStatus(bool $status): self { - $this->rememberColumnSelectionStatus = $status; + $this->storeColumnSelectInSessionStatus($status); return $this; } diff --git a/src/Traits/Configuration/SessionStorageConfiguration.php b/src/Traits/Configuration/SessionStorageConfiguration.php new file mode 100644 index 000000000..33e8310ce --- /dev/null +++ b/src/Traits/Configuration/SessionStorageConfiguration.php @@ -0,0 +1,40 @@ +sessionStorageStatus['filters'] = $status; + + return $this; + } + + public function storeFiltersInSessionEnabled(): self + { + return $this->storeFiltersInSessionStatus(true); + } + + public function storeFiltersInSessionDisabled(): self + { + return $this->storeFiltersInSessionStatus(false); + } + + protected function storeColumnSelectInSessionStatus(bool $status): self + { + $this->sessionStorageStatus['columnselect'] = $status; + + return $this; + } + + public function storeColumnSelectInSessionEnabled(): self + { + return $this->storeColumnSelectInSessionStatus(true); + } + + public function storeColumnSelectInSessionDisabled(): self + { + return $this->storeColumnSelectInSessionStatus(false); + } +} diff --git a/src/Traits/Configuration/TableAttributeConfiguration.php b/src/Traits/Configuration/TableAttributeConfiguration.php index 01cf7376d..c1bb681e9 100644 --- a/src/Traits/Configuration/TableAttributeConfiguration.php +++ b/src/Traits/Configuration/TableAttributeConfiguration.php @@ -118,4 +118,19 @@ public function setTableRowUrlTarget(\Closure $callback): self return $this; } + + public function setShouldBeDisplayedStatus(bool $status): void + { + $this->shouldBeDisplayed = $status; + } + + public function setShouldBeDisplayed(): void + { + $this->setShouldBeDisplayedStatus(true); + } + + public function setShouldBeHidden(): void + { + $this->setShouldBeDisplayedStatus(false); + } } diff --git a/src/Traits/HasAllTraits.php b/src/Traits/HasAllTraits.php index 567afccd3..8877bc69d 100644 --- a/src/Traits/HasAllTraits.php +++ b/src/Traits/HasAllTraits.php @@ -2,11 +2,14 @@ namespace Rappasoft\LaravelLivewireTables\Traits; +use Rappasoft\LaravelLivewireTables\Views\Traits\Core\HasTheme; + trait HasAllTraits { // Note Specific Order Below! use WithTableHooks; use WithLoadingPlaceholder; + use HasTheme; use ComponentUtilities, WithActions, WithData, @@ -27,6 +30,7 @@ trait HasAllTraits WithRefresh, WithReordering, WithSecondaryHeader, + WithSessionStorage, WithTableAttributes, WithTools; } diff --git a/src/Traits/Helpers/ColumnSelectHelpers.php b/src/Traits/Helpers/ColumnSelectHelpers.php index 9526856a2..961c62847 100644 --- a/src/Traits/Helpers/ColumnSelectHelpers.php +++ b/src/Traits/Helpers/ColumnSelectHelpers.php @@ -24,36 +24,11 @@ public function columnSelectIsDisabled(): bool return $this->getColumnSelectStatus() === false; } - public function getRememberColumnSelectionStatus(): bool - { - return $this->rememberColumnSelectionStatus; - } - - public function rememberColumnSelectionIsEnabled(): bool - { - return $this->getRememberColumnSelectionStatus() === true; - } - - public function rememberColumnSelectionIsDisabled(): bool - { - return $this->getRememberColumnSelectionStatus() === false; - } - public function columnSelectIsEnabledForColumn(mixed $column): bool { return in_array($column instanceof Column ? $column->getSlug() : $column, $this->selectedColumns, true); } - protected function forgetColumnSelectSession(): void - { - session()->forget($this->getColumnSelectSessionKey()); - } - - protected function getColumnSelectSessionKey(): string - { - return $this->getDataTableFingerprint().'-columnSelectEnabled'; - } - public function getColumnSelectIsHiddenOnTablet(): bool { return $this->columnSelectHiddenOnTablet; @@ -206,22 +181,23 @@ public function setupColumnSelect(): void $this->setupFirstColumnSelectRun(); // If remember selection is off, then clear the session - if ($this->rememberColumnSelectionIsDisabled()) { + if (! $this->shouldStoreColumnSelectInSession()) { $this->forgetColumnSelectSession(); } // Set to either the default set or what is stored in the session - $this->selectedColumns = (count($this->selectedColumns) > 1) ? + $selectedColumns = (count($this->selectedColumns) > 1) ? $this->selectedColumns : session()->get($this->getColumnSelectSessionKey(), $this->getDefaultVisibleColumns()); // Check to see if there are any excluded that are already stored in the enabled and remove them foreach ($this->getColumns() as $column) { - if (! $column->isSelectable() && ! in_array($column->getSlug(), $this->selectedColumns, true)) { - $this->selectedColumns[] = $column->getSlug(); - session([$this->getColumnSelectSessionKey() => $this->selectedColumns]); + if (! $column->isSelectable() && ! in_array($column->getSlug(), $selectedColumns, true)) { + $selectedColumns[] = $column->getSlug(); } } + $this->selectedColumns = $selectedColumns; + // $this->storeColumnSelectValues(); } protected function setupFirstColumnSelectRun(): void diff --git a/src/Traits/Helpers/ComponentHelpers.php b/src/Traits/Helpers/ComponentHelpers.php index 828df37a5..980d8d28e 100644 --- a/src/Traits/Helpers/ComponentHelpers.php +++ b/src/Traits/Helpers/ComponentHelpers.php @@ -9,7 +9,7 @@ trait ComponentHelpers { public function getDataTableFingerprint(): string { - return $this->dataTableFingerprint ?? $this->generateDataTableFingerprint(); + return $this->dataTableFingerprint ?? ($this->dataTableFingerprint = $this->generateDataTableFingerprint()); } public function setBuilder(Builder $builder): void @@ -57,44 +57,6 @@ public function getModel() return $this->model; } - public function setTheme(): void - { - $theme = $this->getTheme(); - - if ($theme === 'bootstrap-4' || $theme === 'bootstrap-5') { - $this->setPaginationTheme('bootstrap'); - } - } - - public function getTheme(): string - { - return $this->theme ?? config('livewire-tables.theme', 'tailwind'); - } - - #[Computed] - public function isTailwind(): bool - { - return $this->getTheme() === 'tailwind'; - } - - #[Computed] - public function isBootstrap(): bool - { - return $this->getTheme() === 'bootstrap-4' || $this->getTheme() === 'bootstrap-5'; - } - - #[Computed] - public function isBootstrap4(): bool - { - return $this->getTheme() === 'bootstrap-4'; - } - - #[Computed] - public function isBootstrap5(): bool - { - return $this->getTheme() === 'bootstrap-5'; - } - /** * Get the translated empty message of the table */ @@ -132,7 +94,7 @@ public function getTableName(): string #[Computed] public function getTableId(): string { - return $this->getTableAttributes()['id']; + return $this->getTableAttributes()['id'] ?? 'table-'.$this->getTableName(); } public function isTableNamed(string $name): bool diff --git a/src/Traits/Helpers/FilterHelpers.php b/src/Traits/Helpers/FilterHelpers.php index 205322ccd..4a78b333b 100644 --- a/src/Traits/Helpers/FilterHelpers.php +++ b/src/Traits/Helpers/FilterHelpers.php @@ -18,6 +18,8 @@ trait FilterHelpers */ public function mountFilterHelpers(): void { + $this->restoreFilterValues(); + foreach ($this->getFilters() as $filter) { if (! isset($this->appliedFilters[$filter->getKey()])) { if ($filter->hasFilterDefaultValue()) { @@ -145,6 +147,8 @@ public function setFilter(string $filterKey, string|array|null $value): void event(new FilterApplied($this->getTableName(), $filterKey, $value)); } $this->dispatch('filter-was-set', tableName: $this->getTableName(), filterKey: $filterKey, value: $value); + $this->storeFilterValues(); + } public function selectAllFilterOptions(string $filterKey): void @@ -173,6 +177,7 @@ public function setFilterDefaults(): void $this->resetFilter($filter); } } + } /** @@ -252,6 +257,7 @@ public function resetFilter($filter): void $this->callHook('filterReset', ['filter' => $filter->getKey()]); $this->callTraitHook('filterReset', ['filter' => $filter->getKey()]); $this->setFilter($filter->getKey(), $filter->getDefaultValue()); + } public function getFilterLayout(): string diff --git a/src/Traits/Helpers/SessionStorageHelpers.php b/src/Traits/Helpers/SessionStorageHelpers.php new file mode 100644 index 000000000..67f4d5829 --- /dev/null +++ b/src/Traits/Helpers/SessionStorageHelpers.php @@ -0,0 +1,96 @@ +sessionStorageStatus[$name] ?? false; + } + + public function shouldStoreFiltersInSession(): bool + { + return $this->getSessionStorageStatus('filters'); + } + + public function getFilterSessionKey(): string + { + return $this->getTableName().'-stored-filters'; + } + + public function storeFilterValues(): void + { + if ($this->shouldStoreFiltersInSession()) { + $this->clearStoredFilterValues(); + session([$this->getFilterSessionKey() => $this->appliedFilters]); + } + } + + public function restoreFilterValues(): void + { + if (empty($this->filterComponents) || empty($this->appliedFilters)) { + $this->filterComponents = $this->appliedFilters = $this->getStoredFilterValues(); + } + } + + public function getStoredFilterValues(): array + { + if ($this->shouldStoreFiltersInSession() && session()->has($this->getFilterSessionKey())) { + return session()->get($this->getFilterSessionKey()); + } + + return []; + } + + public function clearStoredFilterValues(): void + { + if ($this->shouldStoreFiltersInSession() && session()->has($this->getFilterSessionKey())) { + session()->forget($this->getFilterSessionKey()); + } + } + + public function shouldStoreColumnSelectInSession(): bool + { + return $this->getSessionStorageStatus('columnselect'); + } + + public function getColumnSelectSessionKey(): string + { + return $this->getTableName().'-stored-columnselect'; + } + + public function storeColumnSelectValues(): void + { + if ($this->shouldStoreColumnSelectInSession()) { + $this->clearStoredColumnSelectValues(); + session([$this->getColumnSelectSessionKey() => $this->selectedColumns]); + } + } + + public function restoreColumnSelectValues(): void + { + $this->selectedColumns = $this->getStoredColumnSelectValues(); + } + + public function getStoredColumnSelectValues(): array + { + if ($this->shouldStoreColumnSelectInSession() && session()->has($this->getColumnSelectSessionKey())) { + return session()->get($this->getColumnSelectSessionKey()); + } + + return []; + } + + public function clearStoredColumnSelectValues(): void + { + if ($this->shouldStoreColumnSelectInSession() && session()->has($this->getColumnSelectSessionKey())) { + session()->forget($this->getColumnSelectSessionKey()); + } + } + + protected function forgetColumnSelectSession(): void + { + session()->forget($this->getColumnSelectSessionKey()); + } +} diff --git a/src/Traits/Helpers/TableAttributeHelpers.php b/src/Traits/Helpers/TableAttributeHelpers.php index 842c20886..4d82a5393 100644 --- a/src/Traits/Helpers/TableAttributeHelpers.php +++ b/src/Traits/Helpers/TableAttributeHelpers.php @@ -3,6 +3,7 @@ namespace Rappasoft\LaravelLivewireTables\Traits\Helpers; use Illuminate\Database\Eloquent\Model; +use Illuminate\View\ComponentAttributeBag; use Livewire\Attributes\Computed; use Rappasoft\LaravelLivewireTables\Views\Column; @@ -76,4 +77,28 @@ public function getTableRowUrlTarget(int|Model $row): ?string { return isset($this->trUrlTargetCallback) ? call_user_func($this->trUrlTargetCallback, $row) : null; } + + #[Computed] + public function getShouldBeDisplayed(): bool + { + return $this->shouldBeDisplayed; + } + + public function getTopLevelAttributesArray(): array + { + return [ + 'x-data' => 'laravellivewiretable($wire)', + 'x-init' => "setTableId('".$this->getTableAttributes()['id']."'); setAlpineBulkActions('".$this->showBulkActionsDropdownAlpine()."'); setPrimaryKeyName('".$this->getPrimaryKey()."');", + 'x-cloak', + 'x-show' => 'shouldBeDisplayed', + 'x-on:show-table.window' => 'showTable(event)', + 'x-on:hide-table.window' => 'hideTable(event)', + ]; + } + + #[Computed] + public function getTopLevelAttributes(): ComponentAttributeBag + { + return new ComponentAttributeBag($this->getTopLevelAttributesArray()); + } } diff --git a/src/Traits/WithColumnSelect.php b/src/Traits/WithColumnSelect.php index af1ebca61..704d1bea5 100644 --- a/src/Traits/WithColumnSelect.php +++ b/src/Traits/WithColumnSelect.php @@ -32,8 +32,6 @@ trait WithColumnSelect protected bool $columnSelectStatus = true; - protected bool $rememberColumnSelectionStatus = true; - protected bool $columnSelectHiddenOnMobile = false; protected bool $columnSelectHiddenOnTablet = false; @@ -51,13 +49,20 @@ protected function queryStringWithColumnSelect(): array public function bootedWithColumnSelect(): void { + $this->callHook('configuringColumnSelect'); + $this->callTraitHook('configuringColumnSelect'); + $this->setupColumnSelect(); + + $this->callHook('configuredColumnSelect'); + $this->callTraitHook('configuredColumnSelect'); + } public function updatedSelectedColumns(): void { // The query string isn't needed if it's the same as the default - session([$this->getColumnSelectSessionKey() => $this->selectedColumns]); + $this->storeColumnSelectValues(); if ($this->getEventStatusColumnSelect()) { event(new ColumnsSelected($this->getTableName(), $this->getColumnSelectSessionKey(), $this->selectedColumns)); } @@ -67,7 +72,7 @@ public function renderingWithColumnSelect(\Illuminate\View\View $view, array $da { if (! $this->getComputedPropertiesStatus()) { $view->with([ - 'selectedVisibleColumns' => $this->getVisibleColumns(), + 'selectedVisibleColumns' => $this->selectedVisibleColumns(), ]); } } diff --git a/src/Traits/WithFilters.php b/src/Traits/WithFilters.php index 49c91da8c..9ec7e60aa 100644 --- a/src/Traits/WithFilters.php +++ b/src/Traits/WithFilters.php @@ -78,6 +78,7 @@ public function applyFilters(): Builder } } } + $this->storeFilterValues(); } return $this->getBuilder(); @@ -110,5 +111,6 @@ public function updatedFilterComponents(string|array|null $value, string $filter $this->dispatch('filter-was-set', tableName: $this->getTableName(), filterKey: $filter->getKey(), value: $value); } + } } diff --git a/src/Traits/WithSessionStorage.php b/src/Traits/WithSessionStorage.php new file mode 100644 index 000000000..08cfbe5a7 --- /dev/null +++ b/src/Traits/WithSessionStorage.php @@ -0,0 +1,17 @@ + true, + 'filters' => false, + ]; +} diff --git a/src/Traits/WithTableAttributes.php b/src/Traits/WithTableAttributes.php index 0ec1884c1..f87edea61 100644 --- a/src/Traits/WithTableAttributes.php +++ b/src/Traits/WithTableAttributes.php @@ -3,6 +3,7 @@ namespace Rappasoft\LaravelLivewireTables\Traits; use Closure; +use Livewire\Attributes\On; use Rappasoft\LaravelLivewireTables\Traits\Configuration\TableAttributeConfiguration; use Rappasoft\LaravelLivewireTables\Traits\Helpers\TableAttributeHelpers; @@ -32,4 +33,6 @@ trait WithTableAttributes protected ?\Closure $trUrlCallback; protected ?\Closure $trUrlTargetCallback; + + public bool $shouldBeDisplayed = true; } diff --git a/src/Views/Traits/Configuration/ColumnConfiguration.php b/src/Views/Traits/Configuration/ColumnConfiguration.php index 2b20f595c..c46b01663 100644 --- a/src/Views/Traits/Configuration/ColumnConfiguration.php +++ b/src/Views/Traits/Configuration/ColumnConfiguration.php @@ -84,13 +84,6 @@ public function setColumnLabelStatus(bool $status): void $this->displayColumnLabel = $status; } - public function setTheme(string $theme): self - { - $this->theme = $theme; - - return $this; - } - public function setHasTableRowUrl(bool $hasTableRowUrl): self { $this->hasTableRowUrl = $hasTableRowUrl; diff --git a/src/Views/Traits/Core/HasTheme.php b/src/Views/Traits/Core/HasTheme.php index 65ccfb885..5d229879a 100644 --- a/src/Views/Traits/Core/HasTheme.php +++ b/src/Views/Traits/Core/HasTheme.php @@ -2,34 +2,50 @@ namespace Rappasoft\LaravelLivewireTables\Views\Traits\Core; +use Livewire\Attributes\{Computed,Locked}; + trait HasTheme { - protected string $theme = 'tailwind'; + #[Locked] + public ?string $theme; + + public function getTheme(): string + { + return $this->theme ?? ($this->theme = config('livewire-tables.theme', 'tailwind')); + } public function setTheme(string $theme): self { $this->theme = $theme; + if (($theme === 'bootstrap-4' || $theme === 'bootstrap-5') && method_exists($this, 'setPaginationTheme')) { + $this->setPaginationTheme('bootstrap'); + } + return $this; } + #[Computed] public function isTailwind(): bool { - return $this->theme != 'bootstrap-4' && $this->theme != 'bootstrap-5'; + return ! $this->isBootstrap4() && ! $this->isBootstrap5(); } + #[Computed] public function isBootstrap(): bool { - return $this->theme == 'bootstrap-4' || $this->theme == 'bootstrap-5'; + return $this->isBootstrap4() || $this->isBootstrap5(); } + #[Computed] public function isBootstrap4(): bool { - return $this->theme == 'bootstrap-4'; + return $this->getTheme() === 'bootstrap-4'; } + #[Computed] public function isBootstrap5(): bool { - return $this->theme == 'bootstrap-5'; + return $this->getTheme() === 'bootstrap-5'; } } diff --git a/src/Views/Traits/Helpers/ColumnHelpers.php b/src/Views/Traits/Helpers/ColumnHelpers.php index 1b016590c..da220287e 100644 --- a/src/Views/Traits/Helpers/ColumnHelpers.php +++ b/src/Views/Traits/Helpers/ColumnHelpers.php @@ -211,26 +211,6 @@ public function getHasTableRowUrl(): bool return $this->hasTableRowUrl; } - public function isTailwind(): bool - { - return $this->theme != 'bootstrap-4' && $this->theme != 'bootstrap-5'; - } - - public function isBootstrap(): bool - { - return $this->theme == 'bootstrap-4' || $this->theme == 'bootstrap-5'; - } - - public function isBootstrap4(): bool - { - return $this->theme == 'bootstrap-4'; - } - - public function isBootstrap5(): bool - { - return $this->theme == 'bootstrap-5'; - } - public function getIsReorderColumn(): bool { return $this->isReorderColumn; diff --git a/src/Views/Traits/IsColumn.php b/src/Views/Traits/IsColumn.php index 7ff25cf3f..42bbfb5b4 100644 --- a/src/Views/Traits/IsColumn.php +++ b/src/Views/Traits/IsColumn.php @@ -5,7 +5,7 @@ use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\Views\Traits\Columns\{HasVisibility, IsCollapsible, IsSearchable, IsSelectable, IsSortable}; use Rappasoft\LaravelLivewireTables\Views\Traits\Configuration\ColumnConfiguration; -use Rappasoft\LaravelLivewireTables\Views\Traits\Core\{HasAttributes,HasFooter,HasSecondaryHeader,HasView}; +use Rappasoft\LaravelLivewireTables\Views\Traits\Core\{HasAttributes,HasFooter,HasSecondaryHeader,HasTheme,HasView}; use Rappasoft\LaravelLivewireTables\Views\Traits\Helpers\{ColumnHelpers,RelationshipHelpers}; trait IsColumn @@ -20,6 +20,7 @@ trait IsColumn HasAttributes, HasFooter, HasSecondaryHeader, + HasTheme, HasView, HasVisibility; @@ -57,7 +58,5 @@ trait IsColumn protected bool $hasTableRowUrl = false; - protected string $theme = 'tailwind'; - protected bool $isReorderColumn = false; } diff --git a/tests/Http/Livewire/PetsTable.php b/tests/Http/Livewire/PetsTable.php index 28cc1782c..59b52049d 100644 --- a/tests/Http/Livewire/PetsTable.php +++ b/tests/Http/Livewire/PetsTable.php @@ -3,6 +3,7 @@ namespace Rappasoft\LaravelLivewireTables\Tests\Http\Livewire; use Illuminate\Database\Eloquent\Builder; +use Livewire\Attributes\On; use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\Tests\Models\Breed; use Rappasoft\LaravelLivewireTables\Tests\Models\Pet; diff --git a/tests/Http/Livewire/PetsTableAttributes.php b/tests/Http/Livewire/PetsTableAttributes.php index 53f79646f..690faf813 100644 --- a/tests/Http/Livewire/PetsTableAttributes.php +++ b/tests/Http/Livewire/PetsTableAttributes.php @@ -2,26 +2,8 @@ namespace Rappasoft\LaravelLivewireTables\Tests\Http\Livewire; -use Illuminate\Database\Eloquent\Builder; -use Rappasoft\LaravelLivewireTables\DataTableComponent; -use Rappasoft\LaravelLivewireTables\Tests\Models\Breed; -use Rappasoft\LaravelLivewireTables\Tests\Models\Pet; -use Rappasoft\LaravelLivewireTables\Tests\Models\Species; -use Rappasoft\LaravelLivewireTables\Views\Column; -use Rappasoft\LaravelLivewireTables\Views\Columns\ImageColumn; -use Rappasoft\LaravelLivewireTables\Views\Columns\LinkColumn; -use Rappasoft\LaravelLivewireTables\Views\Filters\DateFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\DateTimeFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectDropdownFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\NumberFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\SelectFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter; - -class PetsTableAttributes extends DataTableComponent +class PetsTableAttributes extends PetsTable { - public $model = Pet::class; - public function configure(): void { $this->setPrimaryKey('id') @@ -49,123 +31,4 @@ public function configure(): void }); } - - public function columns(): array - { - return [ - Column::make('ID', 'id') - ->sortable() - ->setSortingPillTitle('Key') - ->setSortingPillDirections('0-9', '9-0'), - Column::make('Sort') - ->sortable() - ->excludeFromColumnSelect(), - Column::make('Name') - ->sortable() - ->secondaryHeader($this->getFilterByKey('pet_name_filter')) - ->footerFilter('pet_name_filter') - ->searchable(), - - Column::make('Age'), - - Column::make('Breed', 'breed.name') - ->secondaryHeaderFilter('breed') - ->footer($this->getFilterByKey('breed')) - ->sortable( - fn (Builder $query, string $direction) => $query->orderBy('pets.id', $direction) - ) - ->searchable( - fn (Builder $query, $searchTerm) => $query->orWhere('breed.name', $searchTerm) - ), - - Column::make('Other') - ->label(function ($row, Column $column) { - return 'Other'; - }) - ->footer(function ($rows) { - return 'Count: '.$rows->count(); - }), - - LinkColumn::make('Link') - ->title(fn ($row) => 'Edit') - ->location(fn ($row) => 'http://www.google.com') - ->attributes(fn ($row) => [ - 'class' => 'rounded-full', - 'alt' => $row->name.' Avatar', - ]), - ImageColumn::make('RowImg') - ->location(fn ($row) => 'test'.$row->id) - ->attributes(fn ($row) => [ - 'class' => 'rounded-full', - 'alt' => $row->name.' Avatar', - ]), - Column::make('Last Visit', 'last_visit') - ->sortable() - ->deselected(), - ]; - } - - public function filters(): array - { - return [ - MultiSelectFilter::make('Breed') - ->options( - Breed::query() - ->orderBy('name') - ->get() - ->keyBy('id') - ->map(fn ($breed) => $breed->name) - ->toArray() - ) - ->filter(function (Builder $builder, array $values) { - return $builder->whereIn('breed_id', $values); - }), - MultiSelectDropdownFilter::make('Species') - ->options( - Species::query() - ->orderBy('name') - ->get() - ->keyBy('id') - ->map(fn ($species) => $species->name) - ->toArray() - ) - ->filter(function (Builder $builder, array $values) { - return $builder->whereIn('species_id', $values); - }), - NumberFilter::make('Breed ID', 'breed_id_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->where('breed_id', '=', $value); - }), - - TextFilter::make('Pet Name', 'pet_name_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->where('pets.name', '=', $value); - }), - - DateFilter::make('Last Visit After Date', 'last_visit_date_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->whereDate('pets.last_visit', '=>', $value); - }), - - DateTimeFilter::make('Last Visit Before DateTime', 'last_visit_datetime_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->whereDate('pets.last_visit', '<=', $value); - }), - - SelectFilter::make('Breed SelectFilter', 'breed_select_filter') - ->options( - Breed::query() - ->orderBy('name') - ->get() - ->keyBy('id') - ->map(fn ($breed) => $breed->name) - ->toArray() - ) - ->filter(function (Builder $builder, string $value) { - return $builder->where('breed_id', $value); - }) - ->setCustomFilterLabel('livewire-tables::tests.testFilterLabel') - ->setFilterPillBlade('livewire-tables::tests.testFilterPills'), - ]; - } } diff --git a/tests/Http/Livewire/PetsTableEvents.php b/tests/Http/Livewire/PetsTableEvents.php new file mode 100644 index 000000000..24c7163cf --- /dev/null +++ b/tests/Http/Livewire/PetsTableEvents.php @@ -0,0 +1,25 @@ +setShouldBeHidden(); + } + + #[On('showTable')] + public function showTable(): void + { + $this->setShouldBeDisplayed(); + } + + #[On('hideTable')] + public function hideTable() + { + $this->setShouldBeHidden(); + } +} diff --git a/tests/Http/Livewire/PetsTableLoadingPlaceholder.php b/tests/Http/Livewire/PetsTableLoadingPlaceholder.php index c5096c496..26fd7c367 100644 --- a/tests/Http/Livewire/PetsTableLoadingPlaceholder.php +++ b/tests/Http/Livewire/PetsTableLoadingPlaceholder.php @@ -2,149 +2,12 @@ namespace Rappasoft\LaravelLivewireTables\Tests\Http\Livewire; -use Illuminate\Database\Eloquent\Builder; -use Rappasoft\LaravelLivewireTables\DataTableComponent; -use Rappasoft\LaravelLivewireTables\Tests\Models\Breed; -use Rappasoft\LaravelLivewireTables\Tests\Models\Pet; -use Rappasoft\LaravelLivewireTables\Tests\Models\Species; -use Rappasoft\LaravelLivewireTables\Views\Column; -use Rappasoft\LaravelLivewireTables\Views\Columns\ImageColumn; -use Rappasoft\LaravelLivewireTables\Views\Columns\LinkColumn; -use Rappasoft\LaravelLivewireTables\Views\Filters\DateFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\DateTimeFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectDropdownFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\MultiSelectFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\NumberFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\SelectFilter; -use Rappasoft\LaravelLivewireTables\Views\Filters\TextFilter; - -class PetsTableLoadingPlaceholder extends DataTableComponent +class PetsTableLoadingPlaceholder extends PetsTable { - public $model = Pet::class; - public function configure(): void { $this->setPrimaryKey('id') ->setLoadingPlaceholderEnabled() ->setLoadingPlaceholderContent('TestLoadingPlaceholderContentTestTest'); } - - public function columns(): array - { - return [ - Column::make('ID', 'id') - ->sortable() - ->setSortingPillTitle('Key') - ->setSortingPillDirections('0-9', '9-0'), - Column::make('Sort') - ->sortable() - ->excludeFromColumnSelect(), - Column::make('Name') - ->sortable() - ->secondaryHeader($this->getFilterByKey('pet_name_filter')) - ->footerFilter('pet_name_filter') - ->searchable(), - - Column::make('Age'), - - Column::make('Breed', 'breed.name') - ->secondaryHeaderFilter('breed') - ->footer($this->getFilterByKey('breed')) - ->sortable( - fn (Builder $query, string $direction) => $query->orderBy('pets.id', $direction) - ) - ->searchable( - fn (Builder $query, $searchTerm) => $query->orWhere('breed.name', $searchTerm) - ), - - Column::make('Other') - ->label(function ($row, Column $column) { - return 'Other'; - }) - ->footer(function ($rows) { - return 'Count: '.$rows->count(); - }), - - LinkColumn::make('Link') - ->title(fn ($row) => 'Edit') - ->location(fn ($row) => 'http://www.google.com') - ->attributes(fn ($row) => [ - 'class' => 'rounded-full', - 'alt' => $row->name.' Avatar', - ]), - ImageColumn::make('RowImg') - ->location(fn ($row) => 'test'.$row->id) - ->attributes(fn ($row) => [ - 'class' => 'rounded-full', - 'alt' => $row->name.' Avatar', - ]), - Column::make('Last Visit', 'last_visit') - ->sortable() - ->deselected(), - ]; - } - - public function filters(): array - { - return [ - MultiSelectFilter::make('Breed') - ->options( - Breed::query() - ->orderBy('name') - ->get() - ->keyBy('id') - ->map(fn ($breed) => $breed->name) - ->toArray() - ) - ->filter(function (Builder $builder, array $values) { - return $builder->whereIn('breed_id', $values); - }), - MultiSelectDropdownFilter::make('Species') - ->options( - Species::query() - ->orderBy('name') - ->get() - ->keyBy('id') - ->map(fn ($species) => $species->name) - ->toArray() - ) - ->filter(function (Builder $builder, array $values) { - return $builder->whereIn('species_id', $values); - }), - NumberFilter::make('Breed ID', 'breed_id_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->where('breed_id', '=', $value); - }), - - TextFilter::make('Pet Name', 'pet_name_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->where('pets.name', '=', $value); - }), - - DateFilter::make('Last Visit After Date', 'last_visit_date_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->whereDate('pets.last_visit', '=>', $value); - }), - - DateTimeFilter::make('Last Visit Before DateTime', 'last_visit_datetime_filter') - ->filter(function (Builder $builder, string $value) { - return $builder->whereDate('pets.last_visit', '<=', $value); - }), - - SelectFilter::make('Breed SelectFilter', 'breed_select_filter') - ->options( - Breed::query() - ->orderBy('name') - ->get() - ->keyBy('id') - ->map(fn ($breed) => $breed->name) - ->toArray() - ) - ->filter(function (Builder $builder, string $value) { - return $builder->where('breed_id', $value); - }) - ->setCustomFilterLabel('livewire-tables::tests.testFilterLabel') - ->setFilterPillBlade('livewire-tables::tests.testFilterPills'), - ]; - } } diff --git a/tests/Http/Livewire/PetsTableNoFilters.php b/tests/Http/Livewire/PetsTableNoFilters.php index 20bc7a7b9..d209a6602 100644 --- a/tests/Http/Livewire/PetsTableNoFilters.php +++ b/tests/Http/Livewire/PetsTableNoFilters.php @@ -6,15 +6,8 @@ use Rappasoft\LaravelLivewireTables\Tests\Models\Pet; use Rappasoft\LaravelLivewireTables\Views\Column; -class PetsTableNoFilters extends DataTableComponent +class PetsTableNoFilters extends PetsTable { - public $model = Pet::class; - - public function configure(): void - { - $this->setPrimaryKey('id'); - } - public function columns(): array { return [ @@ -36,4 +29,10 @@ public function columns(): array }), ]; } + + public function filters(): array + { + return [ + ]; + } } diff --git a/tests/TestCase.php b/tests/TestCase.php index 0bf3aa3e2..92cec4db2 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -9,7 +9,7 @@ use Livewire\LivewireServiceProvider; use Orchestra\Testbench\TestCase as Orchestra; use Rappasoft\LaravelLivewireTables\LaravelLivewireTablesServiceProvider; -use Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\{BreedsTable,PetsTable,PetsTableUnpaginated,PetsTableWithOwner,SpeciesTable}; +use Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\{BreedsTable,PetsTable,PetsTableEvents,PetsTableUnpaginated,PetsTableWithOwner,SpeciesTable}; use Rappasoft\LaravelLivewireTables\Tests\Http\TestComponent; use Rappasoft\LaravelLivewireTables\Tests\Models\Breed; use Rappasoft\LaravelLivewireTables\Tests\Models\Owner; @@ -107,6 +107,21 @@ protected function setupBasicTable() $this->basicTable->render(); } + protected function setupEventsTable() + { + $view = view('livewire-tables::datatable'); + $this->eventsTable = new PetsTableEvents; + $this->eventsTable->boot(); + $this->eventsTable->bootedComponentUtilities(); + $this->eventsTable->bootedWithData(); + $this->eventsTable->bootedWithColumns(); + $this->eventsTable->bootedWithColumnSelect(); + $this->eventsTable->bootedWithSecondaryHeader(); + $this->eventsTable->booted(); + $this->eventsTable->renderingWithPagination($view, []); + $this->eventsTable->render(); + } + protected function setupBreedsTable() { $view = view('livewire-tables::datatable'); diff --git a/tests/Traits/Configuration/ColumnSelectConfigurationTest.php b/tests/Traits/Configuration/ColumnSelectConfigurationTest.php index 2daf1e25a..ea79e5a21 100644 --- a/tests/Traits/Configuration/ColumnSelectConfigurationTest.php +++ b/tests/Traits/Configuration/ColumnSelectConfigurationTest.php @@ -41,23 +41,23 @@ public function test_can_set_column_select_status(): void public function test_can_set_remember_column_selection_status(): void { - $this->assertTrue($this->basicTable->getRememberColumnSelectionStatus()); + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); $this->basicTable->setRememberColumnSelectionDisabled(); - $this->assertFalse($this->basicTable->getRememberColumnSelectionStatus()); + $this->assertFalse($this->basicTable->shouldStoreColumnSelectInSession()); $this->basicTable->setRememberColumnSelectionEnabled(); - $this->assertTrue($this->basicTable->getRememberColumnSelectionStatus()); + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); $this->basicTable->setRememberColumnSelectionStatus(false); - $this->assertFalse($this->basicTable->getRememberColumnSelectionStatus()); + $this->assertFalse($this->basicTable->shouldStoreColumnSelectInSession()); $this->basicTable->setRememberColumnSelectionStatus(true); - $this->assertTrue($this->basicTable->getRememberColumnSelectionStatus()); + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); } public function test_can_deselect_all_columns(): void diff --git a/tests/Traits/Helpers/ColumnSelectHelpersTest.php b/tests/Traits/Helpers/ColumnSelectHelpersTest.php index 71867823b..6c0d1fbf5 100644 --- a/tests/Traits/Helpers/ColumnSelectHelpersTest.php +++ b/tests/Traits/Helpers/ColumnSelectHelpersTest.php @@ -21,15 +21,24 @@ public function test_can_get_column_select_status(): void public function test_can_get_remember_column_selection_status(): void { - $this->assertTrue($this->basicTable->rememberColumnSelectionIsEnabled()); + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); $this->basicTable->setRememberColumnSelectionDisabled(); - $this->assertTrue($this->basicTable->rememberColumnSelectionIsDisabled()); + $this->assertFalse($this->basicTable->shouldStoreColumnSelectInSession()); $this->basicTable->setRememberColumnSelectionEnabled(); - $this->assertTrue($this->basicTable->rememberColumnSelectionIsEnabled()); + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); + + $this->basicTable->storeColumnSelectInSessionDisabled(); + + $this->assertFalse($this->basicTable->shouldStoreColumnSelectInSession()); + + $this->basicTable->storeColumnSelectInSessionEnabled(); + + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); + } public function test_can_set_column_select_hidden_on_mobile_status(): void diff --git a/tests/Traits/Helpers/SessionStorageHelpersTest.php b/tests/Traits/Helpers/SessionStorageHelpersTest.php new file mode 100644 index 000000000..17362c503 --- /dev/null +++ b/tests/Traits/Helpers/SessionStorageHelpersTest.php @@ -0,0 +1,109 @@ +assertFalse($this->basicTable->shouldStoreFiltersInSession()); + + $this->basicTable->storeFiltersInSessionEnabled(); + + $this->assertTrue($this->basicTable->shouldStoreFiltersInSession()); + + $this->basicTable->storeFiltersInSessionDisabled(); + + $this->assertFalse($this->basicTable->shouldStoreFiltersInSession()); + + } + + public function test_can_get_session_storage_status_filter_key(): void + { + $this->assertSame($this->basicTable->getTableName().'-stored-filters', $this->basicTable->getFilterSessionKey()); + } + + public function test_can_store_for_fikers(): void + { + $this->basicTable->storeFiltersInSessionEnabled(); + + $this->assertTrue($this->basicTable->shouldStoreFiltersInSession()); + + $this->basicTable->setFilter('breed', ['1']); + $this->assertSame(['1'], $this->basicTable->getAppliedFilterWithValue('breed')); + $this->assertSame(['breed' => ['1']], $this->basicTable->appliedFilters); + $this->assertSame(['breed' => ['1']], $this->basicTable->getStoredFilterValues()); + + $this->basicTable->setFilter('breed', ['22']); + $this->assertSame(['breed' => ['22']], $this->basicTable->appliedFilters); + $this->assertSame(['22'], $this->basicTable->getAppliedFilterWithValue('breed')); + $this->assertSame(['breed' => ['22']], $this->basicTable->getStoredFilterValues()); + + $this->basicTable->restoreFilterValues(); + $this->assertSame(['22'], $this->basicTable->getAppliedFilterWithValue('breed')); + $this->assertSame(['breed' => ['22']], $this->basicTable->getStoredFilterValues()); + + $this->basicTable->clearStoredFilterValues(); + $this->assertSame([], $this->basicTable->getStoredFilterValues()); + $this->assertSame(['22'], $this->basicTable->getAppliedFilterWithValue('breed')); + + $this->basicTable->setFilter('breed', ['33']); + $this->assertSame(['breed' => ['33']], $this->basicTable->getStoredFilterValues()); + $this->assertSame(['33'], $this->basicTable->getAppliedFilterWithValue('breed')); + + $this->basicTable->appliedFilters = $this->basicTable->filterComponents = ['breed' => ['44']]; + $this->basicTable->storeFilterValues(); + $this->assertSame(['44'], $this->basicTable->getAppliedFilterWithValue('breed')); + + $this->basicTable->appliedFilters = $this->basicTable->filterComponents = []; + $this->assertNull($this->basicTable->getAppliedFilterWithValue('breed')); + $this->assertSame([], $this->basicTable->appliedFilters); + $this->assertSame([], $this->basicTable->filterComponents); + + $this->basicTable->restoreFilterValues(); + $this->assertSame(['breed' => ['44']], $this->basicTable->appliedFilters); + $this->assertSame(['44'], $this->basicTable->getAppliedFilterWithValue('breed')); + $this->assertSame(['breed' => ['44']], $this->basicTable->getStoredFilterValues()); + + } + + public function test_can_get_session_storage_status_for_columnselect(): void + { + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); + + $this->basicTable->storeColumnSelectInSessionDisabled(); + + $this->assertFalse($this->basicTable->shouldStoreColumnSelectInSession()); + + $this->basicTable->storeColumnSelectInSessionEnabled(); + + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); + + } + + public function test_can_get_session_storage_status_columnselect_key(): void + { + $this->assertSame($this->basicTable->getTableName().'-stored-columnselect', $this->basicTable->getColumnSelectSessionKey()); + } + + public function test_can_store_for_columnselect(): void + { + $this->assertTrue($this->basicTable->shouldStoreColumnSelectInSession()); + + $this->basicTable->selectedColumns = ['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg']; + $this->assertSame(['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg'], $this->basicTable->selectedColumns); + $this->basicTable->storeColumnSelectValues(); + $this->assertSame(['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg'], $this->basicTable->getStoredColumnSelectValues()); + $this->assertSame(['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg'], $this->basicTable->selectedColumns); + $this->basicTable->selectedColumns = ['rowimg']; + $this->assertSame(['rowimg'], $this->basicTable->selectedColumns); + $this->basicTable->restoreColumnSelectValues(); + $this->assertSame(['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg'], $this->basicTable->getStoredColumnSelectValues()); + $this->assertSame(['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg'], $this->basicTable->selectedColumns); + $this->basicTable->clearStoredColumnSelectValues(); + $this->assertSame([], $this->basicTable->getStoredColumnSelectValues()); + $this->assertSame(['id', 'sort', 'name', 'age', 'breed', 'other', 'rowimg'], $this->basicTable->selectedColumns); + } +} diff --git a/tests/Traits/Helpers/TableAttributeHelpersTest.php b/tests/Traits/Helpers/TableAttributeHelpersTest.php new file mode 100644 index 000000000..ec62d40c2 --- /dev/null +++ b/tests/Traits/Helpers/TableAttributeHelpersTest.php @@ -0,0 +1,29 @@ +basicTable->getTopLevelAttributesArray(); + $this->assertSame('shouldBeDisplayed', $topLevelAttributesArray['x-show']); + $this->assertSame('showTable(event)', $topLevelAttributesArray['x-on:show-table.window']); + $this->assertSame('hideTable(event)', $topLevelAttributesArray['x-on:hide-table.window']); + $this->assertSame('laravellivewiretable($wire)', $topLevelAttributesArray['x-data']); + } + + public function test_top_level_attribute_bag_matches(): void + { + $topLevelAttributeBag = $this->basicTable->getTopLevelAttributes(); + + $topLevelAttributesArray = $topLevelAttributeBag->getAttributes(); + + $this->assertSame('shouldBeDisplayed', $topLevelAttributesArray['x-show']); + $this->assertSame('showTable(event)', $topLevelAttributesArray['x-on:show-table.window']); + $this->assertSame('hideTable(event)', $topLevelAttributesArray['x-on:hide-table.window']); + $this->assertSame('laravellivewiretable($wire)', $topLevelAttributesArray['x-data']); + } +} diff --git a/tests/Traits/Visuals/ComponentVisualsTest.php b/tests/Traits/Visuals/ComponentVisualsTest.php index 62cd5cf6b..1b2df3adf 100644 --- a/tests/Traits/Visuals/ComponentVisualsTest.php +++ b/tests/Traits/Visuals/ComponentVisualsTest.php @@ -48,15 +48,15 @@ public function test_fails_when_table_has_no_pk(): void Livewire::test(NoPrimaryKeyTable::class); } catch (DataTableConfigurationException $DataTableConfigurationException) { $this->testErrors = true; - $this->assertSame('You must set a primary key using setPrimaryKey in the configure method.', substr($DataTableConfigurationException->getMessage(), 0, 71)); + $this->assertSame('You must set a primary key using setPrimaryKey in the configure method, or configuring/configured lifecycle hooks', substr($DataTableConfigurationException->getMessage(), 0, 113)); } catch (ViewException $ViewException) { $this->testErrors = true; - $this->assertSame('You must set a primary key using setPrimaryKey in the configure method.', substr($ViewException->getMessage(), 0, 71)); + $this->assertSame('You must set a primary key using setPrimaryKey in the configure method, or configuring/configured lifecycle hooks', substr($ViewException->getMessage(), 0, 113)); } catch (Exception $standardException) { $this->testErrors = true; - $this->assertSame('You must set a primary key using setPrimaryKey in the configure method.', substr($standardException->getMessage(), 0, 71)); + $this->assertSame('You must set a primary key using setPrimaryKey in the configure method, or configuring/configured lifecycle hooks', substr($standardException->getMessage(), 0, 113)); } if (! $this->testErrors) { $this->fail('Did Not Throw Error - Missing Primary Key'); diff --git a/tests/Traits/Visuals/HideableTableTest.php b/tests/Traits/Visuals/HideableTableTest.php new file mode 100644 index 000000000..6af61ed75 --- /dev/null +++ b/tests/Traits/Visuals/HideableTableTest.php @@ -0,0 +1,69 @@ +setPrimaryKey('id'); + } + + public function bulkActions(): array + { + return ['exportBulk' => 'exportBulk']; + } + + public function exportBulk($items) + { + return $items; + } + }); + Livewire::test($petsTable) + ->assertSet('shouldBeDisplayed', true) + ->assertSee('Cartman'); + } + + public function test_can_see_table_if_shown(): void + { + $this->setupEventsTable(); + + Livewire::test($this->eventsTable) + ->assertSet('shouldBeDisplayed', false) + ->assertSee('Cartman') + ->call('setShouldBeDisplayed') + ->assertSet('shouldBeDisplayed', true) + ->assertSee('Cartman'); + + } + + public function test_can_not_see_hidden_table(): void + { + $this->setupEventsTable(); + + Livewire::test($this->eventsTable) + ->assertSee('Cartman') + ->assertSet('shouldBeDisplayed', false) + ->assertSee('Cartman'); + } + + public function test_can_show_hidden_table(): void + { + $this->setupEventsTable(); + + Livewire::test($this->eventsTable) + ->assertSet('shouldBeDisplayed', false) + ->dispatch('showTable') + ->assertSet('shouldBeDisplayed', true) + ->assertSee('Cartman'); + + } +} diff --git a/tests/Traits/Visuals/PaginationVisualsTest.php b/tests/Traits/Visuals/PaginationVisualsTest.php index 95d9f5e56..95cdfd062 100644 --- a/tests/Traits/Visuals/PaginationVisualsTest.php +++ b/tests/Traits/Visuals/PaginationVisualsTest.php @@ -184,7 +184,7 @@ public function test_detailed_pagination_is_not_displayed_simple_tw(): void public function test_detailed_pagination_is_displayed_standard_bs4(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-4') + ->call('setTheme', 'bootstrap-4') ->call('enableDetailedPagination', 'standard') ->assertSeeHtmlInOrder(['
', 'Showing', @@ -197,7 +197,7 @@ public function test_detailed_pagination_is_displayed_standard_bs4(): void public function test_detailed_pagination_is_displayed_simple_bs4(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-4') + ->call('setTheme', 'bootstrap-4') ->call('enableDetailedPagination', 'simple') ->assertSeeHtmlInOrder(['
', 'Showing', @@ -210,7 +210,7 @@ public function test_detailed_pagination_is_displayed_simple_bs4(): void public function test_detailed_pagination_is_not_displayed_standard_bs4(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-4') + ->call('setTheme', 'bootstrap-4') ->call('disableDetailedPagination', 'standard') ->assertDontSeeHtml('Showing') ->assertDontSeeHtml('to') @@ -220,7 +220,7 @@ public function test_detailed_pagination_is_not_displayed_standard_bs4(): void public function test_detailed_pagination_is_not_displayed_simple_bs4(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-4') + ->call('setTheme', 'bootstrap-4') ->call('disableDetailedPagination', 'simple') ->assertDontSeeHtml('Showing') ->assertDontSeeHtml('to'); @@ -229,7 +229,7 @@ public function test_detailed_pagination_is_not_displayed_simple_bs4(): void public function test_detailed_pagination_is_displayed_standard_bs5(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-5') + ->call('setTheme', 'bootstrap-5') ->call('enableDetailedPagination', 'standard') ->assertSeeHtmlInOrder(['
', 'Showing', @@ -242,7 +242,7 @@ public function test_detailed_pagination_is_displayed_standard_bs5(): void public function test_detailed_pagination_is_displayed_simple_bs5(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-5') + ->call('setTheme', 'bootstrap-5') ->call('enableDetailedPagination', 'simple') ->assertSeeHtmlInOrder(['
', 'Showing', @@ -255,7 +255,7 @@ public function test_detailed_pagination_is_displayed_simple_bs5(): void public function test_detailed_pagination_is_not_displayed_standard_bs5(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-5') + ->call('setTheme', 'bootstrap-5') ->call('disableDetailedPagination', 'standard') ->assertDontSeeHtml('Showing') ->assertDontSeeHtml('to') @@ -265,7 +265,7 @@ public function test_detailed_pagination_is_not_displayed_standard_bs5(): void public function test_detailed_pagination_is_not_displayed_simple_bs5(): void { Livewire::test(PetsTable::class) - ->set('theme', 'bootstrap-5') + ->call('setTheme', 'bootstrap-5') ->call('disableDetailedPagination', 'simple') ->assertDontSeeHtml('Showing') ->assertDontSeeHtml('to'); diff --git a/tests/Traits/Visuals/SortingVisualsTest.php b/tests/Traits/Visuals/SortingVisualsTest.php index 4b2d44275..6419f2643 100644 --- a/tests/Traits/Visuals/SortingVisualsTest.php +++ b/tests/Traits/Visuals/SortingVisualsTest.php @@ -121,7 +121,6 @@ public function test_multiple_sorting_pill_shows_with_single_column_off(): void public function test_sorting_pill_shows_correct_name_and_direction(): void { Livewire::test(PetsTable::class) - ->assertDontSee('Key') ->call('sortBy', 'id') ->assertSee('Key') ->assertSee('0-9')