Replace 'Najnowszy wpis na forum' (duplicate with Nowe na portalu)
with 'Nowi użytkownicy portalu' showing 4 latest registered users
with avatars, names, dates and company names.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows 2 latest forum topics + 2 latest B2B classifieds in a 4-column
grid between events and NordaGPT banner. Responsive 2-col on mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New edit route with form pre-filled with existing data
- Edit existing attachments (mark for deletion) + add new ones
- Edit button visible to classified author on detail view
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New ClassifiedAttachment model with migration
- FileUploadService extended with 'classified' type
- Dropzone with drag & drop, paste, multi-file preview in creation form
- Image gallery with lightbox in classified detail view
- Max 10 files, 5MB each, JPG/PNG/GIF
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Left-align grid (max-width 900px)
- Show 12 events instead of 8
- Add filter buttons (Wszystkie / Norda Biznes / Zewnętrzne)
- Green gradient for external events matching homepage style
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New "Karty" view shows up to 8 upcoming events as dark gradient cards
in a 2-column grid, matching the homepage event banner style.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add profile links to usernames and avatars across forum, classifieds,
announcements, company recommendations, board members, and group messages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added global parseUTC() helper in base.html that appends 'Z' to
naive ISO dates from server. Applied to:
- Notification bell (base.html) — formatTimeAgo
- NordaGPT conversation sort (chat.html)
- B2B interest dates (classifieds/view.html)
- Admin forum moderation dates (admin/forum.html)
- Admin AI insights dates (admin/insights.html)
Same fix as conversations.js parseUTC, now available globally.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The clipboard.onPaste override broke text pasting in Quill 2.x
where this internal API is no longer public. Replaced with a DOM
paste event listener on quill.root that only intercepts image
pastes and lets Quill handle text paste natively.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added "X odpow." counter next to views count on each classified
card in the B2B board listing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added avatar_path photo display for: author avatar, seen-by readers,
and Q&A question authors on the classified detail page. Falls back
to colored initial circle when no photo is uploaded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When clicking "Skontaktuj się" on a classified ad, the conversation
now starts with a pre-filled message: "Hej, piszę w sprawie ogłoszenia
na tablicy B2B: „<tytuł>"". If conversation already exists, the
context is pre-filled in the editor for the user to send.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The interest endpoint was returning 400 because fetch sent
Content-Type:application/json with an empty body, causing Flask
to fail JSON parsing. Removed the header since no JSON body is
sent. Also reverted unnecessary CSRF blueprint exemption.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Changed B2B classified contact link from old messages_new to new
conversations page with ?new_to=USER_ID parameter. JS creates a
1:1 conversation via API and opens it, or opens existing one if
already present. Messages now visible in the conversations inbox.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New /admin/roadmap page showing feature requests from members in
three columns: Planned, In Progress, Done. Cards expand on click
to show implementation details. First item: multi-location support
requested by Daniel Kochański (Stalpunkt).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mobile menu stayed open after history.back() due to bfcache restoring
the page with menu in active state. Now closes menu before navigating
back, and on pageshow event to handle bfcache restore.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows a ← back button in the navbar only when running as installed
PWA (display-mode: standalone). Uses history.back() for navigation.
Hidden in regular browser where native back button exists.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Browser's native anchor scroll races with JS. Run doScroll at 50ms,
300ms, and 600ms after load to ensure it wins regardless of timing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use window 'load' event and scrollRestoration=manual to ensure scroll
happens after all content is rendered, overriding browser's native
anchor scroll which fires too early.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When opening a forum topic from a notification link (e.g. #reply-55),
the page now smoothly scrolls to the specific reply with a brief
highlight, accounting for the sticky header offset.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server stores timestamps in UTC without timezone suffix. JavaScript
new Date() treated them as local time, showing times 2h behind.
Added parseUTC() helper that appends 'Z' to naive ISO dates so the
browser correctly converts UTC → user's local timezone.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The template always rendered initials instead of checking for avatar_path.
Now displays the user's photo when available, with initials as fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Fixed missing rx parameter in SVG arc command (a2 0 → a2 2 0)
that caused console error on every page load
2. Removed preload of favicon-512.png — only used in meta tags,
not rendered on page, causing "preloaded but not used" warning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A previous replace-all of 'currentConversation' → 'currentConversationId'
doubled the suffix on the existing 'currentConversationId' variable,
breaking all conversation state references including the group panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The panel was showing 0 members because it used cached conversation
details that might have been loaded before the panel was opened.
Now it always fetches fresh data from the API.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New PATCH /api/conversations/<id>/members/<uid> endpoint for role changes
- Owner can promote members to admin and demote back to member
- Admin can add/remove members and edit group name (same as owner except role changes)
- Member list shows role labels (Właściciel/Administrator/Członek)
- Fix: state.currentConversation → state.currentConversationId (panel was empty)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When viewing a group conversation, a settings button appears in the chat
header. Clicking it opens a panel to: rename the group (owner only),
view members with roles, remove members (owner only), and add new members
via search. Uses existing API endpoints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New button next to "Nowa wiadomość" with outline style. Modal includes
group name field, multi-member search picker, and optional first message.
Uses the existing POST /api/conversations endpoint with is_group=true.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The modal had no CSS — it was rendering as unstyled HTML. Added proper
overlay, card layout, input styling, suggestion list, and footer buttons
matching the NordaBiz design system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The compose button was just a small pencil icon with no label. Now it shows
"Nowa wiadomość" text (hidden on mobile). Recipient search was broken because
window.__USERS__ was always empty — replaced with /api/users/search API endpoint
that queries active users by name/email with autocomplete suggestions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JS reads from API JSON which returns 'attendee_count' field (already includes
guests after previous fix). Using 'total_attendee_count' caused 'undefined'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Event attendee counts were inconsistent - event detail page showed total
(members + guests = 42) but event list and homepage showed only members (39).
Now all views use total_attendee_count including guests (osoby towarzyszące).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logo images were cached for 30 days by nginx. After selecting a new logo
from the gallery, the browser still showed the old/placeholder image.
- Add cache-bust query param (?v=timestamp) to logo <img> src
- Update company.last_updated when logo is confirmed
- Use Date.now() redirect instead of reload() after confirm
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Flash success message showing format conversion (e.g. "JPG do WebP")
- Flash error message if conversion fails with suggestion to try another file
- Flash warning for unsupported file formats
- Form hint explains automatic WebP conversion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description is managed by portal admin (via CLI/DB), not editable in form.
Office manager edits only structured fields (title, date, time, prices, etc).
New events still get a plain textarea for initial description.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Admin action bar (edit + payments) moved to top of event detail page
- Quill WYSIWYG editor replaces raw textarea in event create/edit form
- Back-to-event link in edit form
- Removed duplicate admin buttons from bottom of event page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Route GET/POST /admin/kalendarz/<id>/edytuj
- Reuses admin_new.html template with pre-filled fields in edit mode
- Edit button on event detail page and admin calendar list
- Supports all fields including paid event settings and attachments
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- EventGuest.guest_type: 'member' (member rate) or 'external' (guest rate)
- Dropdown of company colleagues when adding member-type guest
- Manual entry option for members not on portal
- Admin payment panel: "Dodaj osobę" with "Dodaj + opłacone" shortcut
- Migration 064: guest_type column
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add is_paid, price_member, price_guest to NordaEvent. Add payment_status,
payment_amount, payment_confirmed_by/at to EventAttendee and EventGuest.
Auto-assign amounts on RSVP. Admin panel at /admin/kalendarz/<id>/platnosci
for OFFICE_MANAGER to confirm payments. User sees payment status on event page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PWA smart banner displayed icon at 40x40 but loaded 192x192 PNG (17KB).
Now uses 48x48 WebP (1.9KB) — 89% smaller, with explicit dimensions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Browser starts downloading fonts immediately instead of waiting
for CSS parse. Reduces the window between system font and Poppins,
which should lower CLS from font-display: swap reflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
d3.v7.min.js (225KB) and connections_modal.html (~1100 lines) were
loaded on every page but only used by owner-only "Mapa Powiązań" tool.
- Removed d3.js and connections_modal include from base.html
- Added {% block extra_scripts %} for pages that need external JS
- admin/zopk_knowledge_graph.html loads d3 via extra_scripts block
- connections_map.html already had its own d3 import
- "Mapa Powiązań" link now points to /connections page instead of modal
- zopk/index.html d3 code was disabled ({% if false %}) — no change needed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace external Google Fonts CSS request (780ms render-blocking) with
self-hosted woff2 files served from /static/fonts/ with 30-day cache.
- 8 woff2 files: Poppins 400/500/600/700 × latin/latin-ext (53KB total)
- Inline @font-face declarations in <style> tag (no external request)
- font-display: swap preserved (no FOIT)
- CSP updated: removed fonts.googleapis.com and fonts.gstatic.com
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Missed 2 occurrences of #94a3b8 in previous commit. Now zero instances
of the old color remain in base.html.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previous contrast ratio 3.58:1 (FAIL), now 4.82:1 (PASS).
Affects footer section text, links, footer-bottom, and inline span.
All 18 elements flagged by Lighthouse are resolved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix heading hierarchy: H4→H3 in "Dlaczego warto?" section (6 cards)
to maintain sequential H1→H2→H3 order (accessibility)
- Add explicit width/height to logo images in header/footer (CLS)
- Add Cache-Control: 30 days for /static/ assets (performance)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add defer to d3.v7.min.js in base.html — eliminates ~1.8s render
blocking on every page (d3 only needed on user interaction)
- Shorten landing page title from 71 to 59 chars (SEO optimum: 30-60)
- Add Permissions-Policy security header (camera, microphone, geolocation)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Forum tile: show newest reply (author + date), not newest topic creation
- New members: find newest board meeting that actually has admitted companies
- Fix events-row container for proper filter rendering
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add admitted_at_meeting_id to Company model linking firms to board meetings.
Homepage now shows 2 events (left column) + latest forum topic and new members
admitted at the last board meeting (right column). Responsive single-column on mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Production moved from on-prem VM 249 (10.22.68.249) to OVH VPS
(57.128.200.27, inpi-vps-waw01). Updated ALL documentation, slash
commands, memory files, architecture docs, and deploy procedures.
Added |local_time Jinja filter (UTC→Europe/Warsaw) and converted
155 .strftime() calls across 71 templates so timestamps display
in Polish timezone regardless of server timezone.
Also includes: created_by_id tracking, abort import fix, ICS
calendar fix for missing end times, Pros Poland data cleanup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Self-referential FK with lazy='joined' causes DetachedInstanceError after
db.close(). Build a simple dict lookup in the route instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add created_by_id FK to users table (NULL = self-registration)
- Set created_by_id in admin create, bulk create, and team add routes
- Show "samorejestracja" or "dodał: [name]" in admin users panel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
localStorage key was global ('audit_open_Strona_WWW') — expanding on one
company expanded on all. Now uses company ID in key and defaults to collapsed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Modal had overflow:hidden cutting off the footer buttons. Changed to
overflow-y:auto with sticky footer so 'Zapisz wybrane' is always reachable.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Auto-strip legal form from name (CONSTELLATION SP. Z O.O. → Constellation)
2. Auto-suggest category from main PKD code (62.02.Z → IT)
3. Clean empty 'https://' from WWW field
4. Rename button to 'Wyszukaj w internecie'
5. Auto-advance to step 4 after logo confirmation
6. Larger logo preview in summary step
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Green checkmarks appear next to correctly filled fields in Step 2
- Live validation on input (checkmarks update as user types)
- 'Wyszukaj stronę' recognizes when URL already from KRS
- Backend returns existing website without Brave search if already known
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KRS for PROS POLAND has no www/email/phone. All Brave results are directory
sites (filtered). Show clear message about what's missing from registry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add 'Wyszukaj stronę' button in Step 2 next to WWW field (uses WebsiteDiscoveryService/Brave)
- Fix company name: update from legal_name when KRS enrichment provides it
- Add discover-website endpoint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allows Kierownik Biura to independently add new member companies via NIP lookup,
registry data enrichment (KRS/CEIDG), logo discovery, SEO/GBP/Social audits.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Logo upload in company edit was writing the file path to `logo_dark_bg`
(a Boolean column), causing TypeError and rolling back ALL profile changes.
Now saves to static/img/companies/{slug}.{ext} where company_detail expects it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Hide "Zapisz zmiany" and preview panel when team tab is active
- Show last login date or "Nie zalogował/a się jeszcze" per member
- Add "Wyślij ponownie zaproszenie" button for inactive accounts
- New endpoint POST /firma/<id>/zespol/<user_id>/zaproszenie
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Permission checkboxes now show descriptive labels with hints explaining
what each permission controls. Role descriptions visible under each member.
Dropdown options in add form also more descriptive.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nordaConfirm(message, callback) signature requires callback as 2nd arg,
not 3rd. The description text is now part of the message HTML.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow company MANAGERs to add/remove users, change roles,
and manage granular permissions from the company edit page.
New "Zespół" tab with AJAX-based team CRUD.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nordaConfirm now accepts both (form, message, options) for form submission
and (message, callback, options) for AJAX-based confirmations like guest deletion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nordaConfirm() expects (form, message, options) for form submission,
not a callback. Using native confirm() for AJAX-based guest deletion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Menu was placed outside header (for iOS z-index stacking) but used
position:absolute relative to body, rendering it below viewport.
Changed to position:fixed with dynamic top calculated from trigger
button position via getBoundingClientRect.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds direct shortcut to company edit (MANAGER) or company profile (EMPLOYEE)
in the user avatar dropdown. Addresses feedback that editing company data
required searching for own company in the directory.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows: total active, paying members, subsidiaries (fee in parent),
resignations, standard vs premium fee tier counts.
All dynamic from database.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GBP audit modal displayed raw <span> tags instead of rendered HTML
because updateStep() used textContent instead of innerHTML.
Migration 090: Lord Alkohole NIP update (company transformation).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause of double paste: Quill's internal clipboard handler AND my DOM
handler both processed the image. Fix: override clipboard.onPaste directly
to intercept images before Quill processes them.
- uploadAndInsertImage() extracted as reusable method
- CSS: img.selected gets resize:both for native browser resize handle
- Removed complex DOM resize hack (didn't work with Quill contenteditable)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>