Merge pull request #1058 from denisdulici/master

New widget structure
This commit is contained in:
Denis Duliçi 2019-12-31 02:21:14 +03:00 committed by GitHub
commit ad2b69b9b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 333 additions and 502 deletions

View File

@ -2,31 +2,31 @@
namespace App\Abstracts;
use Arrilot\Widgets\AbstractWidget;
use App\Models\Income\Invoice;
use App\Traits\Charts;
use Date;
abstract class Widget extends AbstractWidget
abstract class Widget
{
use Charts;
/**
* The configuration array.
*
* @var array
*/
protected $config = [
'width' => 'col-md-4',
];
public $model;
/**
* Treat this method as a controller action.
* Return view() or other content to display.
*/
public function run()
public function __construct($model = null)
{
return $this->show();
$this->model = $model;
}
public function getDefaultSettings()
{
return [
'width' => 'col-md-4',
];
}
public function view($name, $data = [])
{
return view($name, array_merge(['model' => $this->model], (array) $data));
}
public function applyFilters($model, $args = ['date_field' => 'paid_at'])
@ -38,7 +38,7 @@ abstract class Widget extends AbstractWidget
$start_date = request()->get('start_date') . ' 00:00:00';
$end_date = request()->get('end_date') . ' 23:59:59';
return $model->whereBetween($args['date_field'], [$start_date, $end_date]);
return $model->whereBetween($args['date_field'], [$start_date, $end_date]);
}
public function calculateDocumentTotals($model)

View File

@ -10,6 +10,6 @@
"files": [],
"requires": [],
"reports": [],
"settings": [],
"widgets": []
"widgets": [],
"settings": []
}

View File

