Skip to content

Commit e03fab0

Browse files
author
nejc
committed
feat: Add dynamic admin sidebar config and real analytics data
- Add configurable navbar_links array in config - Support both 'route' and 'url' for sidebar links - Add 'target' attribute support (e.g., _blank) - Replace demo analytics data with real database queries - Add AnalyticsService with repository pattern - Update README with sidebar configuration docs - Add strict types and return types throughout - Implement repository pattern for all models - Add standalone /whats-new page - Update middleware to redirect to standalone page
1 parent f21c761 commit e03fab0

29 files changed

+979
-381
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,40 @@ The package configuration file `config/version-platform-manager.php` contains:
9292
- Version comparison logic
9393
- Admin panel settings
9494

95+
## Admin Sidebar (Dynamic Navbar)
96+
97+
The admin sidebar is fully configurable via the `navbar_links` array in `config/version-platform-manager.php`.
98+
99+
You can add, remove, or reorder links. Each link supports:
100+
- `label`: The text to display
101+
- `route`: (optional) The Laravel route name to use
102+
- `url`: (optional) A direct URL (internal or external)
103+
- `icon`: (optional) SVG icon markup
104+
- `target`: (optional) e.g. `_blank` to open in a new tab
105+
106+
**Example:**
107+
108+
```php
109+
'navbar_links' => [
110+
[
111+
'label' => 'Dashboard',
112+
'route' => 'version-manager.dashboard',
113+
'icon' => '<svg ...></svg>',
114+
],
115+
[
116+
'label' => 'Logs',
117+
'url' => '/admin/logs',
118+
'icon' => '<svg ...></svg>',
119+
'target' => '_blank', // open in new tab
120+
],
121+
// Add more links as needed
122+
],
123+
```
124+
125+
- If both `route` and `url` are present, `route` is used.
126+
- The sidebar will highlight the active link for both route and URL types.
127+
- You can use any SVG icon markup for the `icon` field.
128+
95129
## Database Structure
96130

97131
### Platform Versions Table

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
}
1111
],
1212
"require": {
13-
"php": "^8.1",
14-
"laravel/framework": "^10.0|^11.0|^12.0"
13+
"php": "^8.4",
14+
"laravel/framework": "^12.0"
1515
},
1616
"require-dev": {
1717
"orchestra/testbench": "^8.0|^9.0|^10.0",
1818
"phpunit/phpunit": "^10.0",
19-
"pestphp/pest": "^2.0"
19+
"pestphp/pest": "^2.0",
20+
"laravel/pint": "^1.0"
2021
},
2122
"autoload": {
2223
"psr-4": {

config/version-platform-manager.php

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,53 @@
5151
'middleware' => ['web', 'auth'],
5252
],
5353

54+
/*
55+
|--------------------------------------------------------------------------
56+
| Admin Navbar Links
57+
|--------------------------------------------------------------------------
58+
|
59+
| Configure the links shown in the admin sidebar. You can add, remove, or
60+
| reorder links here. Each link should have a label, route (route name),
61+
| and SVG icon path (optional, for sidebar display).
62+
|
63+
*/
64+
'navbar_links' => [
65+
[
66+
'label' => 'Dashboard',
67+
'route' => 'version-manager.dashboard',
68+
'icon' => '<svg class="w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z" /><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5a2 2 0 012-2h4a2 2 0 012 2v6H8V5z" /></svg>'
69+
],
70+
[
71+
'label' => 'Versions',
72+
'route' => 'version-manager.versions.index',
73+
'icon' => '<svg class="w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l3 3m0 0l3-3m-3 3V10" /></svg>'
74+
],
75+
[
76+
'label' => 'Users',
77+
'route' => 'version-manager.users.index',
78+
'icon' => '<svg class="w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5-9a2.5 2.5 0 11-5 0 2.5 2.5 0 015 0z" /></svg>'
79+
],
80+
[
81+
'label' => 'Analytics',
82+
'route' => 'version-manager.analytics.index',
83+
'icon' => '<svg class="w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" /></svg>'
84+
],
85+
[
86+
'label' => 'Logs',
87+
// You can use either 'route' or 'url' for custom links:
88+
// 'route' => 'admin.logs',
89+
'url' => '/admin/logs',
90+
'icon' => '<svg class="w-5 h-5 mr-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 9V7a5 5 0 0110 0v2m-1 4h-8" /></svg>',
91+
'target' => '_blank', // Optional: open in new tab
92+
],
93+
// Example custom link:
94+
// [
95+
// 'label' => 'Logs',
96+
// 'route' => 'admin.logs',
97+
// 'icon' => '<svg ...></svg>'
98+
// ],
99+
],
100+
54101
/*
55102
|--------------------------------------------------------------------------
56103
| Database Tables
@@ -94,14 +141,25 @@
94141
'channels' => ['mail', 'database'],
95142
],
96143

144+
'whats_new_signature' => env('VERSION_WHATS_NEW_SIGNATURE', 'Best regards, <br>Your Company Name'),
145+
'whats_new_exclude' => [
146+
'admin*',
147+
'api*',
148+
'login',
149+
'register',
150+
'password/*',
151+
],
152+
97153
/*
98154
|--------------------------------------------------------------------------
99-
| Whats New Style
155+
| Public What's New Page
100156
|--------------------------------------------------------------------------
101157
|
102-
| The style for the whats new modal. Options: 'tailwind', 'bootstrap'
158+
| Configuration for the standalone public 'What's New' page.
103159
|
104160
*/
105-
'whats_new_style' => env('VERSION_WHATS_NEW_STYLE', 'tailwind'), // or 'bootstrap'
106-
'whats_new_signature' => env('VERSION_WHATS_NEW_SIGNATURE', 'Best regards, <br>Your Company Name'),
161+
'public_whats_new' => [
162+
'url' => env('VERSION_PUBLIC_WHATS_NEW_URL', 'whats-new'),
163+
'view' => env('VERSION_PUBLIC_WHATS_NEW_VIEW', 'version-platform-manager::whats-new.page'),
164+
],
107165
];

