├── .gitignore
├── LICENSE.md
├── composer.json
├── dist
├── css
│ └── card.css
├── js
│ └── card.js
└── mix-manifest.json
├── img
├── after.gif
├── custom-trend.png
└── metrics-before.gif
├── package.json
├── readme.md
├── resources
├── js
│ ├── card.js
│ └── components
│ │ ├── CustomPartitionMetric.vue
│ │ ├── CustomTrendMetric.vue
│ │ └── CustomValueMetric.vue
└── sass
│ └── card.scss
├── routes
└── api.php
├── src
├── CardServiceProvider.php
├── CustomPartition.php
├── CustomTrend.php
└── CustomValue.php
└── webpack.mix.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /vendor
3 | /node_modules
4 | package-lock.json
5 | composer.phar
6 | composer.lock
7 | phpunit.xml
8 | .phpunit.result.cache
9 | .DS_Store
10 | Thumbs.db
11 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Square1 LTD hello@square1.io
4 |
5 | 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:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | 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.
10 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "square1/nova-metrics",
3 | "description": "Add support for resource-filters on your laravel nova metrics",
4 | "keywords": [
5 | "laravel",
6 | "nova",
7 | "metrics",
8 | "filters"
9 | ],
10 | "license": "MIT",
11 | "require": {
12 | "php": ">=7.1.0"
13 | },
14 | "autoload": {
15 | "psr-4": {
16 | "Square1\\NovaMetrics\\": "src/"
17 | }
18 | },
19 | "extra": {
20 | "laravel": {
21 | "providers": [
22 | "Square1\\NovaMetrics\\CardServiceProvider"
23 | ]
24 | }
25 | },
26 | "config": {
27 | "sort-packages": true
28 | },
29 | "minimum-stability": "dev",
30 | "prefer-stable": true
31 | }
32 |
--------------------------------------------------------------------------------
/dist/css/card.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/square1-io/nova-metrics/f006fe8f79db058fb49ee57fc79f2e8346933b36/dist/css/card.css
--------------------------------------------------------------------------------
/dist/mix-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "/js/card.js": "/js/card.js",
3 | "/css/card.css": "/css/card.css"
4 | }
--------------------------------------------------------------------------------
/img/after.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/square1-io/nova-metrics/f006fe8f79db058fb49ee57fc79f2e8346933b36/img/after.gif
--------------------------------------------------------------------------------
/img/custom-trend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/square1-io/nova-metrics/f006fe8f79db058fb49ee57fc79f2e8346933b36/img/custom-trend.png
--------------------------------------------------------------------------------
/img/metrics-before.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/square1-io/nova-metrics/f006fe8f79db058fb49ee57fc79f2e8346933b36/img/metrics-before.gif
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "dev": "npm run development",
5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
7 | "watch-poll": "npm run watch -- --watch-poll",
8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
9 | "prod": "npm run production",
10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
11 | },
12 | "devDependencies": {
13 | "cross-env": "^5.0.0",
14 | "laravel-mix": "^1.0"
15 | },
16 | "dependencies": {
17 | "vue": "^2.5.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Custom Nova Metrics Components
2 |
3 | This package will allow you to access your resource-filters on any Laravel Nova Metric class, and will update these cards dynamically every time you select a new filter on your resources-list.
4 |
5 | ---
6 |
7 | Charts are a great way to display graphic information on your dashboard, and with Laravel Nova you can create beautiful **Metrics Cards** really fast.
8 |
9 | You can use these charts on your resource views as well.
10 |
11 | 
12 |
13 | Usually when you add those metrics to any resource, you'd expect the chart to be a representation of the data you are seeing in the list down below. Currently on Nova this is not possible - when you change a filter selection, the resources-list is updated, but the corresponding charts are not.
14 |
15 | 
16 |
17 | This happens because the requests to populate the list are independent from the request used to get the metrics-data. This means that updating the filters breaks the connection with the charts, leaving them outdated.
18 |
19 | This package restores that connection, ensuring that the charts and data on-screen remain in sync.
20 |
21 | 
22 |
23 | ## Install
24 |
25 | Install via composer
26 |
27 | ```bash
28 | composer require square1/nova-metrics
29 | ```
30 |
31 | ## Usage
32 |
33 | You can create new metrics using the default nova commands:
34 |
35 | ```bash
36 | php artisan nova:partition NewPartition
37 | php artisan nova:trend NewTrend
38 | php artisan nova:value NewValue
39 | ```
40 |
41 | Then you only need to update your recently created metric class. Extend from one of the following classes to have access to your resource filters:
42 |
43 | ```php
44 | use Square1\NovaMetrics\CustomTrend;
45 | use Square1\NovaMetrics\CustomValue;
46 | use Square1\NovaMetrics\CustomPartition;
47 | ```
48 |
49 | For example:
50 |
51 | ```php
52 | filters
65 | }
66 | }
67 | ```
68 |
69 | Let's say you have a `CategoryFilter::class` :
70 |
71 | ```php
72 | where('category', $value);
88 | }
89 |
90 | public function options(Request $request)
91 | {
92 | return [
93 | 'css' => 'css',
94 | 'javascript' => 'javascript',
95 | 'laravel' =>'laravel',
96 | 'php' => 'php',
97 | ];
98 | }
99 | }
100 | ```
101 |
102 | This is how you can apply this filter to your `NewTrend::class` :
103 |
104 | ```php
105 | class NewTrend extends CustomTrend
106 | {
107 | public function calculate(NovaRequest $request)
108 | {
109 | $model = Post::make();
110 |
111 | if (!empty($filters)) {
112 | if ($request->has('filters')) {
113 | // Get the decoded list of filters
114 | $filters = json_decode(base64_decode($request->filters));
115 |
116 | foreach ($filters as $filter) {
117 | if (empty($filter->value)) {
118 | continue;
119 | }
120 | // Create a new instance of the filter and apply the query to your model
121 | $model = (new $filter->class)->apply($request, $model, $filter->value);
122 | }
123 | }
124 | }
125 |
126 | return $this->averageByDays($request, $model, 'pageviews');
127 | }
128 | }
129 | ```
130 |
131 | ---
132 |
133 | ## Known Issues
134 |
135 | If you'd like to contribute on this package, this is a good place to start 🙂
136 |
137 | - Wait until the first `resources-loaded` event is fired to load the cards.
138 | - Decode the `$request->filters` in the request object.
139 |
140 | ## Credits
141 |
142 | - [Jeff Ochoa](https://github.com/jeffochoa)
143 | - [All Contributors](../../contributors)
144 |
145 | ## License
146 |
147 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
148 |
--------------------------------------------------------------------------------
/resources/js/card.js:
--------------------------------------------------------------------------------
1 | Nova.booting((Vue, router, store) => {
2 | Vue.component('CustomTrendMetric', require('./components/CustomTrendMetric'))
3 | Vue.component('CustomValueMetric', require('./components/CustomValueMetric'))
4 | Vue.component('CustomPartitionMetric', require('./components/CustomPartitionMetric'))
5 | })
6 |
--------------------------------------------------------------------------------
/resources/js/components/CustomPartitionMetric.vue:
--------------------------------------------------------------------------------
1 |
44 |
--------------------------------------------------------------------------------
/resources/js/components/CustomTrendMetric.vue:
--------------------------------------------------------------------------------
1 |
44 |
--------------------------------------------------------------------------------
/resources/js/components/CustomValueMetric.vue:
--------------------------------------------------------------------------------
1 |
41 |
--------------------------------------------------------------------------------
/resources/sass/card.scss:
--------------------------------------------------------------------------------
1 | // Nova Card CSS
2 |
--------------------------------------------------------------------------------
/routes/api.php:
--------------------------------------------------------------------------------
1 | app->booted(function () {
20 | $this->routes();
21 | });
22 |
23 | Nova::serving(function (ServingNova $event) {
24 | Nova::script('CustomTrend', __DIR__.'/../dist/js/card.js');
25 | Nova::style('CustomTrend', __DIR__.'/../dist/css/card.css');
26 |
27 | Nova::script('CustomValue', __DIR__.'/../dist/js/card.js');
28 | Nova::style('CustomValue', __DIR__.'/../dist/css/card.css');
29 |
30 | Nova::script('CustomPartition', __DIR__.'/../dist/js/card.js');
31 | Nova::style('CustomPartition', __DIR__.'/../dist/css/card.css');
32 | });
33 | }
34 |
35 | /**
36 | * Register the card's routes.
37 | *
38 | * @return void
39 | */
40 | protected function routes()
41 | {
42 | if ($this->app->routesAreCached()) {
43 | return;
44 | }
45 |
46 | Route::middleware(['nova'])
47 | ->prefix('nova-vendor/CustomTrend')
48 | ->group(__DIR__.'/../routes/api.php');
49 |
50 | Route::middleware(['nova'])
51 | ->prefix('nova-vendor/CustomValue')
52 | ->group(__DIR__.'/../routes/api.php');
53 |
54 | Route::middleware(['nova'])
55 | ->prefix('nova-vendor/CustomPartition')
56 | ->group(__DIR__.'/../routes/api.php');
57 | }
58 |
59 | /**
60 | * Register any application services.
61 | *
62 | * @return void
63 | */
64 | public function register()
65 | {
66 | //
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/CustomPartition.php:
--------------------------------------------------------------------------------
1 |