Major enhancements to the fl-maps admin panel for improved moderation capabilities at scale.
- Component:
imports/client/ui/pages/Admin/PostsView/index.js - Technology: react-window v1.8.10 (lightweight virtual scrolling library, 7KB)
- Features:
- Displays all posts in a scrollable list with efficient rendering
- Shows: Title, Organizer, Location, Categories, Date
- Inline delete action for individual posts
- Multi-select with bulk deletion
- Handles thousands of posts without performance degradation
- Search Filters:
- Title: Search posts by title
- User: Search by organizer name
- Location: Search by city, country, or location name
- Category: Search by category name
- Real-time search with automatic query on text change
- Filter buttons to switch search context
- Date (Newest) - Default sort
- Date (Oldest)
- Most Attendees
- Alphabetical (by title)
- By Category
- By Location
- Alphabetical - Default sort
- Most Posts (counts posts per user)
- Join Date (Newest)
- Join Date (Oldest)
- Multi-select checkboxes on posts
- "Select All" checkbox in header
- "Delete Selected (X)" button appears when posts are selected
- Confirmation dialog: "Are you sure you want to delete X posts?"
- Server method:
Admin.deletePostshandles bulk deletion safely
- Button to switch between "Posts View" and "Users View"
- Button text changes dynamically: "Show Posts View" / "Show Users View"
- Posts-specific controls only appear in Posts view
- Users-specific controls only appear in Users view
- Changed "Toggle Events Display" → "Toggle Posts Display"
- All user-facing text updated from "events" to "posts"
- Backend method names preserved for consistency (e.g.,
getEvents,deleteAllEvents)
- File:
server/methods/admin/syncDiscourseUsers.js - Features:
- Fetches all users from Discourse API
- Creates new user accounts in fl-maps
- Updates existing user profiles (name, username, email, roles)
- Syncs admin/moderator roles from Discourse
- Scheduled to run weekly automatically
- Manual trigger via "Sync Discourse Users" button in admin UI
- Logs sync results (total synced, created, updated)
- Purpose: Fetch posts with search, filter, and sort options
- Parameters:
searchQuery: String to search forsearchFilter: 'title' | 'user' | 'location' | 'category'sortBy: 'dateNewest' | 'dateOldest' | 'mostAttendees' | 'alphabetical' | 'category' | 'location'
- Returns:
{ posts: [], totalCount: Number } - Performance: Returns up to 1000 posts with selected fields only
- Purpose: Bulk delete posts by ID
- Parameters: Array of post IDs (strings)
- Security: Admin-only access
- Returns:
{ deletedCount: Number }
- Purpose: Sync users from Discourse to fl-maps
- Security: Admin-only access
- Returns:
{ totalSynced, totalCreated, totalUpdated, completedAt } - Schedule: Runs automatically every 7 days
Add to your settings.json:
{
"private": {
"discourse": {
"url": "https://your-discourse-instance.org",
"secret": "your-sso-secret",
"apiKey": "your-discourse-api-key",
"apiUsername": "system"
}
}
}To get a Discourse API key:
- Go to your Discourse admin panel
- Navigate to API → Keys
- Create a new API key with "All Users" scope
- Set the key to be used by user "system" (or another admin user)
- Copy the key to your settings
Users are automatically created when they log in via Discourse SSO. The Accounts.updateOrCreateUserFromExternalService method creates the user account, and the Accounts.onLogin handler:
- Sets
profile.namefrom Discourse name/username - Syncs roles (admin, moderator, user) from Discourse status
- This happens on every login, keeping profiles up-to-date
The syncDiscourseUsers function:
- Runs automatically on server startup (if last run was >7 days ago)
- Runs every 7 days automatically
- Can be triggered manually by admins via the "Sync Discourse Users" button
- Fetches ALL users from Discourse (paginated API calls)
- Creates accounts for users who haven't logged in yet
- Updates profiles for existing users (name, email, roles)
Why sync periodically?
- Ensures profile information stays current even if users don't log in frequently
- Catches role changes (e.g., user promoted to moderator in Discourse)
- Backfills users who exist in Discourse but haven't logged into fl-maps yet
imports/client/ui/pages/Admin/PostsView/index.js- Main posts view componentimports/client/ui/pages/Admin/PostsView/styles.scss- Styling for posts viewserver/methods/admin/getPosts.js- Server method for fetching postsserver/methods/admin/deletePosts.js- Server method for bulk deletionserver/methods/admin/syncDiscourseUsers.js- Discourse user sync logic
package.json- Added react-window@1.8.10 dependencyimports/client/ui/pages/Admin/index.js- View toggle, sort logic, sync buttonimports/client/ui/pages/Admin/style.scss- Styling for sort dropdownserver/methods/admin/index.js- Registered new server methodssettings.sample.json- Added Discourse API configuration
- Switch to Posts View: Click "Show Posts View" button
- Search Posts:
- Type in search box
- Click filter button (Title/User/Location/Category)
- Sort Posts: Select option from "Sort by" dropdown
- Delete Single Post: Click "Delete" button next to post
- Bulk Delete:
- Check boxes next to posts you want to delete
- Click "Delete Selected (X)" button
- Confirm deletion in dialog
- Sync Discourse Users (Admin only):
- Click "Sync Discourse Users" button in Users view
- Wait for sync to complete (may take a few minutes)
- View sync results in alert dialog
Run sync manually in Meteor shell:
Meteor.call('Admin.syncDiscourseUsers', (err, result) => {
console.log(result);
});- Virtual Scrolling: Only renders visible posts (~10-15 at a time)
- Field Selection: Server only returns necessary fields, reducing bandwidth
- 1000 Post Limit: Posts view caps at 1000 results (use search to narrow down)
- Debounced Search: Consider adding debounce if search performance is an issue
- Sync Duration: Discourse sync may take 1-2 minutes for large user bases (1000+ users)
Potential improvements:
- Pagination controls (in addition to virtual scrolling)
- Export posts to CSV
- Advanced filters (date range, category multi-select)
- Post preview/edit in admin
- User import from CSV
- Sync status indicator (last sync time, next scheduled sync)
- Check browser console for errors
- Verify
Admin.getPostsmethod is registered - Check user has admin permissions
- Verify Discourse API key is valid
- Check
apiUsernamehas admin permissions in Discourse - Check Discourse API endpoint is accessible from server
- Review server logs for detailed error messages
- Ensure react-window@1.8.10 is installed (compatible with React 16)
- Clear browser cache
- Check for console errors related to react-window
Manual testing checklist:
- Posts view displays correctly
- Search works for all filter types
- All sort options work correctly
- Individual post deletion works
- Bulk deletion works with confirmation
- View toggle preserves state
- User sort options work
- Discourse sync creates new users
- Discourse sync updates existing users
- Sync button shows "Syncing..." state
- Success/error messages display correctly