External monitoring via UptimeRobot (free tier) with internal health
logger to differentiate ISP outages from server issues. Includes:
- 4 new DB models (UptimeMonitor, UptimeCheck, UptimeIncident, InternalHealthLog)
- Migration 082 with tables, indexes, and permissions
- Internal health logger script (cron */5 min)
- UptimeRobot sync script (cron hourly) with automatic cause correlation
- Admin dashboard /admin/uptime with uptime %, response time charts,
incident log with editable notes/causes, pattern analysis, monthly report
- SLA comparison table (99.9%/99.5%/99%)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prevents confusing "link invalid" error when verification link is
clicked twice (or prefetched by email clients like Outlook). The token
now expires naturally instead of being cleared on first use.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New page /admin/gbp-audit/match-places shows companies without
google_place_id. Admin searches Google Maps, reviews results, and
confirms the correct match. Adds search_places_raw() to return all
results without name filtering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Companies with an existing google_place_id now skip the name-matching
search and use the verified Place ID directly. This fixes companies like
ALMARES ("PSB Profi Almares" in Google) whose single-word name failed
strict matching. Also removes invalid 'source' kwarg from GBPAudit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Batch audit now collects changes without saving to DB. Admin must
review before/after differences and approve or discard. Mirrors the
existing social audit enrichment review pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Run audit for all active companies with background thread, live progress
panel, and optional Google Places API data refresh. Pattern mirrors
existing social audit batch implementation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Personalized guide with GBP links (write review, view profile, photos)
for each member's company. Includes tips on collecting reviews,
responding to feedback, Local Guides program, and Google policies.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin-sent reset emails now say "Administrator portalu wygenerował
link do ustawienia hasła" instead of generic "zażądano resetowania".
Validity period shown correctly: 24h for admin, 1h for self-service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The admin reset-password endpoint used datetime.utcnow() while the
validation used datetime.now(), causing tokens to appear expired
immediately on CET servers. Changed to datetime.now() and extended
admin-initiated resets to 24 hours validity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin can now send a password reset email directly from /admin/users
instead of manually copying and sharing the reset link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove unused social-media analytics panel (replaced by social-audit).
Rename admin menu items for clarity:
- Forum → Moderacja forum
- Ogłoszenia → Moderacja ogłoszeń
- Rekomendacje → Moderacja rekomendacji
- Deklaracje → Zarządzanie deklaracjami
- Składki → Zarządzanie składkami
- Korzyści → Zarządzanie korzyściami
- Social Media → Audyt social media
- Social Dashboard → Publikacja social media
- Kalendarz → Zarządzanie kalendarzem
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace generic "OAuth API niedostępne" with platform-specific
instructions explaining what's needed to fetch data:
- Instagram: 3-step guide (Business account, FB link, OAuth)
- Twitter/YouTube: note that data is fetched automatically
- Facebook: prompt to connect OAuth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- YouTubeService now fetches: subscribers, views, video count, description,
avatar, banner, country, creation date, recent 5 videos
- Enricher uses API first, falls back to scraping
- Extra YouTube data stored in content_types JSONB
- Audit detail shows view count, country, creation date, recent videos
- Requires enabling YouTube Data API v3 in Google Cloud Console
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can now select which platforms to scan (Facebook, Instagram,
LinkedIn, YouTube, Twitter/X, TikTok) via checkboxes in the
confirmation dialog. Backend filters both company list and profiles.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 attempts with 2-5s random delay between retries. Detects authwall
and rate limit (429/999) responses. Updated status message to explain
LinkedIn's inconsistent availability to users.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
og:description from LinkedIn/Facebook embeds dynamic follower counts
and varies by language, causing false "changes" on every scan.
The field is still saved to DB, just not tracked for review.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of checking profile.source (which was never 'facebook_api'),
now checks SocialMediaConfig for companies with OAuth page_id.
Added progress indicator with spinner and percentage during scan.
After API sync, page auto-refreshes to show new data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of skipping OAuth-connected Facebook profiles, the enrichment
scan now calls sync_facebook_to_social_media() to fetch fresh data
via Graph API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Events with plain text (no <p>, <br>, <div>, <ul> tags) now get
newlines converted to <p>/<br> for proper formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- /profil/<user_id>: simple profile for users without person_id,
redirects to /osoba/ if person_id exists
- event.html: all attendees are now clickable links (green)
- Auto-link User→Person by name match on every login (no manual scripts)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parse HTML into tags and text nodes, only process text nodes outside
<a> tags. Uses \b word boundary instead of broken lookbehind.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Member names in event description link to person profiles
- URLs auto-linked (nordabiznes.pl, https://... etc)
- Calendar add section: blue gradient card with Google/Outlook buttons
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- POST /konto/avatar: upload, center-crop to square, resize 300x300
- POST /konto/avatar/delete: remove file and clear DB
- dane.html: interactive avatar editor with hover overlay
- person_detail.html: show photo if available, fallback to initials
- Migration 070: avatar_path column on users table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rada Izby badge next to name
- Last active label (e.g. "Aktywny 2 dni temu")
- Forum stats (topics + replies count)
- Recent events attended (up to 5, linked)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Norda Biznes logo on featured events
- Speaker name links to person profile
- Google Calendar and ICS/Outlook export buttons
- Update dev banner: official launch April 9, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Facebook, Instagram, LinkedIn block public access - messages now explain
this and suggest OAuth API connection instead of generic "no data".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace all _enrichment_status in-memory dict references with
file-based shared state (/tmp/nordabiz_enrichment_state.json).
Fixes enrichment appearing instantly complete in multi-worker env.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Live panel with spinner, progress bar, company counter
- Each company appears as a row with platform badges showing status
(changes/no_changes/skipped/error/no_data)
- Incremental polling (since= param) for efficient updates
- After completion: link to review page if changes found
- Blue highlighted rows for companies with new data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Scraper now collects data to staging area (in-memory), NOT to database
- New review page (/admin/social-audit/enrichment-review) with:
- Summary stats (scanned, changes, skipped, errors)
- Per-company expandable sections with before→after diff per field
- Pending approval banner with change count
- Sticky bottom bar with Approve/Discard buttons
- Approve endpoint writes staged data to DB
- Discard endpoint clears staging without touching DB
- After scan completes, auto-redirect to review page
- Companies without changes shown in collapsed list
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Scraper no longer overwrites API data (source priority hierarchy)
- Per-platform data provenance badges (API OAuth/Scraping/Manual/Unknown)
- Expandable field-level source breakdown (which fields from API vs scraping)
- OAuth status per platform with connect/renew/sync links
- "Run audit" button on dashboard (background enrichment for all companies)
- "Run audit" button on detail view (single company enrichment)
- Enrichment progress polling with real-time status updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Social Health Score (0-100) composite: activity 30%, engagement 25%,
completeness 20%, growth 15%, cross-platform 10%. Add followers growth
rate from JSONB history, activity status classification (active/moderate/
slow/dormant/abandoned). Display health score in dashboard table and
detail view with color-coded ring, growth indicators per platform,
and cross-platform coverage score.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows latest version, date, one highlight feature, and count of other
changes. Links to /release-notes. Extracted _get_releases() helper
for reuse between index and release_notes routes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New route /admin/social-audit/<company_id> showing detailed social media
audit per company: platform cards with metrics, profile checklist,
completeness bar, recommendations, invalid profiles section.
Added audit detail icon in dashboard table alongside profile link.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows full conversation thread when replies exist, with per-message
status (sent/read with timestamps), sender→recipient flow, and
current message highlighted. Single messages show status bar at bottom.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
UserCompanyPermissions has no 'position' column, causing 500 error on
/wiadomosci/nowa. Use User.company_role as fallback for position display.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>