New email template with friendly tone and green CTA button for first-time
account activation. Script with --dry-run, --test-email, --user-id flags
and 72h token validity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add frontend button disable on submit and backend duplicate detection
(same user, same content, within 30 seconds).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New column: users.notify_email_messages (default true)
- Send email via MS Graph when someone receives a private message
- Toggle in /konto/prywatnosc to enable/disable email notifications
- Email includes message preview, sender name, and direct link
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of using stale open_now flag from audit time, opening hours
status is now computed client-side using JavaScript Date and the
periods data from Google Business Profile. Updates every 60 seconds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
URLs are now linked before being wrapped in <li>/<blockquote>,
and consecutive text lines are joined into paragraphs instead of
getting individual <br> tags.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Normalize \r\n to \n before processing
- Strip leading whitespace from lines (textarea indentation)
- Auto-link bare URLs works correctly inside list items
- Smart <br> insertion: skip block elements (ul, li, blockquote, pre)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plain https:// URLs are now automatically converted to clickable links.
Markdown [text](url) syntax continues to work without duplication.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merged three separate v1.36-38 entries for Feb 20 into single v1.36.0.
Renumbered: Feb 21 = v1.37.0, Feb 22 = v1.38.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hovering over a reaction button (👍, ❤️) now shows who reacted.
Names are loaded server-side and updated dynamically after toggling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
User model has 'name', not 'full_name'. The incorrect attribute caused
every hover tooltip on forum usernames to show an error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Email button as full-width card showing address + "Wyślij e-mail"
- Private message button with subtitle "na portalu Norda Biznes"
- Phone shown as plain text above action buttons
- Contact preferences moved to bottom as subtle footer
- Both actions clearly distinguishable with different styling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Email/phone are already clickable links (mailto:/tel:), no need for
separate button. Renamed "Napisz" to "Wiadomość prywatna" with chat
icon to clearly distinguish from email contact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set is_norda_member=True when admin assigns active company to user
- Clear is_norda_member=False when last active company is removed
- Covers admin edit route and admin API add/remove company routes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create UserNotification when sending private message (bell icon)
- Add "Wiadomości" link in main nav between Social and Aktualności
- Unread badge syncs across nav, user menu, and bell via polling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- "Powrót do firmy" link when composing from company profile
- "Wyślij e-mail" button opens default mail client (mailto:)
- "E-mail" button on company contact cards for direct mailto
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows portal users linked to a company with their contact details,
role badges, Norda membership status, and direct messaging link.
Respects individual privacy settings (show_phone, show_email).
Addresses forum feedback from Jakub Bornowski (topic #18).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a "Send reset" action button in the Problems tab and user profile page,
allowing admins to send password reset emails directly from User Insights
dashboard. Each reset requires manual confirmation via dialog.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users who had auth problems (failed logins, password resets, security
alerts) but have since logged in successfully are now shown in a
collapsed "Rozwiązane problemy" section. Active problems remain
prominently displayed at the top.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows whether password resets and welcome emails led to successful logins:
- Summary cards: success rate, resolved/pending/failed counts, avg time to login
- Detailed table: each action with user, type, date sent, and outcome
- Resolved = user logged in after email, Pending = <48h, Failed = no login
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- _tab_problems: 750 queries → ~10 batch queries with GROUP BY
- _tab_engagement: 2550 queries → ~12 batch queries, sparkline in 1 query
- user_insights_profile: 60+ queries → batch trend (2 queries), bot filtering on all metrics
- Stat cards exclude UNAFFILIATED, dormant excludes never-logged-in users
- Engagement status: never-logged=dormant, login<=7d+score>=10=active, 8-30d=at_risk
- Badge CSS: support both at-risk and at_risk class names
- Problems table: added Alerts and Locked columns
- Security alerts stat card in Problems tab
- Back link preserves tab/period context
- Trend chart Y-axis dynamic instead of hardcoded max:30
- Timeline truncation info when >= 150 events
- Migration 080: composite indexes on audit_logs and email_logs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add is_bot column to user_sessions with backfill from user_agent patterns
- Update analytics_daily trigger to skip bot sessions
- Recalculate 90 days of analytics_daily without bot contamination
- Replace cumulative failed_login_attempts with time-based audit_logs queries
- Switch engagement score from linear (capped at 100) to log2 scale
- Expand section_map from 9 to 17 categories (~95% traffic coverage)
- Exclude robots.txt, sitemap.xml etc from page view tracking
- Add bot filter to all overview, pages, paths, and engagement queries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Proactive alerts in Problems tab: never_logged_in, locked, reset_no_effect, repeat_resets
- 5th stat card showing never-logged-in users count
- Full problem chronology in user profile: audit_logs, emails, sessions, security alerts
- Resolution status card: resolved/pending/blocked/unresolved with time-to-resolution
- Timeline enhanced with detail field, CSS severity classes, and new icon types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
email_logs.user_id is never populated for password_reset emails.
Match by recipient_email instead. Also fix failed_logins stat card
to use users.failed_login_attempts sum instead of security_alerts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Migration 064 fixes 12 records in company_websites table missing https://
- Added ensure_url filter to w.url in contact bar template as safety net
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Updated Facebook link from /nordabiznes to /profile.php?id=100057396041901
across all 4 locations (email templates, JSON-LD schema)
- Added Facebook link to site footer (Contact section)
- Added "Follow us on Facebook" to landing page CTA
- Redesigned upcoming events: side-by-side layout instead of stacked
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previous logo-circle.png was 404, favicon-192 was wrong icon.
Generated logo-email.png from favicon.svg compass via sharp.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shared _email_v3_wrap() helper: branded header with logo, full footer
with address/links. Updated: password reset, welcome, forum reply,
role notification. Action buttons grid layout in /admin/users.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Email: dark header with compass, company card, green checkmarks, Polish
date format, full footer with address, phone and tech support contact.
Actions: 4-column grid layout instead of vertical stack.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds envelope icon in AKCJE column that sends an email to the user
with their current company role and permissions summary.
Uses approved v3 email template with Norda Business branding.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every email sent via send_email() now includes a BCC to the portal
administrator (MAIL_BCC env var, defaults to maciej.pienczyn@inpi.pl).
Recipients who are already in TO are automatically excluded from BCC.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix address from Hallera 18 to 12 Marca 238/5 in all JSON-LD, contact
section, and Google Maps embed
- Update geo coordinates for new address
- Broaden company descriptions: not just Wejherowo but also powiat
wejherowski, neighboring counties, and wojewodztwo pomorskie
- Update all meta descriptions, OG tags, hero text, and tile headers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Polish city name declensions to local keyword matcher
- Add openingHours string format alongside openingHoursSpecification
- Add Wejherowo to page title for city_in_title signal
- Add service+city keyword phrases in visible text (serwis, transport,
szkolenia, sklep, remonty, instalacje + Wejherowo/Rumia/Reda/Gdynia)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add email, image, priceRange, openingHoursSpecification to LocalBusiness JSON-LD
- Add Google Maps embed with address section on landing page
- Add local keywords (Wejherowo, Kaszuby) in visible text
- Add frame-src CSP directive for Google Maps iframe
- Responsive layout for map section on mobile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
parsedate_to_datetime returns offset-aware datetime from Last-Modified
header, but datetime.now() is naive. Strip tzinfo before subtraction.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add missing SEO elements to improve audit score from 89 to 95+:
- Canonical URL and dynamic meta description blocks in base.html
- Open Graph tags (og:title, og:description, og:image, og:url, og:locale)
- JSON-LD structured data (Organization + WebSite schemas)
- robots.txt route with proper Disallow rules
- sitemap.xml route with homepage and release-notes
- LocalBusiness JSON-LD schema on landing page for Local SEO
- Last-Modified header for freshness signals
- Preload critical image for LCP optimization
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. seo_analyzer.py: Consider aria-label, title, img AND svg as valid
link text (SVG icon links were falsely counted as "without text")
2. routes_portal_seo.py: Calculate overall_seo score using
SEOAuditor._calculate_overall_score() before saving to DB
(was always None because stream route bypasses audit_company())
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Extract HSTS, CSP, X-Frame-Options, X-Content-Type-Options from
HTTP response headers during portal SEO audit (were always None
because SEOAuditor doesn't check security headers natively)
2. Add aria-label to all social media and website icon links on
landing page tiles (300 of 317 links had no text content,
only SVG icons)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>