phpstan.neon

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
includes:
2+
- vendor/nunomaduro/larastan/extension.neon
3+
4+
parameters:
5+
level: 4
6+
7+
paths:
8+
- app
9+
- bootstrap
10+
- config
11+
- routes
12+
- database
13+
- tests
14+
15+
excludePaths:
16+
- storage/*
17+
- vendor/*
18+
- node_modules/*
19+
- public/*
20+
- resources/js/*
21+
- resources/vue/*
22+
- resources/sass/*
23+
- bootstrap/cache/*
24+
- database/migrations/*.php
25+
- app/helpers.php
26+
27+
inferPrivatePropertyTypeFromConstructor: true
28+
treatPhpDocTypesAsCertain: true
29+
reportUnmatchedIgnoredErrors: false
30+
checkMissingTypehints: true
31+
checkUninitializedProperties: true
32+
checkExplicitMixed: true
33+
34+
bootstrapFiles:
35+
- bootstrap/app.php
36+
37+
scanFiles:
38+
- app/Providers/AppServiceProvider.php
39+
40+
ignoreErrors:
41+
- '#Call to an undefined method Illuminate\\[a-zA-Z\\]+#'
42+
- '#^Access to an undefined property App\\Models\\.*::$#'
43+
- '#Property App\\Models\\.* has unknown class#'

pint.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"preset": "laravel",
3+
"exclude": [
4+
"packages",
5+
"deprecated",
6+
"Plugins/PDFGenerator"
7+
],
8+
"notName": [
9+
"*.js",
10+
"*.html"
11+
],
12+
"notPath": [
13+
],
14+
"rules": {
15+
"align_multiline_comment": true,
16+
"array_indentation": true,
17+
"array_syntax": true,
18+
"binary_operator_spaces": false,
19+
"statement_indentation": true,
20+
"curly_braces_position": false,
21+
"braces": false,
22+
"blank_line_after_namespace": true,
23+
"blank_line_after_opening_tag": true,
24+
"combine_consecutive_issets": true,
25+
"combine_consecutive_unsets": true,
26+
"concat_space": false,
27+
"declare_parentheses": true,
28+
"declare_strict_types": true,
29+
"explicit_string_variable": true,
30+
"final_class": true,
31+
"final_internal_class": false,
32+
"fully_qualified_strict_types": true,
33+
"global_namespace_import": {
34+
"import_classes": true,
35+
"import_constants": true,
36+
"import_functions": true
37+
},
38+
"is_null": true,
39+
"lambda_not_used_import": true,
40+
"logical_operators": true,
41+
"mb_str_functions": true,
42+
"method_chaining_indentation": true,
43+
"modernize_strpos": true,
44+
"new_with_braces": true,
45+
"no_empty_comment": true,
46+
"not_operator_with_space": false,
47+
"not_operator_with_successor_space": false,
48+
"ordered_traits": true,
49+
"protected_to_private": true,
50+
"simplified_if_return": true,
51+
"strict_comparison": true,
52+
"ternary_to_null_coalescing": true,
53+
"trim_array_spaces": true,
54+
"use_arrow_functions": true,
55+
"void_return": true,
56+
"yoda_style": false
57+
}
58+
}

0 commit comments

Comments
 (0)