phplaravel

Laravel Dashboard with multiple components


I am trying to create a dashboard where a user can choose which widgets they want to see on their dashboard. Those widgets must be within what his role can do.


Solution

  • Step 1: Create migrations.

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    class CreateDashboardTilesTable extends Migration
    {
        public function up()
        {
            Schema::create('dashboard_tiles', function (Blueprint $table) {
                $table->id();
                $table->string('widget_type')->nullable();
                $table->string('crud_model')->nullable();
                $table->string('groupbycolumn')->nullable();
                $table->string('title')->nullable();
                $table->string('ranges')->nullable();
                $table->integer('position')->nullable();
                $table->integer('width')->nullable();
                $table->integer('height')->nullable();
                $table->timestamps();
                $table->softDeletes();
            });
        }
    }
    

    Step2 : Create Model:

    <?php
    
    namespace App\Models;
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class DashboardTile extends Model
    {
    -----
    ----
    ---
    
    --
    }
    

    Step3: Livewire Component:

    <?php
    namespace App\Http\Livewire;
    use Livewire\Component;
    use Illuminate\Support\Facades\Auth;
    use App\Models\DashboardTile;
    use App\Traits\DashboardTraits;
    
    
        class DashboardComponent extends Component
        {
            use DashboardTraits;
            public $updatemode=false;
            protected $listeners = ['widgetAdded'];
            public $modalFormVisible = false;
            public $modalWidth  = '7xl';
            public $aggregate_function,$crud_model,$widget_type,$groupbycolumn,$title,$ranges,$position,$width,$height;
            public $groupingcolumns=[];
        
            public function getDashboardWidgetsProperty(){
               return  $this->widgetAdded();
            }
            protected $rules = [
                'widget_type' => 'required',
                'crud_model' => 'required',
                'groupbycolumn' => 'required',
                'title' => 'required',
                'width' => 'required',
                'height' => 'required'
                
            ];
        
        
            public function create(){
                $this->validate();
                DashboardTile::create([
                    'widget_type' => $this->widget_type,
                    'crud_model' => $this->crud_model,
                    'groupbycolumn' => $this->groupbycolumn,
                    'title' => $this->title,
                    'ranges' => $this->ranges,
                    'position'=>$this->position,
                    'width'=>$this->width,
                    'height'=>$this->height
        
                ]);
               $this->refreshPages();
            }
         
        
            public function refreshpages(){
                $this->reset();
                $this->emitTo('DashboardComponent', 'widgetAdded');
              
            }
           
        public function widgetAdded(){
            return  DashboardTile::where('created_by','=',Auth::user()->id)->orderBy('position', 'ASC')->get();
        }
        
           
            public function render()
            {
                return view('dashboard');
            }
            public function createShowModal()
            {
                $this->modalFormVisible = true;
            }
          
            public function closeCreateModal(){
                $this->modalFormVisible = false;
                $this->reset();
            }
            
           
           
          
        }
    

    Step 4: Create DashboardTraits.

    <?php
    
    namespace App\Traits;
    use Illuminate\Support\Carbon;
    use Illuminate\Support\Facades\App;
    use Illuminate\Support\Facades\File;
    use Illuminate\Support\Facades\Schema;
    use Illuminate\Database\Eloquent\Model;
    use App\Models\DashboardTile;
    
    trait DashboardTraits
    {
       public $modelId;
       public $modalConfirmDeleteVisible = false;
        public function displaymodels(): array
        {
            $composer = json_decode(file_get_contents(base_path('composer.json')), true);
            $models = [];
            foreach ((array)data_get($composer, 'autoload.psr-4') as $namespace => $path) {
                $models = array_merge(collect(File::allFiles(base_path($path)))
                    ->map(function ($item) use ($namespace) {
                        $path = $item->getRelativePathName();
                        return sprintf('\%s%s',
                            $namespace,
                            strtr(substr($path, 0, strrpos($path, '.')), '/', '\\'));
                    })
                    ->filter(function ($class) {
                        $valid = false;
                        if (class_exists($class)) {
                            $reflection = new \ReflectionClass($class);
                            $valid = $reflection->isSubclassOf(Model::class) &&
                                !$reflection->isAbstract();
                        }
                        return $valid;
                    })
                    ->values()
                    ->toArray(), $models);
            }
            return $models;
        }
        public function displaycolumns($modelname){
          $table= $modelname::getModel()->getTable(); 
          $primaryKey = App::make($modelname)->getKeyName();
           $cols=  Schema::getColumnListing($table);
           $colsWithFields = [];
           foreach ($cols as $key => $column) {
               $columntype= Schema::getColumnType($table,$column);
               if(!in_array($column, array($primaryKey,'deleted_by','deleted_at','restored_by'))){
                   $columnlabel =   ucfirst(str_replace('_', ' ', $column));
                if( $columntype== 'datetime'){
                    $colsWithFields[$column.'|DAY'] = 'DAY('.$columnlabel.')';
                    $colsWithFields[$column.'|DATE'] = 'DATE('.$columnlabel.')';
                    $colsWithFields[$column.'|MONTH'] = 'MONTH('.$columnlabel.')';
                    $colsWithFields[$column.'|YEAR'] = 'YEAR('.$columnlabel.')';
                    
                }else if( $columntype== 'text') {}
    
                else{
                    $colsWithFields[$column] = $columnlabel;
                }
            }
    
              
    
        }
      
        return $colsWithFields;
           
        }
        public function addDateRangeFilter($query){
       
            switch($this->AvailableRanges){
                case 'TODAY':
                    $query->whereDate('created_at', Carbon::today());
                    break;
                case 'WEEK':
                    $query->whereBetween('created_at', [Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek()]);
                    break; 
                case 'MONTH':
                    $query->whereMonth('created_at', date('m'))
                            ->whereYear('created_at', date('Y'));
                    break;
                case 'YEAR':
                    $query->whereYear('created_at', date('Y'));
                    break;
            }
        
            return $query;
        }
        
    public function addSelectFilters($query){
        $groupbycolumn=  $this->groupbycolumn;
        $groupbycolumnArr = explode("|",$groupbycolumn);
    if(count($groupbycolumnArr)>1){
        switch($groupbycolumnArr[1]){
            case 'DAY':
                $query->selectRaw('(COUNT(*)) as count, DAYNAME('.$groupbycolumnArr[0].') as label');
                break;
            case 'DATE':
                    $query->selectRaw('(COUNT(*)) as count, DATE_FORMAT('.$groupbycolumnArr[0].',"%d/%m/%Y") as label');
                    break;
                
            case 'YEAR':
                $query->selectRaw('(COUNT(*)) as count, YEAR('.$groupbycolumnArr[0].') as label');
                break;
            case 'MONTH':
                $query->selectRaw('(COUNT(*)) as count, MONTHNAME('.$groupbycolumnArr[0].') as label');
                break;
            default:
            $query->selectRaw('(COUNT(*)) as count, ('.$groupbycolumnArr[0].') as label');
            break;
            }
        }
        else{
            $query->selectRaw('(COUNT(*)) as count, '.$groupbycolumn.' as label');
        }
          
        return $query;
    }
    
         /**
         * Get the ranges available.
         *
         * @return array
         */
        public function getAvailableRangesProperty()
        {
            return $this->allRanges()[$this->ranges ?? 'all'];
            
        }
        public function allRanges(){
            return $ranges = [
                'Today' => 'TODAY',
                'This Week' => 'WEEK',
                'This Month' => 'MONTH',
                'This Year' => 'YEAR',
                'all' => ''
            ];
        }
       }
    

    Examples:

    I created a package for dashboard widget creating in laravel livewire. You can refer that for more details.

    https://github.com/shihabphp/livewire-dashboard

    enter image description here