Home: - Empty state: 2-column with 'How it works' 5-step guide - Has data: 7/5 grid — pledges left, education right - Right column: status breakdown, sources, 'What to do next' contextual links, 'What the statuses mean' guide Money: - 8/4 two-column layout: table left, education right - Right column: 'How matching works' 4-step guide, status explainer, collection tips, quick action buttons - No more wasted right margin Reports: - 7/5 two-column layout: downloads left, education right - Right column: 'For your treasurer' 3-step guide, Gift Aid FAQ, 'Understanding your numbers' explainer - Activity log moved to right column Settings: - Removed max-w-2xl constraint, now uses full width - 7/5 two-column: checklist left, education right - Right column: 'What you're setting up' (5 items with Required badges), Privacy & data assurance, Common questions FAQ, 'Need help?' CTA - Every setting explained in human language
185 lines
6.4 KiB
Python
185 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Navigation overhaul:
|
|
- Daily: Donors, Donations (with recurring tab)
|
|
- Seasonal Campaigns: Campaign Dashboard, Subscribers, Giving Campaigns config
|
|
- Fundraising: Review Queue, All Fundraisers
|
|
- Setup: unchanged
|
|
"""
|
|
import os
|
|
|
|
BASE = '/home/forge/app.charityright.org.uk'
|
|
|
|
# ── 1. ScheduledGivingDonationResource → Seasonal Campaigns group ──
|
|
|
|
path = os.path.join(BASE, 'app/Filament/Resources/ScheduledGivingDonationResource.php')
|
|
with open(path, 'r') as f:
|
|
c = f.read()
|
|
|
|
# Change nav group
|
|
c = c.replace(
|
|
"protected static ?string $navigationGroup = 'Daily';",
|
|
"protected static ?string $navigationGroup = 'Seasonal Campaigns';"
|
|
)
|
|
# Change label
|
|
c = c.replace(
|
|
"protected static ?string $navigationLabel = 'Regular Giving';",
|
|
"protected static ?string $navigationLabel = 'Subscribers';"
|
|
)
|
|
# Change sort
|
|
c = c.replace(
|
|
"protected static ?int $navigationSort = 3;",
|
|
"protected static ?int $navigationSort = 1;"
|
|
)
|
|
# Change model label
|
|
c = c.replace(
|
|
"protected static ?string $modelLabel = 'Regular Giving';",
|
|
"protected static ?string $modelLabel = 'Scheduled Giving';"
|
|
)
|
|
c = c.replace(
|
|
"protected static ?string $pluralModelLabel = 'Regular Giving';",
|
|
"protected static ?string $pluralModelLabel = 'Scheduled Giving';"
|
|
)
|
|
# Change icon to calendar
|
|
c = c.replace(
|
|
"protected static ?string $navigationIcon = 'heroicon-o-arrow-path';",
|
|
"protected static ?string $navigationIcon = 'heroicon-o-user-group';"
|
|
)
|
|
|
|
with open(path, 'w') as f:
|
|
f.write(c)
|
|
print('Updated ScheduledGivingDonationResource nav')
|
|
|
|
# ── 2. ScheduledGivingCampaignResource → Seasonal Campaigns group ──
|
|
|
|
path = os.path.join(BASE, 'app/Filament/Resources/ScheduledGivingCampaignResource.php')
|
|
with open(path, 'r') as f:
|
|
c = f.read()
|
|
|
|
c = c.replace(
|
|
"protected static ?string $navigationGroup = 'Fundraising';",
|
|
"protected static ?string $navigationGroup = 'Seasonal Campaigns';"
|
|
)
|
|
c = c.replace(
|
|
"protected static ?string $navigationLabel = 'Giving Campaigns';",
|
|
"protected static ?string $navigationLabel = 'Campaign Config';"
|
|
)
|
|
|
|
# Add sort if missing
|
|
if 'navigationSort' not in c:
|
|
c = c.replace(
|
|
"protected static ?string $navigationLabel = 'Campaign Config';",
|
|
"protected static ?string $navigationLabel = 'Campaign Config';\n\n protected static ?int $navigationSort = 2;"
|
|
)
|
|
|
|
with open(path, 'w') as f:
|
|
f.write(c)
|
|
print('Updated ScheduledGivingCampaignResource nav')
|
|
|
|
# ── 3. AdminPanelProvider → Add Seasonal Campaigns group ──
|
|
|
|
path = os.path.join(BASE, 'app/Providers/Filament/AdminPanelProvider.php')
|
|
with open(path, 'r') as f:
|
|
c = f.read()
|
|
|
|
old_groups = """ ->navigationGroups([
|
|
// ── Daily Work (always visible, top of sidebar) ──
|
|
NavigationGroup::make('Daily')
|
|
->collapsible(false),
|
|
|
|
// ── Fundraising (campaigns, review queue) ──
|
|
NavigationGroup::make('Fundraising')
|
|
->icon('heroicon-o-megaphone')
|
|
->collapsible(),
|
|
|
|
// ── Setup (rarely touched config) ──
|
|
NavigationGroup::make('Setup')
|
|
->icon('heroicon-o-cog-6-tooth')
|
|
->collapsible()
|
|
->collapsed(),
|
|
])"""
|
|
|
|
new_groups = """ ->navigationGroups([
|
|
// ── Daily Work (always visible, top of sidebar) ──
|
|
NavigationGroup::make('Daily')
|
|
->collapsible(false),
|
|
|
|
// ── Seasonal Campaigns (30 Nights, 10 Days, Night of Power) ──
|
|
NavigationGroup::make('Seasonal Campaigns')
|
|
->icon('heroicon-o-calendar-days')
|
|
->collapsible(),
|
|
|
|
// ── Fundraising (appeals, review queue) ──
|
|
NavigationGroup::make('Fundraising')
|
|
->icon('heroicon-o-megaphone')
|
|
->collapsible(),
|
|
|
|
// ── Setup (rarely touched config) ──
|
|
NavigationGroup::make('Setup')
|
|
->icon('heroicon-o-cog-6-tooth')
|
|
->collapsible()
|
|
->collapsed(),
|
|
])"""
|
|
|
|
c = c.replace(old_groups, new_groups)
|
|
|
|
with open(path, 'w') as f:
|
|
f.write(c)
|
|
print('Updated AdminPanelProvider nav groups')
|
|
|
|
# ── 4. Update ListScheduledGivingDonations labels ──
|
|
|
|
path = os.path.join(BASE, 'app/Filament/Resources/ScheduledGivingDonationResource/Pages/ListScheduledGivingDonations.php')
|
|
with open(path, 'r') as f:
|
|
c = f.read()
|
|
|
|
c = c.replace(
|
|
"return 'Regular Giving';",
|
|
"return 'Scheduled Giving Subscribers';"
|
|
)
|
|
c = c.replace(
|
|
'return "{$active} people giving every month.";',
|
|
'return "{$active} active subscribers across all campaigns.";'
|
|
)
|
|
|
|
with open(path, 'w') as f:
|
|
f.write(c)
|
|
print('Updated ListScheduledGivingDonations labels')
|
|
|
|
# ── 5. Add "Recurring" tab to Donations list ──
|
|
# Monthly/weekly donors should be visible under Donations
|
|
|
|
path = os.path.join(BASE, 'app/Filament/Resources/DonationResource/Pages/ListDonations.php')
|
|
with open(path, 'r') as f:
|
|
c = f.read()
|
|
|
|
# Check if 'recurring' tab already exists
|
|
if "'recurring'" not in c:
|
|
# Find the 'everything' tab and add 'recurring' before it
|
|
old_everything = """ 'everything' => Tab::make('Everything')"""
|
|
new_recurring = """ 'recurring' => Tab::make('Recurring')
|
|
->icon('heroicon-o-arrow-path')
|
|
->badge($recurring > 0 ? $recurring : null)
|
|
->badgeColor('info')
|
|
->modifyQueryUsing(fn (Builder $q) => $q->where('reoccurrence', '!=', -1)
|
|
->whereHas('donationConfirmation', fn ($sub) => $sub->whereNotNull('confirmed_at'))),
|
|
|
|
'everything' => Tab::make('Everything')"""
|
|
c = c.replace(old_everything, new_recurring)
|
|
|
|
# Add $recurring count variable
|
|
if '$recurring' not in c:
|
|
c = c.replace(
|
|
"return [",
|
|
"$recurring = Donation::where('reoccurrence', '!=', -1)\n ->whereHas('donationConfirmation', fn ($q) => $q->whereNotNull('confirmed_at'))\n ->count();\n\n return [",
|
|
1 # only first occurrence in getTabs
|
|
)
|
|
|
|
with open(path, 'w') as f:
|
|
f.write(c)
|
|
print('Added Recurring tab to ListDonations')
|
|
else:
|
|
print('ListDonations already has recurring tab')
|
|
|
|
print('Navigation update complete!')
|