2 Komitmen 4ea4f0a3a9 ... cb89d9fd37

Pembuat SHA1 Pesan Tanggal
  ttreasure cb89d9fd37 Made the buttons and columndefs datatables JSON dynamically driven from the DB. 4 bulan lalu
  ttreasure 3c3392f6f4 Added basic single-button action columns 4 bulan lalu

+ 4 - 0
app/Livewire/ShowReports.php

@@ -12,6 +12,8 @@ class ShowReports extends Component
     public $datatableName;
     public $datatableColumnsConfig;
     public $datatableHeadersConfig;
+    public $datatableButtonsConfig;
+    public $datatableColumnDefsConfig;
 
 
     public function mount($datatableName)
@@ -29,6 +31,8 @@ class ShowReports extends Component
         // Store the decoded JSON as a plain array
         $this->datatableColumnsConfig = json_decode($datatableConfigQuery->columns_config, true);
         $this->datatableHeadersConfig = json_decode($datatableConfigQuery->column_headers, true);
+        $this->datatableColumnDefsConfig = json_decode($datatableConfigQuery->column_defs, true);
+        $this->datatableButtonsConfig = json_decode($datatableConfigQuery->buttons, true);
     }
 
     public function render()

+ 49 - 0
database/migrations/2025_07_24_165629_add_buttons_and_columndefs_columns_to_datatables_table.php

@@ -0,0 +1,49 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::table('datatables', function (Blueprint $table) {
+            // Drop 5 old columns
+            $table->dropColumn(['enable_copy', 'enable_csv', 'enable_excel', 'enable_pdf', 'enable_print']);
+
+            // Add new JSON columns for buttons config
+            $buttons = [
+                ['extend' => 'copyHtml5',  'className' => 'dt-button'],
+                ['extend' => 'csvHtml5',   'className' => 'dt-button'],
+                ['extend' => 'excelHtml5', 'className' => 'dt-button'],
+                ['extend' => 'pdfHtml5',   'className' => 'dt-button'],
+                ['extend' => 'print',      'className' => 'dt-button'],
+            ];
+            $table->json('buttons')->default(json_encode($buttons));
+
+            $columnDefs = [
+            ['responsivePriority' => 1, 'targets' => 1],
+            ['responsivePriority' => 2, 'targets' => -1],
+            ['visible' => false, 'targets' => 0]
+        ];
+
+            $table->json('column_defs')->default(json_encode($columnDefs));
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+
+            Schema::table('datatables', function (Blueprint $table) {
+                // Drop the new JSON columns
+                $table->dropColumn(['buttons', 'column_defs']);
+            });
+    }
+};

+ 16 - 0
resources/css/datatables.css

@@ -37,3 +37,19 @@ body {
     background-color: white; /* even rows */
 }
 
+.action-button {
+    display: inline-block;
+    padding: 6px 12px;
+    background-color: grey;
+    color: black;
+    border: none;
+    border-radius: 4px;
+    text-decoration: none;
+    font-size: 14px;
+    cursor: pointer;
+}
+
+.action-button:hover {
+    background-color: darkgrey;
+}
+

+ 57 - 15
resources/js/datatables.js

@@ -14,20 +14,71 @@ import 'datatables.net-responsive-dt';
 
 
 
+
 // Ensure jQuery is available globally
 window.$ = window.jQuery = $;
 window.JSZip = JSZip;
 // Initialize DataTable
