├── src ├── views │ ├── html.blade.php │ └── javascript.blade.php ├── LaravelChartsServiceProvider.php └── Classes │ └── LaravelChart.php ├── composer.json ├── license.md └── readme.md /src/views/html.blade.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/LaravelChartsServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadViewsFrom(__DIR__.'/views', 'laravelchart'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laraveldaily/laravel-charts", 3 | "description": "Create charts and reports from Laravel", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Povilas Korop", 8 | "email": "povilas@laraveldaily.com" 9 | } 10 | ], 11 | "minimum-stability": "dev", 12 | "require": {}, 13 | "autoload": { 14 | "psr-4": { 15 | "LaravelDaily\\LaravelCharts\\": "src" 16 | } 17 | }, 18 | "extra": { 19 | "laravel": { 20 | "providers": [ 21 | "LaravelDaily\\LaravelCharts\\LaravelChartsServiceProvider" 22 | ] 23 | } 24 | }, 25 | "version": "0.2.3" 26 | } 27 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2019 LaravelDaily 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/views/javascript.blade.php: -------------------------------------------------------------------------------- 1 | 78 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Laravel Charts 2 | 3 | Package to generate Chart.js charts directly from Laravel/Blade, without interacting with JavaScript. 4 | 5 | --- 6 | 7 | ## Simple Usage 8 | 9 | ![Laravel Charts - Users by Months](https://laraveldaily.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-18-at-2.37.09-PM.png) 10 | 11 | If you want to generate a chart above, grouping __users__ records by the month of __created_at__ value, here's the code. 12 | 13 | __Controller__: 14 | 15 | ```php 16 | use LaravelDaily\LaravelCharts\Classes\LaravelChart; 17 | 18 | // ... 19 | 20 | $chart_options = [ 21 | 'chart_title' => 'Users by months', 22 | 'report_type' => 'group_by_date', 23 | 'model' => 'App\Models\User', 24 | 'group_by_field' => 'created_at', 25 | 'group_by_period' => 'month', 26 | 'chart_type' => 'bar', 27 | ]; 28 | $chart1 = new LaravelChart($chart_options); 29 | 30 | return view('home', compact('chart1')); 31 | ``` 32 | 33 | __View File__ 34 | 35 | ```blade 36 | @extends('layouts.app') 37 | 38 | @section('content') 39 |
40 |
41 |
42 |
43 |
Dashboard
44 | 45 |
46 | 47 |

{{ $chart1->options['chart_title'] }}