@ -3,10 +3,9 @@
namespace App\Http\Controllers\Common;
use App\Abstracts\Http\Controller;
use App\Models\Common\Dashboard as Model;
use App\Models\Common\DashboardWidget;
use App\Http\Requests\Common\Dashboard as Request;
use App\Models\Common\Dashboard as Model;
use App\Models\Common\Widget;
use App\Traits\DateTime;
class Dashboard extends Controller
@ -40,14 +39,12 @@ class Dashboard extends Controller
// Dashboard
$dashboard = Model::find($dashboard_id);
// Dashboard Widgets
$widgets = DashboardWidget::where('dashboard_id', $dashboard->id)
->where('user_id', $user_id)
->orderBy('sort', 'asc')->get();
// Widgets
$widgets = Widget::where('dashboard_id', $dashboard->id)->orderBy('sort', 'asc')->get();
$financial_start = $this->getFinancialStart()->format('Y-m-d');
return view('common.dashboard.index', compact('dashboards','dashboard', 'widgets', 'financial_start'));
return view('common.dashboard.index', compact('dashboards', 'dashboard', 'widgets', 'financial_start'));
}
/**

View File

@ -3,10 +3,9 @@
namespace App\Http\Controllers\Common;
use App\Abstracts\Http\Controller;
use App\Models\Common\DashboardWidget as Model;
use App\Models\Common\Widget;
use App\Http\Requests\Common\Widget as Request;
use App\Models\Common\Widget;
use App\Utilities\Widgets as Utility;
class Widgets extends Controller
{
@ -17,7 +16,7 @@ class Widgets extends Controller
*/
public function index()
{
$widgets = Widget::enabled()->get();
$widgets = Utility::getClasses();
return response()->json($widgets);
}
@ -30,13 +29,11 @@ class Widgets extends Controller
*/
public function store(Request $request)
{
$request['user_id'] = user()->id;
$request['settings'] = [
'width' => $request->get('width'),
];
$widget = Model::create($request->input());
$widget = Widget::create($request->input());
$settings = $widget->settings;
unset($settings['widget']);
@ -59,17 +56,17 @@ class Widgets extends Controller
/**
* Show the form for editing the specified resource.
*
* @param Model $dashboard
* @param Widget $widget
*
* @return Response
*/
public function edit(Model $widget)
public function edit(Widget $widget)
{
$settings = $widget->settings;
unset($settings['widget']);
return response()->json([
'widget_id' => $widget->widget_id,
'class' => $widget->class,
'name' => $widget->name,
'settings' => $settings,
'sort' => $widget->sort,
@ -79,14 +76,12 @@ class Widgets extends Controller
/**
* Update the specified resource in storage.
*
* @param Model $dashboard
* @param Widget $widget
* @param $request
* @return Response
*/
public function update(Model $widget, Request $request)
public function update(Widget $widget, Request $request)
{
$request['user_id'] = user()->id;
$request['settings'] = [
'width' => $request->get('width'),
];
@ -102,7 +97,7 @@ class Widgets extends Controller
'error' => false,
'message' => trans('messages.success.added', ['type' => $widget->name]),
'data' => [
'widget_id' => $widget->widget_id,
'class' => $widget->class,
'name' => $widget->name,
'settings' => $settings,
'sort' => $widget->sort,
@ -114,11 +109,11 @@ class Widgets extends Controller
/**
* Remove the specified resource from storage.
*
* @param Model $dashboard
* @param Widget $widget
*
* @return Response
*/
public function destroy(Model $widget)
public function destroy(Widget $widget)
{
$message = trans('messages.success.deleted', ['type' => $widget->name]);

View File

@ -28,7 +28,7 @@ class DeleteUser extends Job
{
$this->authorize();
$this->deleteRelationships($this->user, ['dashboards', 'dashboard_widgets']);
$this->deleteRelationships($this->user, ['widgets', 'dashboards']);
$this->user->delete();

View File

@ -33,9 +33,9 @@ class DeleteCompany extends Job
$this->deleteRelationships($this->company, [
'accounts', 'bills', 'bill_histories', 'bill_items', 'bill_item_taxes', 'bill_statuses', 'bill_totals', 'categories',
'contacts', 'currencies', 'dashboards', 'dashboard_widgets', 'email_templates', 'invoices', 'invoice_histories',
'invoice_items', 'invoice_item_taxes', 'invoice_statuses', 'invoice_totals', 'items', 'modules', 'module_histories',
'reconciliations', 'recurring', 'reports', 'settings', 'taxes', 'transactions', 'transfers', 'widgets',
'contacts', 'currencies', 'dashboards', 'email_templates', 'invoices', 'invoice_histories', 'invoice_items',
'invoice_item_taxes', 'invoice_statuses', 'invoice_totals', 'items', 'modules', 'module_histories', 'reconciliations',
'recurring', 'reports', 'settings', 'taxes', 'transactions', 'transfers', 'widgets',
]);
$this->company->delete();

View File

@ -62,9 +62,9 @@ class User extends Authenticatable
return $this->hasMany('App\Models\Common\Dashboard');
}
public function dashboard_widgets()
public function widgets()
{
return $this->hasMany('App\Models\Common\DashboardWidget');
return $this->hasManyThrough('App\Models\Common\Widget', 'App\Models\Common\Dashboard');
}
/**

View File

@ -98,11 +98,6 @@ class Company extends Eloquent
return $this->hasMany('App\Models\Common\Dashboard');
}
public function dashboard_widgets()
{
return $this->hasMany('App\Models\Common\DashboardWidget');
}
public function email_templates()
{
return $this->hasMany('App\Models\Common\EmailTemplate');

View File

@ -27,7 +27,7 @@ class Dashboard extends Model
public function widgets()
{
return $this->hasMany('App\Models\Common\DashboardWidget')->orderBy('sort', 'asc');
return $this->hasMany('App\Models\Common\Widget')->orderBy('sort', 'asc');
}
public function user()

View File

@ -1,65 +0,0 @@
<?php
namespace App\Models\Common;
use App\Abstracts\Model;
class DashboardWidget extends Model
{
protected $table = 'dashboard_widgets';
/**
* Attributes that should be mass-assignable.
*
* @var array
*/
protected $fillable = ['company_id', 'user_id', 'dashboard_id', 'widget_id', 'name', 'settings', 'sort'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts = [
'settings' => 'array',
];
public function user()
{
return $this->belongsTo('App\Models\Auth\User', 'user_id', 'id');
}
public function dashboard()
{
return $this->belongsTo('App\Models\Common\Dashboard');
}
public function widget()
{
return $this->belongsTo('App\Models\Common\Widget');
}
public function getNameAttribute($value)
{
if ($value) {
return $value;
}
return $this->widget->name;
}
public function getSettingsAttribute($value)
{
if (!empty($value)) {
$value = json_decode($value, true);
$value['widget'] = $this;
} else {
$value = [
'widget' => $this,
];
}
return $value;
}
}

View File

@ -16,14 +16,7 @@ class Widget extends Model
*
* @var array
*/
protected $fillable = ['company_id', 'name', 'alias', 'settings', 'enabled'];
/**
* Sortable columns.
*
* @var array
*/
public $sortable = ['name', 'alias', 'enabled'];
protected $fillable = ['company_id', 'dashboard_id', 'class', 'name', 'settings', 'sort'];
/**
* The attributes that should be casted to native types.
@ -31,16 +24,11 @@ class Widget extends Model
* @var array
*/
protected $casts = [
'settings' => 'array',
'settings' => 'object',
];
public function dashboard_widgets()
public function dashboard()
{
return $this->hasMany('App\Models\Common\DashboardWidget');
}
public function dashboard_widget()
{
return $this->belongsTo('App\Models\Common\DashboardWidget', 'id', 'widget_id')->where('dashboard_id', 1);
return $this->belongsTo('App\Models\Common\Dashboard');
}
}

View File

@ -20,6 +20,10 @@ class Blade extends ServiceProvider
Facade::directive('date', function ($expression) {
return "<?php echo company_date($expression); ?>";
});
Facade::directive('widget', function ($expression) {
return "<?php echo show_widget($expression); ?>";
});
}
/**

67
app/Utilities/Widgets.php Normal file
View File

@ -0,0 +1,67 @@
<?php
namespace App\Utilities;
use App\Models\Module\Module;
class Widgets
{
public static function getClasses()
{
$classes = [];
$core_classes = [
'App\Widgets\TotalIncome',
'App\Widgets\TotalExpenses',
'App\Widgets\TotalProfit',
'App\Widgets\CashFlow',
'App\Widgets\IncomeByCategory',
'App\Widgets\ExpensesByCategory',
'App\Widgets\AccountBalance',
'App\Widgets\LatestIncome',
'App\Widgets\LatestExpenses',
];
static::parseClasses($classes, $core_classes);
$modules = Module::enabled()->get();
foreach ($modules as $module) {
$m = module($module->alias);
// Check if the module exists and has widgets
if (!$m || empty($m->get('widgets'))) {
continue;
}
static::parseClasses($classes, $m->get('widgets'));
}
return $classes;
}
protected static function parseClasses(&$classes, $list)
{
foreach ($list as $class) {
if (!class_exists($class)) {
continue;
}
$name = (new $class())->getDefaultName();
$classes[$class] = $name;
}
}
public static function getInstance($model)
{
$class = $model->class;
return new $class($model);
}
public static function show($model)
{
return static::getInstance($model)->show();
}
}

View File

@ -1,6 +1,7 @@
<?php
use App\Traits\DateTime;
use App\Utilities\Widgets;
use Jenssegers\Date\Date;
if (!function_exists('user')) {
@ -37,3 +38,15 @@ if (!function_exists('company_date')) {
return Date::parse($date)->format($date_time->getCompanyDateFormat());
}
}
if (!function_exists('show_widget')) {
/**
* Format the given date based on company settings.
*
* @return string
*/
function show_widget($model)
{
return Widgets::show($model);
}
}

View File

@ -11,9 +11,13 @@ class AccountBalance extends Widget
{
$accounts = Account::enabled()->take(5)->get();
return view('widgets.account_balance', [
'config' => (object) $this->config,
return $this->view('widgets.account_balance', [
'accounts' => $accounts,
]);
}
public function getDefaultName()
{
return trans('widgets.account_balance');
}
}

View File

@ -13,10 +13,6 @@ class CashFlow extends Widget
{
use Currencies, DateTime;
protected $config = [
'width' => 'col-md-12',
];
public function show()
{
$financial_start = $this->getFinancialStart()->format('Y-m-d');
@ -96,8 +92,7 @@ class CashFlow extends Widget
])
->fill(false);
return view('widgets.cash_flow', [
'config' => (object) $this->config,
return $this->view('widgets.cash_flow', [
'chart' => $chart,
]);
}
@ -175,4 +170,16 @@ class CashFlow extends Widget
return $profit;
}
public function getDefaultName()
{
return trans('widgets.cash_flow');
}
public function getDefaultSettings()
{
return [
'width' => 'col-md-12',
];
}
}

View File

@ -7,10 +7,6 @@ use App\Models\Setting\Category;
class ExpensesByCategory extends Widget
{
protected $config = [
'width' => 'col-md-6',
];
public function show()
{
Category::with('expense_transactions')->type('expense')->enabled()->each(function ($category) {
@ -27,9 +23,20 @@ class ExpensesByCategory extends Widget
$chart = $this->getDonutChart(trans_choice('general.expenses', 2), 0, 160, 6);
return view('widgets.expenses_by_category', [
'config' => (object) $this->config,
return $this->view('widgets.expenses_by_category', [
'chart' => $chart,
]);
}
public function getDefaultName()
{
return trans('widgets.expenses_by_category');
}
public function getDefaultSettings()
{
return [
'width' => 'col-md-6',
];
}
}

View File

@ -7,10 +7,6 @@ use App\Models\Setting\Category;
class IncomeByCategory extends Widget
{
protected $config = [
'width' => 'col-md-6',
];
public function show()
{
Category::with('income_transacions')->type('income')->enabled()->each(function ($category) {
@ -27,9 +23,20 @@ class IncomeByCategory extends Widget
$chart = $this->getDonutChart(trans_choice('general.incomes', 1), 0, 160, 6);
return view('widgets.income_by_category', [
'config' => (object) $this->config,
return $this->view('widgets.income_by_category', [
'chart' => $chart,
]);
}
public function getDefaultName()
{
return trans('widgets.income_by_category');
}
public function getDefaultSettings()
{
return [
'width' => 'col-md-6',
];
}
}

View File

@ -11,9 +11,13 @@ class LatestExpenses extends Widget
{
$transactions = $this->applyFilters(Transaction::with('category')->type('expense')->orderBy('paid_at', 'desc')->isNotTransfer()->take(5))->get();
return view('widgets.latest_expenses', [
'config' => (object) $this->config,
return $this->view('widgets.latest_expenses', [
'transactions' => $transactions,
]);
}
public function getDefaultName()
{
return trans('widgets.latest_expenses');
}
}

View File

@ -11,9 +11,13 @@ class LatestIncome extends Widget
{
$transactions = $this->applyFilters(Transaction::with('category')->type('income')->orderBy('paid_at', 'desc')->isNotTransfer()->take(5))->get();
return view('widgets.latest_income', [
'config' => (object) $this->config,
return $this->view('widgets.latest_income', [
'transactions' => $transactions,
]);
}
public function getDefaultName()
{
return trans('widgets.latest_income');
}
}

View File

@ -36,9 +36,13 @@ class TotalExpenses extends Widget
'progress' => $progress,
];
return view('widgets.total_expenses', [
'config' => (object) $this->config,
return $this->view('widgets.total_expenses', [
'totals' => $totals,
]);
}
public function getDefaultName()
{
return trans('widgets.total_expenses');
}
}

View File

@ -30,15 +30,19 @@ class TotalIncome extends Widget
}
$totals = [
'current' => $current,
'open' => money($open, setting('default.currency'), true),
'overdue' => money($overdue, setting('default.currency'), true),
'progress' => $progress,
'current' => $current,
'open' => money($open, setting('default.currency'), true),
'overdue' => money($overdue, setting('default.currency'), true),
'progress' => $progress,
];
return view('widgets.total_income', [
'config' => (object) $this->config,
return $this->view('widgets.total_income', [
'totals' => $totals,
]);
}
public function getDefaultName()
{
return trans('widgets.total_income');
}
}

View File

@ -55,9 +55,13 @@ class TotalProfit extends Widget
'progress' => $progress,
];
return view('widgets.total_profit', [
'config' => (object) $this->config,
return $this->view('widgets.total_profit', [
'totals' => $totals,
]);
}
public function getDefaultName()
{
return trans('widgets.total_profit');
}
}

View File

@ -20,7 +20,6 @@
"akaunting/money": "1.0.*",
"akaunting/setting": "1.1.*",
"akaunting/version": "1.0.*",
"arrilot/laravel-widgets": "3.13.*",
"barryvdh/laravel-debugbar": "3.2.*",
"barryvdh/laravel-dompdf": "0.*",
"barryvdh/laravel-ide-helper": "2.6.*",

177
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "986f507365ca5ee6e150335aec149b15",
"content-hash": "1833d7d2fe4dd91486f71b8f08ffb15d",
"packages": [
{
"name": "akaunting/firewall",
@ -262,16 +262,16 @@
},
{
"name": "akaunting/money",
"version": "1.0.13",
"version": "1.0.14",
"source": {
"type": "git",
"url": "https://github.com/akaunting/money.git",
"reference": "da302568d31122b200cbd215622cb0ae47131524"
"reference": "058b2256344ca5cb17aa1fecb574f5264a2444ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/akaunting/money/zipball/da302568d31122b200cbd215622cb0ae47131524",
"reference": "da302568d31122b200cbd215622cb0ae47131524",
"url": "https://api.github.com/repos/akaunting/money/zipball/058b2256344ca5cb17aa1fecb574f5264a2444ef",
"reference": "058b2256344ca5cb17aa1fecb574f5264a2444ef",
"shasum": ""
},
"require": {
@ -319,7 +319,7 @@
"laravel",
"money"
],
"time": "2019-09-21T16:15:52+00:00"
"time": "2019-12-26T08:11:31+00:00"
},
{
"name": "akaunting/setting",
@ -440,68 +440,6 @@
],
"time": "2019-09-26T18:32:38+00:00"
},
{
"name": "arrilot/laravel-widgets",
"version": "3.13.0",
"source": {
"type": "git",
"url": "https://github.com/arrilot/laravel-widgets.git",
"reference": "24297e9a7b1988808b782567892170cd421e6715"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/arrilot/laravel-widgets/zipball/24297e9a7b1988808b782567892170cd421e6715",
"reference": "24297e9a7b1988808b782567892170cd421e6715",
"shasum": ""
},
"require": {
"illuminate/cache": ">=5.5",
"illuminate/console": ">=5.5",
"illuminate/container": ">=5.5",
"illuminate/contracts": ">=5.5",
"illuminate/support": ">=5.5",
"illuminate/view": ">=5.5",
"php": ">=7.0"
},
"require-dev": {
"phpunit/phpunit": "~6.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Arrilot\\Widgets\\ServiceProvider"
],
"aliases": {
"Widget": "Arrilot\\Widgets\\Facade",
"AsyncWidget": "Arrilot\\Widgets\\AsyncFacade"
}
}
},
"autoload": {
"psr-4": {
"Arrilot\\Widgets\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nekrasov Ilya",
"email": "nekrasov.ilya90@gmail.com"
}
],
"description": "A powerful alternative to view composers. Asynchronous widgets, reloadable widgets, console generator, caching - everything you can think of.",
"homepage": "https://github.com/arrilot/laravel-widgets",
"keywords": [
"ajax",
"laravel",
"widgets"
],
"time": "2019-03-25T14:20:55+00:00"
},
{
"name": "balping/json-raw-encoder",
"version": "v1.0.0",
@ -2041,27 +1979,26 @@
},
{
"name": "egulias/email-validator",
"version": "2.1.12",
"version": "2.1.13",
"source": {
"type": "git",
"url": "https://github.com/egulias/EmailValidator.git",
"reference": "a6255605af39f2db7f5cb62e672bd8a7bad8d208"
"reference": "834593d5900615639208417760ba6a17299e2497"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/a6255605af39f2db7f5cb62e672bd8a7bad8d208",
"reference": "a6255605af39f2db7f5cb62e672bd8a7bad8d208",
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/834593d5900615639208417760ba6a17299e2497",
"reference": "834593d5900615639208417760ba6a17299e2497",
"shasum": ""
},
"require": {
"doctrine/lexer": "^1.0.1",
"php": ">= 5.5"
"php": ">=5.5"
},
"require-dev": {
"dominicsayers/isemail": "dev-master",
"phpunit/phpunit": "^4.8.35||^5.7||^6.0",
"satooshi/php-coveralls": "^1.0.1",
"symfony/phpunit-bridge": "^4.4@dev"
"dominicsayers/isemail": "^3.0.7",
"phpunit/phpunit": "^4.8.36|^7.5.15",
"satooshi/php-coveralls": "^1.0.1"
},
"suggest": {
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
@ -2095,7 +2032,7 @@
"validation",
"validator"
],
"time": "2019-12-20T12:49:39+00:00"
"time": "2019-12-30T08:14:25+00:00"
},
{
"name": "erusev/parsedown",
@ -2199,44 +2136,46 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
"version": "6.5.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0"
"psr/log": "^1.1"
},
"suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.3-dev"
"dev-master": "6.5-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@ -2260,7 +2199,7 @@
"rest",
"web service"
],
"time": "2018-04-22T15:46:56+00:00"
"time": "2019-12-23T11:57:10+00:00"
},
{
"name": "guzzlehttp/promises",
@ -3226,16 +3165,16 @@
},
{
"name": "league/flysystem",
"version": "1.0.61",
"version": "1.0.62",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
"reference": "4fb13c01784a6c9f165a351e996871488ca2d8c9"
"reference": "14dd5d7dff5fbc29ca9a2a53ff109760e40d91a0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4fb13c01784a6c9f165a351e996871488ca2d8c9",
"reference": "4fb13c01784a6c9f165a351e996871488ca2d8c9",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/14dd5d7dff5fbc29ca9a2a53ff109760e40d91a0",
"reference": "14dd5d7dff5fbc29ca9a2a53ff109760e40d91a0",
"shasum": ""
},
"require": {
@ -3306,7 +3245,7 @@
"sftp",
"storage"
],
"time": "2019-12-08T21:46:50+00:00"
"time": "2019-12-29T14:46:55+00:00"
},
{
"name": "league/fractal",
@ -4312,16 +4251,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "4.3.3",
"version": "4.3.4",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "2ecaa9fef01634c83bfa8dc1fe35fb5cef223a62"
"reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2ecaa9fef01634c83bfa8dc1fe35fb5cef223a62",
"reference": "2ecaa9fef01634c83bfa8dc1fe35fb5cef223a62",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c",
"reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c",
"shasum": ""
},
"require": {
@ -4333,6 +4272,7 @@
"require-dev": {
"doctrine/instantiator": "^1.0.5",
"mockery/mockery": "^1.0",
"phpdocumentor/type-resolver": "0.4.*",
"phpunit/phpunit": "^6.4"
},
"type": "library",
@ -4359,7 +4299,7 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2019-12-20T13:40:23+00:00"
"time": "2019-12-28T18:55:12+00:00"
},
{
"name": "phpdocumentor/type-resolver",
@ -7300,16 +7240,16 @@
},
{
"name": "filp/whoops",
"version": "2.6.0",
"version": "2.7.0",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "ecbc8f3ed2cafca3cfca3d5febaae5a9d2899508"
"reference": "4c97f814aa2f0dd4d5bedc89181c10ef12c004c5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/ecbc8f3ed2cafca3cfca3d5febaae5a9d2899508",
"reference": "ecbc8f3ed2cafca3cfca3d5febaae5a9d2899508",
"url": "https://api.github.com/repos/filp/whoops/zipball/4c97f814aa2f0dd4d5bedc89181c10ef12c004c5",
"reference": "4c97f814aa2f0dd4d5bedc89181c10ef12c004c5",
"shasum": ""
},
"require": {
@ -7328,7 +7268,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev"
"dev-master": "2.6-dev"
}
},
"autoload": {
@ -7357,7 +7297,7 @@
"throwable",
"whoops"
],
"time": "2019-12-25T10:00:00+00:00"
"time": "2019-12-29T10:00:00+00:00"
},
{
"name": "fzaninotto/faker",
@ -7459,23 +7399,22 @@
},
{
"name": "mockery/mockery",
"version": "1.3.0",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/mockery/mockery.git",
"reference": "5571962a4f733fbb57bede39778f71647fae8e66"
"reference": "f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mockery/mockery/zipball/5571962a4f733fbb57bede39778f71647fae8e66",
"reference": "5571962a4f733fbb57bede39778f71647fae8e66",
"url": "https://api.github.com/repos/mockery/mockery/zipball/f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be",
"reference": "f69bbde7d7a75d6b2862d9ca8fab1cd28014b4be",
"shasum": ""
},
"require": {
"hamcrest/hamcrest-php": "~2.0",
"lib-pcre": ">=7.0",
"php": ">=5.6.0",
"sebastian/comparator": "^1.2.4|^3.0"
"php": ">=5.6.0"
},
"require-dev": {
"phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0"
@ -7483,7 +7422,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
"dev-master": "1.3.x-dev"
}
},
"autoload": {
@ -7521,7 +7460,7 @@
"test double",
"testing"
],
"time": "2019-11-24T07:54:50+00:00"
"time": "2019-12-26T09:49:15+00:00"
},
{
"name": "myclabs/deep-copy",
@ -8054,16 +7993,16 @@
},
{
"name": "phpunit/phpunit",
"version": "8.5.0",
"version": "8.5.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "3ee1c1fd6fc264480c25b6fb8285edefe1702dab"
"reference": "7870c78da3c5e4883eaef36ae47853ebb3cb86f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3ee1c1fd6fc264480c25b6fb8285edefe1702dab",
"reference": "3ee1c1fd6fc264480c25b6fb8285edefe1702dab",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7870c78da3c5e4883eaef36ae47853ebb3cb86f2",
"reference": "7870c78da3c5e4883eaef36ae47853ebb3cb86f2",
"shasum": ""
},
"require": {
@ -8133,7 +8072,7 @@
"testing",
"xunit"
],
"time": "2019-12-06T05:41:38+00:00"
"time": "2019-12-25T14:49:39+00:00"
},
{
"name": "scrivo/highlight.php",

View File

@ -1,22 +0,0 @@
<?php
return [
//'default_namespace' => 'App\Widgets',
'use_jquery_for_ajax_calls' => false,
/*
* Set Ajax widget middleware
*/
'route_middleware' => ['web'],
/*
* Relative path from the base directory to a regular widget stub.
*/
'widget_stub' => 'vendor/arrilot/laravel-widgets/src/Console/stubs/widget.stub',
/*
* Relative path from the base directory to a plain widget stub.
*/
'widget_plain_stub' => 'vendor/arrilot/laravel-widgets/src/Console/stubs/widget_plain.stub',
];

View File

@ -25,12 +25,11 @@ class CreateDashboardsTable extends Migration
$table->index(['company_id']);
});
Schema::create('dashboard_widgets', function (Blueprint $table) {
Schema::create('widgets', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->integer('user_id');
$table->integer('dashboard_id');
$table->integer('widget_id');
$table->string('class');
$table->string('name');
$table->text('settings')->nullable();
$table->integer('sort')->default(0);
@ -39,19 +38,6 @@ class CreateDashboardsTable extends Migration
$table->index(['company_id']);
});
Schema::create('widgets', function (Blueprint $table) {
$table->increments('id');
$table->integer('company_id');
$table->string('name');
$table->string('alias');
$table->text('settings')->nullable();
$table->boolean('enabled')->default(1);
$table->timestamps();
$table->softDeletes();
$table->index(['company_id', 'alias']);
});
}
/**
@ -62,7 +48,6 @@ class CreateDashboardsTable extends Migration
public function down()
{
Schema::drop('dashboards');
Schema::drop('dashboard_widgets');
Schema::drop('widgets');
}
}

View File

@ -5,7 +5,7 @@ namespace Database\Seeds;
use App\Abstracts\Model;
use App\Models\Common\Widget;
use App\Models\Common\Dashboard;
use App\Models\Common\DashboardWidget;
use App\Utilities\Widgets as WidgetUtility;
use Illuminate\Database\Seeder;
class Dashboards extends Seeder
@ -29,35 +29,28 @@ class Dashboards extends Seeder
$user_id = $this->command->argument('user');
$company_id = $this->command->argument('company');
$rows = [
[
$dashboard = Dashboard::create([
'company_id' => $company_id,
'user_id' => $user_id,
'name' => trans('general.dashboard'),
'enabled' => 1,
]);
$widgets = WidgetUtility::getClasses();
$sort = 1;
foreach ($widgets as $class => $name) {
Widget::create([
'company_id' => $company_id,
'user_id' => $user_id,
'name' => trans('general.dashboard'),
'enabled' => 1,
]
];
'dashboard_id' => $dashboard->id,
'class' => $class,
'name' => $name,
'settings' => (new $class())->getDefaultSettings(),
'sort' => $sort,
]);
foreach ($rows as $row) {
$dashboard = Dashboard::create($row);
$widgets = Widget::where('company_id', $company_id)->orderBy('created_at','desc')->get();
$sort = 1;
foreach ($widgets as $widget) {
DashboardWidget::create([
'company_id' => $company_id,
'user_id' => $user_id,
'dashboard_id' => $dashboard->id,
'widget_id' => $widget->id,
'name' => $widget->name,
'settings' => $widget->settings,
'sort' => $sort
]);
$sort++;
}
$sort++;
}
}
}

View File

@ -11,7 +11,6 @@ class UserSeeder extends Seeder
*/
public function run()
{
$this->call(Database\Seeds\Widgets::class);
$this->call(Database\Seeds\Dashboards::class);
}
}

