Add admin dashboard setup wizard for first-time system configuration#7698
Add admin dashboard setup wizard for first-time system configuration#7698
Conversation
- Create admin dashboard at /admin route with Slim4 MVC pattern - Add 7-step quick start setup checklist with direct links to key config pages - Display system health indicators (file integrity, orphaned files) - Show system info (version, database, admin tools) - Implement demo data import with Sunday School selected by default - Add 'Admin Dashboard' menu entry as first item in Admin menu - Redirect fresh installs to /admin dashboard instead of /v2/dashboard - Remove import demo data from system maintenance page - Follow project standards: use Propel ORM, Slim4 routing, Bootstrap 4.6.2, gettext() localization
There was a problem hiding this comment.
Pull request overview
This PR introduces a new admin dashboard at /admin designed to guide administrators through first-time system setup. The dashboard provides a 7-step setup wizard, system health monitoring, and a demo data import feature. Fresh installations (with only 1 person record) are automatically redirected from /v2/dashboard to this new admin dashboard.
Key Changes:
- New admin dashboard with quick-start checklist linking to essential configuration pages
- System health indicators showing file integrity and orphaned files status
- Demo data import feature moved from system maintenance to admin dashboard
- Automatic redirect for fresh installations to streamline onboarding
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
webpack/admin-dashboard.js |
JavaScript for tooltip initialization and smooth scrolling behavior on the admin dashboard |
webpack/admin-dashboard.css |
Custom styling for dashboard cards, badges, and interactive elements |
webpack.config.js |
Adds admin-dashboard entry point to webpack configuration |
src/v2/templates/root/dashboard.php |
Removes demo data import banner from main dashboard (moved to admin dashboard) |
src/v2/routes/root.php |
Adds redirect logic for admin users with no people to new admin dashboard |
src/skin/js/importDemoData.js |
Updates demo data options: disables financial/events, enables Sunday School by default |
src/admin/views/system-maintenance.php |
Removes import demo data button (functionality moved to admin dashboard) |
src/admin/views/dashboard.php |
New admin dashboard template with setup wizard, health monitoring, and system info |
src/admin/routes/dashboard.php |
Slim4 route handler for /admin root path |
src/admin/index.php |
Registers new dashboard route in admin router |
src/ChurchCRM/Config/Menu/Menu.php |
Adds "Admin Dashboard" menu item as first entry in Admin menu |
src/admin/views/dashboard.php
Outdated
| </div> | ||
| <div class="card-body"> | ||
| <p><?= gettext('Import sample families, people, groups and optional events/financial records so you can explore ChurchCRM populated with realistic data.') ?></p> | ||
| <button type="button" id="importDemoDataV2" class="btn btn-success btn-lg w-100"> |
There was a problem hiding this comment.
The w-100 class is a Bootstrap 5 utility class. According to the coding guidelines, this project uses Bootstrap 4.6.2 and must not use Bootstrap 5 classes. Replace w-100 with btn-block for full-width buttons in Bootstrap 4.6.2.
For example, line 133 should be:
<button type="button" id="importDemoDataV2" class="btn btn-success btn-lg btn-block">Apply the same change to lines 162, 174, and 209.
src/admin/views/dashboard.php
Outdated
| <?php endif; ?> | ||
|
|
||
| <hr class="my-3"> | ||
| <a href="<?= SystemURLs::getRootPath() ?>/admin/system/debug" class="btn btn-sm btn-outline-secondary w-100"> |
There was a problem hiding this comment.
The w-100 class is a Bootstrap 5 utility class. Replace with btn-block for full-width buttons in Bootstrap 4.6.2.
src/admin/views/dashboard.php
Outdated
| </div> | ||
| </li> | ||
| <li class="mt-3"> | ||
| <a href="https://github.com/ChurchCRM/CRM/wiki" target="_blank" rel="noopener noreferrer" class="btn btn-sm btn-outline-info w-100"> |
There was a problem hiding this comment.
The w-100 class is a Bootstrap 5 utility class. Replace with btn-block for full-width buttons in Bootstrap 4.6.2.
src/admin/views/dashboard.php
Outdated
| </li> | ||
| <li class="mb-3"> | ||
| <strong><?= gettext('Admin Tools:') ?></strong><br> | ||
| <div class="btn-group w-100 mt-2" role="group"> |
There was a problem hiding this comment.
The w-100 class is a Bootstrap 5 utility class. For btn-group, consider using Bootstrap 4.6.2's d-flex class instead to achieve full width, or restructure without w-100.
webpack/admin-dashboard.js
Outdated
| document.addEventListener('DOMContentLoaded', function () { | ||
| // Initialize tooltips if Bootstrap is available | ||
| if (typeof bootstrap !== 'undefined') { | ||
| const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); |
There was a problem hiding this comment.
Bootstrap 5 uses data-bs-toggle for tooltips, but Bootstrap 4.6.2 uses data-toggle. This code checks for [data-bs-toggle="tooltip"] which is the Bootstrap 5 syntax. Change to [data-toggle="tooltip"] to match Bootstrap 4.6.2. Additionally, verify that the tooltip API is compatible with Bootstrap 4.6.2 (should be new bootstrap.Tooltip() or jQuery's $().tooltip()).
| .list-group-item .badge { | ||
| min-width: 2.5rem; | ||
| height: 2.5rem; | ||
| display: flex; |
There was a problem hiding this comment.
[nitpick] The CSS property display: flex on .badge (line 33) may not render correctly for badges in Bootstrap 4.6.2. Badges are inline elements by default. If flex layout is needed for the badge content, consider using display: inline-flex instead to maintain inline flow while enabling flexbox for children.
| display: flex; | |
| display: inline-flex; |
webpack/admin-dashboard.css
Outdated
|
|
||
| .card:hover { | ||
| transform: translateY(-2px); | ||
| box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; |
There was a problem hiding this comment.
[nitpick] The !important flag on box-shadow should generally be avoided unless absolutely necessary to override other styles. Consider removing it and ensuring proper CSS specificity instead. If this is needed to override Bootstrap's default card hover styles, add a comment explaining why.
| box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; | |
| box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); |
src/admin/views/dashboard.php
Outdated
| <p class="mb-2"><strong><?= gettext('Orphaned Files:') ?></strong></p> | ||
| <span class="badge bg-danger"><?= count($orphanedFiles) ?> <?= gettext('files') ?></span> | ||
| <p class="text-muted small mt-2"><?= gettext('Orphaned files may pose security risks.') ?></p> | ||
| <a href="<?= SystemURLs::getRootPath() ?>/admin/system/orphaned-files" class="btn btn-sm btn-outline-danger w-100 mt-2"> |
There was a problem hiding this comment.
The w-100 class is a Bootstrap 5 utility class. Replace with appropriate Bootstrap 4.6.2 approach. For buttons, use btn-block. For btn-group, you can use d-flex instead of w-100 if you want it to stretch to full width.
src/v2/routes/root.php
Outdated
| ->count(); | ||
|
|
||
| // Redirect admin users with no people to the setup dashboard | ||
| if (AuthenticationManager::getCurrentUser()->isAdmin() && $dashboardCounts['People'] == 1) { |
There was a problem hiding this comment.
Use strict equality comparison (===) instead of loose equality (==) for type-safe comparison. This ensures the comparison checks both value and type, preventing unexpected behavior when $dashboardCounts['People'] is a string "1" vs integer 1.
| if (AuthenticationManager::getCurrentUser()->isAdmin() && $dashboardCounts['People'] == 1) { | |
| if (AuthenticationManager::getCurrentUser()->isAdmin() && $dashboardCounts['People'] === 1) { |
src/admin/views/dashboard.php
Outdated
|
|
||
| // Get system status info | ||
| $integrityStatus = AppIntegrityService::getIntegrityCheckStatus(); | ||
| $integrityPassed = $integrityStatus === gettext('Passed'); |
There was a problem hiding this comment.
Comparing $integrityStatus directly to gettext('Passed') is fragile because it relies on the translated string value. If the language changes or the translation is modified, this comparison will fail. Consider having AppIntegrityService::getIntegrityCheckStatus() return a boolean or constant value instead of a translated string, or compare against the English constant before translation.
| $integrityPassed = $integrityStatus === gettext('Passed'); | |
| $integrityPassed = $integrityStatus === 'Passed'; |
- Move Restore Database and Reset Database cards from maintenance page to dashboard - Add Advanced Operations section below main dashboard content - Update menu: System Maintenance now points to admin dashboard - Remove /admin/system/maintenance route and view file - Update redirect links in orphaned-files and system-reset to go to dashboard - All system admin tools now accessible from single dashboard page
- Replace numbered list with responsive 6-card grid layout - Reorder cards: Settings, Users, Groups, Sunday School, Import, Funds - Add Force Import functionality when initial import fails - Display inline error messages with clear formatting - Fix force parameter name to match API (force vs forceImport) - Update references from System Maintenance to Admin Dashboard - Compact CSS styling for better visual hierarchy
- Test dashboard page loads and displays key sections - Verify all 6 Quick Start cards are present - Verify System Info, System Health, Demo Data cards - Test Import Demo Data overlay opens and cancels correctly - Test navigation from Quick Start cards to target pages
- Replace Bootstrap 5 w-100 utility with Bootstrap 4.6.2 btn-block for full-width buttons
- Use d-flex flex-fill for btn-group layout instead of w-100
- Fix Bootstrap tooltip syntax from data-bs-toggle (v5) to data-toggle (v4.6.2)
- Use jQuery $().tooltip() instead of bootstrap.Tooltip() for Bootstrap 4.6.2
- Use strict equality === instead of == for type-safe comparison
- Compare integrity status to 'Passed' instead of gettext('Passed') to avoid i18n issues
What Changed
Type
Screenshots
Security Check
Code Quality
Pre-Merge