48 | {!! $chart1->renderHtml() !!} 49 | 50 |
51 | 52 |
53 |
54 |
55 |
56 | @endsection 57 | 58 | @section('javascript') 59 | {!! $chart1->renderChartJsLibrary() !!} 60 | {!! $chart1->renderJs() !!} 61 | @endsection 62 | 63 | ``` 64 | 65 | --- 66 | 67 | ## Installation 68 | 69 | ```sh 70 | composer require laraveldaily/laravel-charts 71 | ``` 72 | 73 | No additional configuration or other parameters yet. 74 | 75 | --- 76 | 77 | ## Usage 78 | 79 | You need to create `LaravelChart` object in your Controller, passing array of options. 80 | 81 | ```php 82 | $chart = new LaravelChart($options); 83 | ``` 84 | 85 | Then pass it to the View, as a variable: 86 | 87 | ```php 88 | return view('dashboard', compact('chart')); 89 | ``` 90 | 91 | --- 92 | 93 | ## Available Reports and Options 94 | 95 | Currently package support three types of charts/reports: 96 | 97 | - `group_by_date` - amount of records from the same table, grouped by time period - day/week/month/year; 98 | - `group_by_string` - amount of records from the same table, grouped by any string field, like `name`; 99 | - `group_by_relationship` - amount of records from the same table, grouped by `belongsTo` relationship's field 100 | 101 | 102 | ### NOTE: From Laravel 8, all its models are placed in a folder called Models (App\Models\) 103 | 104 | __Example with all options__ 105 | 106 | ```php 107 | $chart_options = [ 108 | 'chart_title' => 'Transactions by dates', 109 | 'chart_type' => 'line', 110 | 'report_type' => 'group_by_date', 111 | 'model' => 'App\Models\Transaction', 112 | 'conditions' => [ 113 | ['name' => 'Food', 'condition' => 'category_id = 1', 'color' => 'black', 'fill' => true], 114 | ['name' => 'Transport', 'condition' => 'category_id = 2', 'color' => 'blue', 'fill' => true], 115 | ], 116 | 117 | 'group_by_field' => 'transaction_date', 118 | 'group_by_period' => 'day', 119 | 120 | 'aggregate_function' => 'sum', 121 | 'aggregate_field' => 'amount', 122 | 'aggregate_transform' => function($value) { 123 | return round($value / 100, 2); 124 | }, 125 | 126 | 'filter_field' => 'transaction_date', 127 | 'filter_days' => 30, // show only transactions for last 30 days 128 | 'filter_period' => 'week', // show only transactions for this week 129 | 'continuous_time' => true, // show continuous timeline including dates without data 130 | ]; 131 | ``` 132 | 133 | - `chart_title` (required) - just a text title that will be shown as legend; 134 | - `chart_type` (required) - possible values: "line", "bar", "pie"; 135 | - `report_type` (required) - see above, can be `group_by_date`, `group_by_string` or `group_by_relationship`; 136 | - `model` (required) - name of Eloquent model, where to take the data from; 137 | - `name` (optional) - just a text title that will be shown as title, otherwise the legend is used; 138 | - `conditions` (optional, only for `line` chart type) - array of conditions (name + raw condition + color) for multiple datasets; 139 | - `group_by_field` (required) - name of database field that will be used in `group_by` clause; 140 | - `group_by_period` (optional, only for `group_by_date` report type) - possible values are "day", "week", "month", "year"; 141 | - `relationship_name` (optional, only for `group_by_relationship` report type) - the name of model's method that contains `belongsTo` relationship. 142 | - `aggregate_function` (optional) - you can view not only amount of records, but also their `SUM()` or `AVG()`. Possible values: "count" (default), "avg", "sum". 143 | - `aggregate_field` (optional) - see `aggregate_function` above, the name of the field to use in `SUM()` or `AVG()` functions. Irrelevant for `COUNT()`. 144 | - `aggregate_transform` (optional) - callback function for additional transformation of aggregate number 145 | - `filter_field` (optional) - show only data filtered by that datetime field (see below) 146 | - `filter_days` (optional) - see `filter_field` above - show only last `filter_days` days of that field. Example, last __30__ days by `created_at` field. 147 | - `filter_period` (optional) - another way to filter by field, show only record from last __week__ / __month__ / __year__. Possible values are "week", "month", "year". 148 | - `continuous_time` (optional) - show all dates on chart, including dates without data. 149 | - `show_blank_data` (optional) - show date even if the data is blank based on `filter_days`. 150 | - `range_date_start` (optional) - show data in from a date range by `filter_field`, this is the start date. 151 | - `range_date_end` (optional) - show data in from a date range by `filter_field`, this is the end date. 152 | - `field_distinct` (optional) - field name required, it will apply a distinct(fieldname) 153 | - `style_class` (optional) - add class css in canvas 154 | - `date_format` (optional) - add the date format, by default: American format Y-m-d 155 | - `where_raw` (optional) - Condition in multiple consultation situations 156 | - `chart_height` (optional) - add the height in options, default 300px 157 | - `date_format_filter_days` (optional) - add the date format for Filter days 158 | - `withoutGlobalScopes` (optional) - removes global scope restriction from queried model 159 | - `with_trashed` (optional) - includes soft deleted models 160 | - `only_trashed` (optional) - only displays soft deleted models 161 | - `top_results` (optional, integer) - limit number of results shown, see [Issue #49](https://github.com/LaravelDaily/laravel-charts/issues/49) 162 | - `chart_color` (optional, value in rgba, like "0,255,255") - defines the color of the chart 163 | - `labels` (optional, array with key and value) - defines key value array mapping old and new values 164 | - `hidden` (optional, boolean) hides the current dataset. Useful when having multiple datasets in one chart 165 | - `stacked` (optional, boolean, only for bar chart) stacks the chart data when dates or strings match instead of showing it next to eachother 166 | 167 | - - - - - 168 | 169 | ## Example with relationship 170 | 171 | ```php 172 | $chart_options = [ 173 | 'chart_title' => 'Transactions by user', 174 | 'chart_type' => 'line', 175 | 'report_type' => 'group_by_relationship', 176 | 'model' => 'App\Models\Transaction', 177 | 178 | 'relationship_name' => 'user', // represents function user() on Transaction model 179 | 'group_by_field' => 'name', // users.name 180 | 181 | 'aggregate_function' => 'sum', 182 | 'aggregate_field' => 'amount', 183 | 184 | 'filter_field' => 'transaction_date', 185 | 'filter_days' => 30, // show only transactions for last 30 days 186 | 'filter_period' => 'week', // show only transactions for this week 187 | ]; 188 | ``` 189 | 190 | --- 191 | 192 | ## Rendering Charts in Blade 193 | 194 | After you passed `$chart` variable, into Blade, you can render it, by doing __three__ actions: 195 | 196 | __Action 1. Render HTML__. 197 | 198 | Wherever in your Blade, call this: 199 | 200 | ```blade 201 | {!! $chart1->renderHtml() !!} 202 | ``` 203 | 204 | It will generate something like this: 205 | 206 | ```html 207 | 208 | ``` 209 | 210 | __Action 2. Render JavaScript Library__ 211 | 212 | Package is using Chart.js library, so we need to initialize it somewhere in scripts section: 213 | 214 | ```blade 215 | {!! $chart1->renderChartJsLibrary() !!} 216 | ``` 217 | 218 | It will generate something like this: 219 | 220 | ```html 221 | 222 | ``` 223 | 224 | __Action 3. Render JavaScript of Specific Chart__ 225 | 226 | After Chart.js is loaded, launch this: 227 | 228 | ```blade 229 | {!! $chart1->renderJs() !!} 230 | ``` 231 | 232 | --- 233 | 234 | ## Using Multiple Charts 235 | 236 | You can show multiple charts on the same page, initialize them separately. 237 | 238 | __Controller__: 239 | 240 | ```php 241 | public function index() 242 | { 243 | $chart_options = [ 244 | 'chart_title' => 'Users by months', 245 | 'report_type' => 'group_by_date', 246 | 'model' => 'App\Models\User', 247 | 'group_by_field' => 'created_at', 248 | 'group_by_period' => 'month', 249 | 'chart_type' => 'bar', 250 | 'filter_field' => 'created_at', 251 | 'filter_days' => 30, // show only last 30 days 252 | ]; 253 | 254 | $chart1 = new LaravelChart($chart_options); 255 | 256 | 257 | $chart_options = [ 258 | 'chart_title' => 'Users by names', 259 | 'report_type' => 'group_by_string', 260 | 'model' => 'App\Models\User', 261 | 'group_by_field' => 'name', 262 | 'chart_type' => 'pie', 263 | 'filter_field' => 'created_at', 264 | 'filter_period' => 'month', // show users only registered this month 265 | ]; 266 | 267 | $chart2 = new LaravelChart($chart_options); 268 | 269 | $chart_options = [ 270 | 'chart_title' => 'Transactions by dates', 271 | 'report_type' => 'group_by_date', 272 | 'model' => 'App\Models\Transaction', 273 | 'group_by_field' => 'transaction_date', 274 | 'group_by_period' => 'day', 275 | 'aggregate_function' => 'sum', 276 | 'aggregate_field' => 'amount', 277 | 'chart_type' => 'line', 278 | ]; 279 | 280 | $chart3 = new LaravelChart($chart_options); 281 | 282 | return view('home', compact('chart1', 'chart2', 'chart3')); 283 | } 284 | ``` 285 | 286 | __View__: 287 | 288 | ```blade 289 | @extends('layouts.app') 290 | 291 | @section('content') 292 |
293 |
294 |
295 |
296 |
Dashboard
297 | 298 |
299 | 300 |

{{ $chart1->options['chart_title'] }}

301 | {!! $chart1->renderHtml() !!} 302 | 303 |
304 | 305 |

{{ $chart2->options['chart_title'] }}

306 | {!! $chart2->renderHtml() !!} 307 | 308 |
309 | 310 |

{{ $chart3->options['chart_title'] }}

311 | {!! $chart3->renderHtml() !!} 312 | 313 |
314 | 315 |
316 |
317 |
318 |
319 | @endsection 320 | 321 | @section('javascript') 322 | {!! $chart1->renderChartJsLibrary() !!} 323 | 324 | {!! $chart1->renderJs() !!} 325 | {!! $chart2->renderJs() !!} 326 | {!! $chart3->renderJs() !!} 327 | @endsection 328 | ``` 329 | 330 | ![Laravel Charts - Users by Months](https://laraveldaily.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-18-at-2.37.09-PM.png) 331 | 332 | ![Laravel Charts - Users by Names](https://laraveldaily.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-18-at-2.36.50-PM.png) 333 | 334 | ![Laravel Charts - Transactions by Dates](https://laraveldaily.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-18-at-2.37.27-PM.png) 335 | 336 | --- 337 | 338 | ## Multiple Datasets 339 | 340 | This is a new feature from v0.1.27. You can provide multiple arrays of settings to the `LaravelChart` constructor, and they will be drawn on the same chart. 341 | 342 | ```php 343 | $settings1 = [ 344 | 'chart_title' => 'Users', 345 | 'chart_type' => 'line', 346 | 'report_type' => 'group_by_date', 347 | 'model' => 'App\Models\User', 348 | 'group_by_field' => 'created_at', 349 | 'group_by_period' => 'day', 350 | 'aggregate_function' => 'count', 351 | 'filter_field' => 'created_at', 352 | 'filter_days' => '30', 353 | 'group_by_field_format' => 'Y-m-d H:i:s', 354 | 'column_class' => 'col-md-12', 355 | 'entries_number' => '5', 356 | 'translation_key' => 'user', 357 | 'continuous_time' => true, 358 | ]; 359 | $settings2 = [ 360 | 'chart_title' => 'Projects', 361 | 'chart_type' => 'line', 362 | 'report_type' => 'group_by_date', 363 | 'model' => 'App\Models\Project', 364 | // ... other values identical to $settings1 365 | ]; 366 | 367 | $chart1 = new LaravelChart($settings1, $settings2); 368 | ``` 369 | 370 | ![Multiple Datasets](https://laraveldaily.com/wp-content/uploads/2021/10/Screenshot-2021-10-08-at-07.30.04.png) 371 | 372 | --- 373 | 374 | ## License 375 | The MIT License (MIT). Please see [License File](license.md) for more information. 376 | 377 | --- 378 | 379 | ## More from our LaravelDaily Team 380 | 381 | - Enroll in our [Laravel Online Courses](https://laraveldaily.com/courses) 382 | - Check out our adminpanel generator [QuickAdminPanel](https://quickadminpanel.com) 383 | - Subscribe to our [YouTube channel Laravel Daily](https://www.youtube.com/channel/UCTuplgOBi6tJIlesIboymGA) 384 | -------------------------------------------------------------------------------- /src/Classes/LaravelChart.php: -------------------------------------------------------------------------------- 1 | 'Y-m-d', 21 | 'week' => 'Y-W', 22 | 'month' => 'Y-m', 23 | 'year' => 'Y', 24 | ]; 25 | 26 | /** 27 | * LaravelChart constructor. 28 | * @param $chart_options 29 | * @throws \Exception 30 | */ 31 | public function __construct() 32 | { 33 | foreach (func_get_args() as $arg) { 34 | $this->options = $arg; 35 | $this->options['chart_name'] = strtolower(Str::slug($arg['chart_title'], '_')); 36 | $this->datasets[] = $this->prepareData(); 37 | } 38 | } 39 | 40 | /** 41 | * @return array 42 | * @throws \Exception 43 | */ 44 | private function prepareData() 45 | { 46 | $this->validateOptions($this->options); 47 | 48 | try { 49 | if (!class_exists($this->options['model'])) { 50 | return []; 51 | } 52 | 53 | $dataset = []; 54 | $conditions = $this->options['conditions'] ?? 55 | [['name' => '', 'condition' => "", 'color' => '', 'fill' => '']]; 56 | 57 | foreach ($conditions as $condition) { 58 | if (isset($this->options['top_results']) && !is_int($this->options['top_results'])) { 59 | throw new \Exception('Top results value should be integer'); 60 | } 61 | 62 | $query = $this->options['model']::when(isset($this->options['filter_field']), function ($query) { 63 | 64 | if (isset($this->options['filter_days'])) { 65 | return $query->where( 66 | $this->options['filter_field'], 67 | '>=', 68 | now()->subDays($this->options['filter_days'])->format($this->options['date_format_filter_days'] ?? 'Y-m-d') 69 | ); 70 | } else if (isset($this->options['filter_period'])) { 71 | switch ($this->options['filter_period']) { 72 | case 'week': 73 | $start = date('Y-m-d', strtotime('last Monday')); 74 | break; 75 | case 'month': 76 | $start = date('Y-m') . '-01'; 77 | break; 78 | case 'year': 79 | $start = date('Y') . '-01-01'; 80 | break; 81 | } 82 | if (isset($start)) { 83 | return $query->where($this->options['filter_field'], '>=', $start); 84 | } 85 | } 86 | if (isset($this->options['range_date_start']) && isset($this->options['range_date_end'])) { 87 | return $query->whereBetween( 88 | $this->options['filter_field'], 89 | [$this->options['range_date_start'], $this->options['range_date_end']] 90 | ); 91 | } 92 | }); 93 | 94 | if (isset($this->options['where_raw']) && $this->options['where_raw'] != '') { 95 | $query->whereRaw($this->options['where_raw']); 96 | } 97 | 98 | if ($this->options['chart_type'] == 'line' && $condition['condition'] != '') { 99 | $query->whereRaw($condition['condition']); 100 | } 101 | 102 | if ($this->options['report_type'] == 'group_by_relationship') { 103 | $query->with($this->options['relationship_name']); 104 | } 105 | 106 | if (isset($this->options['with_trashed']) && $this->options['with_trashed']) { 107 | $query->withTrashed(); 108 | } 109 | 110 | if (isset($this->options['only_trashed']) && $this->options['only_trashed']) { 111 | $query->onlyTrashed(); 112 | } 113 | 114 | if (isset($this->options['withoutGlobalScopes']) && $this->options['withoutGlobalScopes']) { 115 | $scopesToExclude = is_array($this->options['withoutGlobalScopes']) 116 | ? $this->options['withoutGlobalScopes'] 117 | : null; 118 | 119 | $collection = $query->withoutGlobalScopes($scopesToExclude)->get(); 120 | } else { 121 | $collection = $query->get(); 122 | } 123 | 124 | if ($this->options['report_type'] != 'group_by_relationship') { 125 | $collection->where($this->options['group_by_field'], '!=', ''); 126 | } 127 | 128 | if (count($collection)) { 129 | $data = $collection 130 | ->sortBy($this->options['group_by_field']) 131 | ->groupBy(function ($entry) { 132 | if ($this->options['report_type'] == 'group_by_string') { 133 | return $entry->{$this->options['group_by_field']}; 134 | } else if ($this->options['report_type'] == 'group_by_relationship') { 135 | if ($entry->{$this->options['relationship_name']}) { 136 | return $entry->{$this->options['relationship_name']}->{$this->options['group_by_field']}; 137 | } else { 138 | return ''; 139 | } 140 | } else if ($entry->{$this->options['group_by_field']} instanceof \Carbon\Carbon) { 141 | return $entry->{$this->options['group_by_field']} 142 | ->format($this->options['date_format'] ?? self::GROUP_PERIODS[$this->options['group_by_period']]); 143 | } else { 144 | if ($entry->{$this->options['group_by_field']} && isset($this->options['group_by_field_format'])) { 145 | return \Carbon\Carbon::createFromFormat( 146 | $this->options['group_by_field_format'], 147 | $entry->{$this->options['group_by_field']} 148 | ) 149 | ->format($this->options['date_format'] ?? self::GROUP_PERIODS[$this->options['group_by_period']]); 150 | } else if ($entry->{$this->options['group_by_field']}) { 151 | return \Carbon\Carbon::createFromFormat( 152 | 'Y-m-d H:i:s', 153 | $entry->{$this->options['group_by_field']} 154 | ) 155 | ->format($this->options['date_format'] ?? self::GROUP_PERIODS[$this->options['group_by_period']]); 156 | } else { 157 | return ''; 158 | } 159 | } 160 | }) 161 | ->map(function ($entries) { 162 | if (isset($this->options['field_distinct'])) { 163 | $entries = $entries->unique($this->options['field_distinct']); 164 | } 165 | $aggregate = $entries->{$this->options['aggregate_function'] ?? 'count'}($this->options['aggregate_field'] ?? ''); 166 | if (@$this->options['aggregate_transform']) { 167 | $aggregate = $this->options['aggregate_transform']($aggregate); 168 | } 169 | return $aggregate; 170 | }) 171 | ->when(isset($this->options['top_results']), function ($coll) { 172 | return $coll 173 | ->sortDesc() 174 | ->take($this->options['top_results']) 175 | ->sortKeys(); 176 | }); 177 | } else { 178 | $data = collect([]); 179 | } 180 | 181 | 182 | if ( 183 | (isset($this->options['date_format']) || isset($this->options['group_by_period'])) && 184 | isset($this->options['filter_days']) && 185 | @$this->options['show_blank_data'] 186 | ) { 187 | $newData = collect([]); 188 | $format = $this->options['date_format'] ?? self::GROUP_PERIODS[$this->options['group_by_period']]; 189 | 190 | CarbonPeriod::since(now()->subDays($this->options['filter_days'])) 191 | ->until(now()) 192 | ->forEach(function (Carbon $date) use ($data, &$newData, $format) { 193 | $key = $date->format($format); 194 | $newData->put($key, $data[$key] ?? 0); 195 | }); 196 | 197 | $data = $newData; 198 | } 199 | 200 | if (@$this->options['continuous_time']) { 201 | $dates = $data->keys(); 202 | $interval = $this->options['group_by_period'] ?? 'day'; 203 | $newArr = []; 204 | if (!is_null($dates->first()) or !is_null($dates->last())) { 205 | if ($dates->first() === $dates->last()) { 206 | $firstDate = Carbon::createFromDate(($dates->first()))->addDays(-14); 207 | $lastDate = Carbon::createFromDate(($dates->last()))->addDays(14); 208 | } 209 | 210 | $period = CarbonPeriod::since($firstDate ?? $dates->first())->$interval()->until($lastDate ?? $dates->last()) 211 | ->filter(function (Carbon $date) use ($data, &$newArr) { 212 | $key = $date->format($this->options['date_format'] ?? 'Y-m-d'); 213 | $newArr[$key] = $data[$key] ?? 0; 214 | }) 215 | ->toArray(); 216 | $data = $newArr; 217 | } 218 | } 219 | 220 | $dataset = [ 221 | 'name' => $this->options['name'] ?? $this->options['chart_title'], 222 | 'color' => $condition['color'], 223 | 'chart_color' => $this->options['chart_color'] ?? '', 224 | 'fill' => $condition['fill'], 225 | 'data' => $data, 226 | 'hidden' => $this->options['hidden'] ?? false, 227 | 'stacked' => $this->options['stacked'] ?? false, 228 | ]; 229 | } 230 | 231 | if(!empty($this->options['labels'])) { 232 | foreach($this->options['labels'] as $key => $val) { 233 | if(array_key_exists($key, $data->toArray())) { 234 | $data[$val] = $data[$key]; 235 | unset($data[$key]); 236 | } 237 | } 238 | } 239 | 240 | return $dataset; 241 | } catch (\Error $ex) { 242 | throw new \Exception('Laravel Charts error: ' . $ex->getMessage()); 243 | } 244 | } 245 | 246 | /** 247 | * @param array $options 248 | * @throws \Exception 249 | */ 250 | private function validateOptions(array $options) 251 | { 252 | $rules = [ 253 | 'chart_title' => 'required', 254 | 'report_type' => 'required|in:group_by_date,group_by_string,group_by_relationship', 255 | 'model' => 'required|bail', 256 | 'group_by_field' => 'required|bail', 257 | 'group_by_period' => 'in:day,week,month,year|bail', 258 | 'aggregate_function' => 'in:count,sum,avg|bail', 259 | 'chart_type' => 'required|in:line,bar,pie|bail', 260 | 'filter_days' => 'integer', 261 | 'filter_period' => 'in:week,month,year', 262 | 'hidden' => 'boolean', 263 | 'stacked' => 'boolean', 264 | ]; 265 | 266 | $messages = [ 267 | 'required' => 'please specify :attribute option', 268 | 'report_type.in' => 'report_type option should contain one of these values - group_by_date/group_by_string', 269 | 'group_by_period.in' => 'group_by option should contain one of these values - day/week/month/year', 270 | 'aggregate_function.in' => 'number_function option should contain one of these values - count/sum/avg', 271 | 'chart_type.in' => 'chart_type option should contain one of these values - line/bar/pie', 272 | 'filter_period.in' => 'filter_period option should contain one of these values - week/month/year', 273 | ]; 274 | 275 | $attributes = [ 276 | 'chart_title' => 'chart_title', 277 | 'report_type' => 'report_type', 278 | 'group_by_field' => 'group_by_field', 279 | 'group_by_period' => 'group_by_period', 280 | 'aggregate_function' => 'aggregate_function', 281 | 'chart_type' => 'chart_type', 282 | 'filter_days' => 'filter_days', 283 | 'filter_period' => 'filter_period', 284 | 'field_distinct' => 'field_distinct', 285 | 'hidden' => 'hidden', 286 | 'stacked' => 'stacked', 287 | ]; 288 | 289 | $validator = Validator::make($options, $rules, $messages, $attributes); 290 | 291 | if ($validator->fails()) { 292 | throw new \Exception('Laravel Charts options validator: ' . $validator->errors()->first()); 293 | } 294 | } 295 | 296 | /** 297 | * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View 298 | */ 299 | public function renderHtml() 300 | { 301 | return view('laravelchart::html', ['options' => $this->options]); 302 | } 303 | 304 | /** 305 | * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\View\View 306 | */ 307 | public function renderJs() 308 | { 309 | return view('laravelchart::javascript', ['options' => $this->options, 'datasets' => $this->datasets]); 310 | } 311 | 312 | /** 313 | * @return string 314 | */ 315 | public function renderChartJsLibrary() 316 | { 317 | return ''; 318 | } 319 | 320 | /** 321 | * @return array 322 | */ 323 | public function getDatasets() { 324 | return $this->datasets; 325 | } 326 | } 327 | --------------------------------------------------------------------------------