diff --git a/blueprints/public/routes_company_edit.py b/blueprints/public/routes_company_edit.py index 71c462f..4df4439 100644 --- a/blueprints/public/routes_company_edit.py +++ b/blueprints/public/routes_company_edit.py @@ -5,7 +5,7 @@ Company Edit Routes Routes for editing company profiles by authorized users. """ -from flask import render_template, request, redirect, url_for, flash +from flask import render_template, request, redirect, url_for, flash, jsonify from flask_login import login_required, current_user from blueprints.public import bp from sqlalchemy import or_ @@ -20,6 +20,11 @@ EMPLOYEE_COUNT_WHITELIST = ['1-5', '6-10', '11-25', '26-50', '51-100', '101-250' VALID_SOCIAL_PLATFORMS = ['facebook', 'linkedin', 'instagram', 'youtube', 'twitter', 'tiktok'] VALID_WEBSITE_TYPES = ['website', 'store', 'booking', 'blog', 'portfolio', 'other'] EDITABLE_SOURCES = [None, 'manual_edit', 'manual'] +VALID_SECTION_KEYS = [ + 'about', 'services', 'board', 'owner_info', 'registry', 'legal', + 'contact', 'social_media', 'recommendations', 'website', 'seo_audit', + 'gbp_audit', 'social_audit', 'it_audit', 'news', +] @bp.route('/firma/edytuj') @@ -67,6 +72,24 @@ def company_edit(company_id=None): editable_contacts = [c for c in contacts if c.source in EDITABLE_SOURCES] + section_definitions = [ + ('about', 'O firmie', 'Opis firmy, historia, wartości'), + ('services', 'Usługi i kompetencje', 'Oferowane usługi, technologie, obszar działania'), + ('board', 'Zarząd i Wspólnicy', 'Osoby w zarządzie, wspólnicy, prokurenci'), + ('owner_info', 'Właściciel (JDG)', 'Dane właściciela jednoosobowej działalności'), + ('registry', 'Dane z rejestrów urzędowych', 'Dane z CEIDG/KRS, PKD, adresy rejestrowe'), + ('legal', 'Informacje prawne i biznesowe', 'NIP, REGON, KRS, forma prawna'), + ('contact', 'Dane kontaktowe', 'Telefony, e-mail, adres, dodatkowe kontakty'), + ('social_media', 'Social Media', 'Profile w mediach społecznościowych'), + ('recommendations', 'Rekomendacje', 'Rekomendacje od innych członków Izby'), + ('website', 'Strona WWW', 'Link do strony i podgląd'), + ('seo_audit', 'Analiza SEO', 'Wyniki audytu SEO strony internetowej'), + ('gbp_audit', 'Audyt Google Business Profile', 'Wyniki audytu wizytówki Google'), + ('social_audit', 'Audyt Social Media', 'Wyniki audytu mediów społecznościowych'), + ('it_audit', 'Audyt IT', 'Wyniki audytu infrastruktury IT'), + ('news', 'Aktualności i wydarzenia', 'Najnowsze wydarzenia firmy'), + ] + return render_template( 'company_edit.html', company=company, @@ -76,6 +99,7 @@ def company_edit(company_id=None): social_media=social_media, company_websites=company_websites, permissions=permissions, + section_definitions=section_definitions, ) finally: db.close() @@ -309,3 +333,38 @@ def _save_websites(db, company): company.website = ensure_url(sanitize_input(website_urls[0], max_length=500)) else: company.website = None + + +@bp.route('/firma/edytuj//visibility', methods=['POST']) +@login_required +def company_edit_visibility(company_id): + """Save section visibility preferences via AJAX.""" + if not current_user.can_manage_company(company_id): + return jsonify({'error': 'Brak uprawnień'}), 403 + + db = SessionLocal() + try: + company = db.query(Company).get(company_id) + if not company: + return jsonify({'error': 'Nie znaleziono firmy'}), 404 + + data = request.get_json() + if not data or 'hidden_sections' not in data: + return jsonify({'error': 'Brak danych'}), 400 + + hidden = data['hidden_sections'] + if not isinstance(hidden, list): + return jsonify({'error': 'Nieprawidłowy format'}), 400 + + # Validate keys + validated = [k for k in hidden if k in VALID_SECTION_KEYS] + company.hidden_sections = validated + db.commit() + + return jsonify({'success': True, 'hidden_sections': validated}) + except Exception as e: + db.rollback() + logger.error(f"Error saving visibility for company_id={company_id}: {e}") + return jsonify({'error': 'Wystąpił błąd'}), 500 + finally: + db.close() diff --git a/database.py b/database.py index 2f9f337..b820116 100644 --- a/database.py +++ b/database.py @@ -855,6 +855,13 @@ class Company(Base): cascade='all, delete-orphan', order_by='CompanyWebsite.is_primary.desc()') + # Profile section visibility + hidden_sections = Column(PG_JSONB, nullable=False, default=list, server_default='[]') + + def is_section_hidden(self, section_key): + """Check if a profile section is hidden from visitors.""" + return section_key in (self.hidden_sections or []) + class Service(Base): """Services offered by companies""" diff --git a/database/migrations/069_company_hidden_sections.sql b/database/migrations/069_company_hidden_sections.sql new file mode 100644 index 0000000..bff34a9 --- /dev/null +++ b/database/migrations/069_company_hidden_sections.sql @@ -0,0 +1,7 @@ +-- Migration 069: Add hidden_sections column to companies table +-- Allows company owners/managers to hide specific profile sections from visitors + +ALTER TABLE companies ADD COLUMN IF NOT EXISTS hidden_sections JSONB NOT NULL DEFAULT '[]'::jsonb; + +-- Grant permissions +GRANT ALL ON TABLE companies TO nordabiz_app; diff --git a/templates/company_detail.html b/templates/company_detail.html index f51ed37..bd7c3d3 100755 --- a/templates/company_detail.html +++ b/templates/company_detail.html @@ -91,6 +91,23 @@ margin-bottom: var(--spacing-xl); } + .company-section.section-hidden { + opacity: 0.6; + border: 2px dashed var(--warning-color, #f59e0b); + } + .hidden-section-badge { + background: var(--warning-color, #f59e0b); + color: white; + padding: 4px 12px; + border-radius: var(--radius, 0.5rem); + font-size: 0.85rem; + margin-bottom: var(--spacing-sm, 8px); + display: inline-flex; + align-items: center; + gap: 6px; + } + .hidden-section-badge i { font-size: 0.9rem; } + .section-title { font-size: var(--font-size-2xl); color: var(--text-primary); @@ -898,8 +915,12 @@ {% set about_description = company.description_full or (ai_insights.business_summary if ai_insights else none) or (website_analysis.content_summary if website_analysis else none) %} -{% if about_description %} -
+{% set _about_hidden = company.is_section_hidden('about') %} +{% if about_description and (not _about_hidden or can_edit_profile or is_admin) %} +
+ {% if _about_hidden %} +
Ukryta — niewidoczna dla odwiedzających
+ {% endif %}

O firmie

@@ -949,8 +970,12 @@ {% set www_services = website_analysis.services_extracted if website_analysis and website_analysis.services_extracted else [] %} {% set www_keywords = website_analysis.main_keywords if website_analysis and website_analysis.main_keywords else [] %} -{% if www_services or www_keywords or company.services or company.competencies or company.services_offered or company.technologies_used %} -
+{% set _services_hidden = company.is_section_hidden('services') %} +{% if (www_services or www_keywords or company.services or company.competencies or company.services_offered or company.technologies_used) and (not _services_hidden or can_edit_profile or is_admin) %} +
+ {% if _services_hidden %} +
Ukryta — niewidoczna dla odwiedzających
+ {% endif %}

Usługi i kompetencje

{# Services description (text field from company edit) #} @@ -1079,8 +1104,12 @@ {% endif %} -{% if people and not (company.krs and company.data_source == 'KRS API') %} -
+{% set _board_hidden = company.is_section_hidden('board') %} +{% if people and not (company.krs and company.data_source == 'KRS API') and (not _board_hidden or can_edit_profile or is_admin) %} +
+ {% if _board_hidden %} +
Ukryta — niewidoczna dla odwiedzających
+ {% endif %}

Zarząd i Wspólnicy

{% set role_colors = {'zarzad': '#e74c3c', 'wspolnik': '#2ecc71', 'prokurent': '#f39c12', 'wlasciciel_jdg': '#9b59b6'} %} @@ -1152,8 +1181,12 @@ {% endif %} -{% if company.owner_first_name and not company.krs and not people %} -
+{% set _owner_hidden = company.is_section_hidden('owner_info') %} +{% if company.owner_first_name and not company.krs and not people and (not _owner_hidden or can_edit_profile or is_admin) %} +
+ {% if _owner_hidden %} +
Ukryta — niewidoczna dla odwiedzających
+ {% endif %}

Właściciel

@@ -1181,8 +1214,12 @@ -{% if company.ceidg_id or (company.krs and company.data_source == 'KRS API') %} -
+{% set _registry_hidden = company.is_section_hidden('registry') %} +{% if (company.ceidg_id or (company.krs and company.data_source == 'KRS API')) and (not _registry_hidden or can_edit_profile or is_admin) %} +
+ {% if _registry_hidden %} +
Ukryta — niewidoczna dla odwiedzających
+ {% endif %}

Dane z rejestrów urzędowych {% if company.ceidg_id %} @@ -1691,8 +1728,12 @@ -{% if not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id %} -
+{% set _legal_hidden = company.is_section_hidden('legal') %} +{% if not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id and (not _legal_hidden or can_edit_profile or is_admin) %} +