View File

@ -1,99 +0,0 @@
<?php
namespace Database\Seeds;
use App\Abstracts\Model;
use App\Models\Common\Widget;
use Illuminate\Database\Seeder;
class Widgets extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
$this->create();
Model::reguard();
}
private function create()
{
$company_id = $this->command->argument('company');
$rows = [
[
'company_id' => $company_id,
'name' => trans('dashboard.total_income'),
'alias' => 'total-income',
'settings' => ['width' => 'col-md-4'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.total_expenses'),
'alias' => 'total-expenses',
'settings' => ['width' => 'col-md-4'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.total_profit'),
'alias' => 'total-profit',
'settings' => ['width' => 'col-md-4'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.cash_flow'),
'alias' => 'cash-flow',
'settings' => ['width' => 'col-md-12'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.income_by_category'),
'alias' => 'income-by-category',
'settings' => ['width' => 'col-md-6'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.expenses_by_category'),
'alias' => 'expenses-by-category',
'settings' => ['width' => 'col-md-6'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.account_balance'),
'alias' => 'account-balance',
'settings' => ['width' => 'col-md-4'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.latest_income'),
'alias' => 'latest-income',
'settings' => ['width' => 'col-md-4'],
'enabled' => 1,
],
[
'company_id' => $company_id,
'name' => trans('dashboard.latest_expenses'),
'alias' => 'latest-expenses',
'settings' => ['width' => 'col-md-4'],
'enabled' => 1,
],
];
foreach ($rows as $row) {
Widget::create($row);
}
}
}

View File

@ -10,6 +10,6 @@
"files": [],
"requires": [],
"reports": [],
"settings": [],
"widgets": []
"widgets": [],
"settings": []
}

View File

@ -11,6 +11,7 @@
"files": [],
"requires": [],
"reports": [],
"widgets": [],
"settings": [
{
"type": "textGroup",
@ -77,6 +78,5 @@
"icon": "sort",
"attributes": {}
}
],
"widgets": []
]
}

View File

@ -174,8 +174,8 @@
@section('content')
<div class="row">
@foreach($widgets as $dashboard_widget)
@widget($dashboard_widget->widget->alias, $dashboard_widget->settings)
@foreach($widgets as $widget)
@widget($widget)
@endforeach
</div>
@endsection

View File

@ -1,10 +1,10 @@
<div id="widgets-account-balance" class="{{ $config->width }}">
<div id="widgets-account-balance" class="{{ $model->settings->width }}">
<div class="card">
<div class="card-header border-bottom-0">
<div class="row align-items-center">
<div class="col-6 text-nowrap">
<h4 class="mb-0">{{ trans('dashboard.account_balance') }}</h4>
<h4 class="mb-0">{{ $model->name }}</h4>
</div>
<div class="col-6 hidden-sm">
@ -19,10 +19,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>

View File

@ -1,9 +1,9 @@
<div id="widgets-cash-flow" class="{{ $config->width }}">
<div id="widgets-cash-flow" class="{{ $model->settings->width }}">
<div class="card">
<div class="card-header">
<div class="row align-items-center">
<div class="col-4 text-nowrap">
<h4 class="mb-0">{{ trans('dashboard.cash_flow') }}</h4>
<h4 class="mb-0">{{ $model->name }}</h4>
</div>
<div class="col-8 text-right hidden-sm">
@ -18,10 +18,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>

View File

@ -1,10 +1,10 @@
<div id="widgets-expenses-by-category" class="{{ $config->width }}">
<div id="widgets-expenses-by-category" class="{{ $model->settings->width }}">
<div class="card">
<div class="card-header">
<div class="row align-items-center">
<div class="col-6 text-nowrap">
<h4 class="mb-0">{{ trans('dashboard.expenses_by_category') }}</h4>
<h4 class="mb-0">{{ $model->name }}</h4>
</div>
<div class="col-6 hidden-sm">
@ -19,10 +19,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>

View File

@ -1,10 +1,10 @@
<div id="widgets-incomes-by-category" class="{{ $config->width }}">
<div id="widgets-incomes-by-category" class="{{ $model->settings->width }}">
<div class="card">
<div class="card-header">
<div class="row align-items-center">
<div class="col-6 text-nowrap">
<h4 class="mb-0">{{ trans('dashboard.income_by_category') }}</h4>
<h4 class="mb-0">{{ $model->name }}</h4>
</div>
<div class="col-6 hidden-sm">
@ -19,10 +19,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>

View File

@ -1,9 +1,9 @@
<div id="widgets-latest-expenses" class="{{ $config->width }}">
<div id="widgets-latest-expenses" class="{{ $model->settings->width }}">
<div class="card">
<div class="card-header border-bottom-0">
<div class="row align-items-center">
<div class="col-6 text-nowrap">
<h4 class="mb-0">{{ trans('dashboard.latest_expenses') }}</h4>
<h4 class="mb-0">{{ $model->name }}</h4>
</div>
<div class="col-6 hidden-sm">
@ -18,10 +18,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>

View File

@ -1,9 +1,9 @@
<div id="widgets-latest-incomes" class="{{ $config->width }}">
<div id="widgets-latest-incomes" class="{{ $model->settings->width }}">
<div class="card">
<div class="card-header border-bottom-0">
<div class="row align-items-center">
<div class="col-6 text-nowrap">
<h4 class="mb-0">{{ trans('dashboard.latest_income') }}</h4>
<h4 class="mb-0">{{ $model->name }}</h4>
</div>
<div class="col-6 hidden-sm">
@ -18,10 +18,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>

View File

@ -1,4 +1,4 @@
<div id="widgets-total-expenses" class="{{ $config->width }}">
<div id="widgets-total-expenses" class="{{ $model->settings->width }}">
<div class="card bg-gradient-danger card-stats">
<span>
<div class="dropdown card-action-button">
@ -11,10 +11,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>
@ -22,7 +22,7 @@
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-uppercase text-white mb-0">{{ trans('dashboard.total_expenses') }}</h5>
<h5 class="text-uppercase text-white mb-0">{{ $model->name }}</h5>
<span class="font-weight-bold text-white mb-0">@money($totals['current'], setting('default.currency'), true)</span>
</div>

View File

@ -1,4 +1,4 @@
<div id="widgets-total-incomes" class="{{ $config->width }}">
<div id="widgets-total-incomes" class="{{ $model->settings->width }}">
<div class="card bg-gradient-info card-stats">
<span>
<div class="dropdown card-action-button">
@ -11,10 +11,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>
@ -22,7 +22,7 @@
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-uppercase text-white mb-0">{{ trans('dashboard.total_income') }}</h5>
<h5 class="text-uppercase text-white mb-0">{{ $model->name }}</h5>
<span class="font-weight-bold text-white mb-0">@money($totals['current'], setting('default.currency'), true)</span>
</div>

View File

@ -1,4 +1,4 @@
<div id="widgets-total-profit" class="{{ $config->width }}">
<div id="widgets-total-profit" class="{{ $model->settings->width }}">
<div class="card bg-gradient-success card-stats">
<span>
<div class="dropdown card-action-button">
@ -11,10 +11,10 @@
'type' => 'button',
'class' => 'dropdown-item',
'title' => trans('general.edit'),
'@click' => 'onEditWidget(' . $config->widget->id . ')'
'@click' => 'onEditWidget(' . $model->id . ')'
)) !!}
<div class="dropdown-divider"></div>
{!! Form::deleteLink($config->widget, 'common/widgets') !!}
{!! Form::deleteLink($model, 'common/widgets') !!}
</div>
</div>
</span>
@ -22,7 +22,7 @@
<div class="card-body">
<div class="row">
<div class="col">
<h5 class="text-uppercase text-white mb-0">{{ trans('dashboard.total_profit') }}</h5>
<h5 class="text-uppercase text-white mb-0">{{ $model->name }}</h5>
<span class="font-weight-bold text-white mb-0">@money($totals['current'], setting('default.currency'), true)</span>
</div>

View File

@ -10,9 +10,7 @@ Route::group(['prefix' => 'common'], function () {
Route::get('companies/{company}/disable', 'Common\Companies@disable')->name('companies.disable');
Route::resource('companies', 'Common\Companies');
Route::get('dashboard/cashflow', 'Common\Dashboard@cashFlow')->name('dashboards.cashflow');
Route::resource('dashboards', 'Common\Dashboard');
Route::post('widgets/getData', 'Common\Widgets@getData')->name('widgets.getData');
Route::resource('widgets', 'Common\Widgets');