-let dataTableInstance;
+var dataTableInstance;
 var searchTerms ={};
 function initializeDataTable() {
     var dataTableName = document.getElementById('datatable-config').dataset.datatableName;
     var dataTableColumnsConfig = JSON.parse(document.getElementById('datatable-config').dataset.datatableColumnsConfig);
     var dataTableHeadersConfig = JSON.parse(document.getElementById('datatable-config').dataset.datatableHeadersConfig);
-    if ($.fn.DataTable.isDataTable(`#${dataTableName}-table`)) {
-        dataTableInstance.destroy();
-        $(`#${dataTableName}-table tbody`).empty(); // Clear rows to prevent residue
+    var dataTablesButtonsConfig = JSON.parse(document.getElementById('datatable-config').dataset.datatableButtonsConfig);
+    var dataTablesColumnDefsConfig = JSON.parse(document.getElementById('datatable-config').dataset.datatableColumnDefsConfig);
+
+
+    //Set up any action columns
+    function doActionButton(url, id)
+    {
+        window.open(url, "_blank");
     }
+    window.doActionButton=doActionButton;
+
+    var renderFunctions = [];
+    dataTableHeadersConfig.forEach(function (headerColumn, columnIndex){
+        if(headerColumn.type === "action")
+        {
+            let buttonUrl = dataTableColumnsConfig[columnIndex].buttonUrl;
+            let parameters = dataTableColumnsConfig[columnIndex].querystring_parameters;
+            console.log(parameters);
+            let renderBody = `if (type === "display") {console.log(row);`;
+            renderBody += `return '<button class="action-button" onclick="doActionButton(`;
+            renderBody += `\\'`+buttonUrl;
+            parameters.forEach(function (parameter, index){
+                if(index === 0)
+                {
+                    renderBody += '?';
+                }
+                else
+                {
+                    renderBody += '&';
+                }
+                for(let key in parameter)
+                {
+                    renderBody += key+'=';
+                    if(parameter[key] === 'row.id')
+                    {
+                        renderBody += '\'+'+encodeURIComponent(parameter[key])+'+\'';
+                    }
+                    else
+                    {
+                        renderBody += encodeURIComponent(parameter[key]);
+                    }
+                }
+
+            })
+            renderBody += `\\'`;
+            renderBody += ")\">"+dataTableColumnsConfig[columnIndex].buttonText+"</button>'}return data;";
+            renderFunctions[columnIndex] = new Function('data', 'type', 'row', 'meta', renderBody);
+            console.log(renderFunctions[columnIndex]);
+            dataTableColumnsConfig[columnIndex].searchable = false;
+            dataTableColumnsConfig[columnIndex].orderable = false;
+            dataTableColumnsConfig[columnIndex].render = renderFunctions[columnIndex];
+
+        }
+    })
 
     dataTableInstance = $(`#${dataTableName}-table`).DataTable({
         responsive: true,
@@ -81,20 +132,11 @@ function initializeDataTable() {
         },
         columns: dataTableColumnsConfig,
         dom: 'lBfrtip',
-        buttons: [
-            { extend: 'copyHtml5', className: 'dt-button' },
-            { extend: 'csvHtml5', className: 'dt-button' },
-            { extend: 'excelHtml5', className: 'dt-button' },
-            { extend: 'pdfHtml5', className: 'dt-button' },
-            { extend: 'print', className: 'dt-button' },
-        ],
+        buttons: dataTablesButtonsConfig,
         layout: {
             topStart: 'buttons'
         },
-        columnDefs: [
-            { responsivePriority: 1, targets: 0 },
-            { responsivePriority: 2, targets: -1 }
-        ]
+        columnDefs: dataTablesColumnDefsConfig
     });
 }
 document.addEventListener('livewire:init', function () {

+ 3 - 1
resources/views/livewire/show-reports.blade.php

@@ -3,7 +3,9 @@
     <div id="datatable-config"
          data-datatable-name="{{ $datatableName }}"
          data-datatable-columns-config='@json($datatableColumnsConfig)'
-         data-datatable-headers-config='@json($datatableHeadersConfig)'>
+         data-datatable-headers-config='@json($datatableHeadersConfig)'
+         data-datatable-buttons-config='@json($datatableButtonsConfig)'
+         data-datatable-column-defs-config='@json($datatableColumnDefsConfig)'>
     </div>
 
     <table id="{{$datatableName}}-table" class="bg-white border border-gray-300">