feat: Add section visibility toggle for company profiles
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Allow company owners, managers, and admins to hide specific profile sections from visitors. Hidden sections remain visible to authorized users with a "Ukryta" badge. Includes migration, API endpoint, edit UI tab, and conditional rendering for all 15 profile sections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
74a13507d2
commit
2c0b068428
@ -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/<int:company_id>/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()
|
||||
|
||||
@ -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"""
|
||||
|
||||
7
database/migrations/069_company_hidden_sections.sql
Normal file
7
database/migrations/069_company_hidden_sections.sql
Normal file
@ -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;
|
||||
@ -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 @@
|
||||
|
||||
<!-- O firmie - Single Description (prioritized sources) -->
|
||||
{% 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 %}
|
||||
<div class="company-section">
|
||||
{% set _about_hidden = company.is_section_hidden('about') %}
|
||||
{% if about_description and (not _about_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _about_hidden %}section-hidden{% endif %}">
|
||||
{% if _about_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">O firmie</h2>
|
||||
|
||||
<div style="background: var(--background); border-radius: var(--radius-lg); padding: var(--spacing-lg); border: 1px solid var(--border);">
|
||||
@ -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 %}
|
||||
<div class="company-section">
|
||||
{% 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) %}
|
||||
<div class="company-section {% if _services_hidden %}section-hidden{% endif %}">
|
||||
{% if _services_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Usługi i kompetencje</h2>
|
||||
|
||||
{# Services description (text field from company edit) #}
|
||||
@ -1079,8 +1104,12 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Zarząd i Wspólnicy Section (ukryte dla firm z danymi KRS API - dane są w sekcji "Dane z rejestrów urzędowych") -->
|
||||
{% if people and not (company.krs and company.data_source == 'KRS API') %}
|
||||
<div class="company-section">
|
||||
{% 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) %}
|
||||
<div class="company-section {% if _board_hidden %}section-hidden{% endif %}">
|
||||
{% if _board_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Zarząd i Wspólnicy</h2>
|
||||
|
||||
{% set role_colors = {'zarzad': '#e74c3c', 'wspolnik': '#2ecc71', 'prokurent': '#f39c12', 'wlasciciel_jdg': '#9b59b6'} %}
|
||||
@ -1152,8 +1181,12 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Właściciel JDG Section (for sole proprietorships without KRS) -->
|
||||
{% if company.owner_first_name and not company.krs and not people %}
|
||||
<div class="company-section">
|
||||
{% 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) %}
|
||||
<div class="company-section {% if _owner_hidden %}section-hidden{% endif %}">
|
||||
{% if _owner_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Właściciel</h2>
|
||||
|
||||
<div style="display: flex; align-items: center; gap: var(--spacing-lg); padding: var(--spacing-lg); background: var(--background); border-radius: var(--radius-lg); border-left: 4px solid #9b59b6;">
|
||||
@ -1181,8 +1214,12 @@
|
||||
<!-- ============================================================ -->
|
||||
<!-- DANE Z REJESTRÓW URZĘDOWYCH (CEIDG / KRS) -->
|
||||
<!-- ============================================================ -->
|
||||
{% if company.ceidg_id or (company.krs and company.data_source == 'KRS API') %}
|
||||
<div class="company-section">
|
||||
{% 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) %}
|
||||
<div class="company-section {% if _registry_hidden %}section-hidden{% endif %}">
|
||||
{% if _registry_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">
|
||||
Dane z rejestrów urzędowych
|
||||
{% if company.ceidg_id %}
|
||||
@ -1691,8 +1728,12 @@
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<!-- Legacy: Legal & Business Info - Card Based (ukryte dla firm z danymi z rejestrów - CEIDG lub KRS API) -->
|
||||
{% if not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id %}
|
||||
<div class="company-section">
|
||||
{% 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) %}
|
||||
<div class="company-section {% if _legal_hidden %}section-hidden{% endif %}">
|
||||
{% if _legal_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Informacje prawne i biznesowe</h2>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--spacing-lg);">
|
||||
@ -1995,8 +2036,12 @@
|
||||
{# Koniec warunku: not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id #}
|
||||
|
||||
<!-- Contact Information - Card Based (ukryte dla firm z danymi z rejestrów - CEIDG lub KRS API) -->
|
||||
{% if not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id %}
|
||||
<div class="company-section">
|
||||
{% set _contact_hidden = company.is_section_hidden('contact') %}
|
||||
{% if not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id and (not _contact_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _contact_hidden %}section-hidden{% endif %}">
|
||||
{% if _contact_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Dane kontaktowe</h2>
|
||||
|
||||
{% set source_names = {'website': 'Strona WWW', 'krs': 'Rejestr KRS', 'google_business': 'Google Business', 'facebook': 'Facebook', 'manual': 'Wprowadzono ręcznie', 'brave_search': 'Wyszukiwarka', 'ceidg': 'CEIDG', 'norda_biznes': 'Norda Biznes', 'website_scrape': 'Strona WWW (auto)'} %}
|
||||
@ -2232,7 +2277,12 @@
|
||||
{# Koniec warunku: not (company.krs and company.data_source == 'KRS API') and not company.ceidg_id dla sekcji "Dane kontaktowe" #}
|
||||
|
||||
<!-- Social Media Section - Always show all platforms -->
|
||||
<div class="company-section">
|
||||
{% set _social_hidden = company.is_section_hidden('social_media') %}
|
||||
{% if not _social_hidden or can_edit_profile or is_admin %}
|
||||
<div class="company-section {% if _social_hidden %}section-hidden{% endif %}">
|
||||
{% if _social_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Social Media</h2>
|
||||
|
||||
{% set platforms = ['facebook', 'instagram', 'youtube', 'linkedin', 'tiktok', 'twitter'] %}
|
||||
@ -2357,6 +2407,7 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}{# social_media visibility #}
|
||||
|
||||
{# ======================================================================
|
||||
REKOMENDACJE - TYMCZASOWO UKRYTE
|
||||
@ -2364,9 +2415,13 @@
|
||||
Data ukrycia: 2026-02-01
|
||||
Aby włączyć: zmień "False" na "True" w linii poniżej
|
||||
====================================================================== #}
|
||||
{% if False %} {# REKOMENDACJE DISABLED - zmień na True aby włączyć #}
|
||||
{% set _recommendations_hidden = company.is_section_hidden('recommendations') %}
|
||||
{% if False and (not _recommendations_hidden or can_edit_profile or is_admin) %} {# REKOMENDACJE DISABLED - zmień False na True aby włączyć #}
|
||||
<!-- Recommendations Section -->
|
||||
<div class="company-section">
|
||||
<div class="company-section {% if _recommendations_hidden %}section-hidden{% endif %}">
|
||||
{% if _recommendations_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">⭐ REKOMENDACJE {% if recommendations %}({{ recommendations|length }} rekomendacji){% endif %}</h2>
|
||||
|
||||
{% if current_user.is_authenticated %}
|
||||
@ -2695,8 +2750,13 @@
|
||||
<!-- Unified Website Section -->
|
||||
{% set primary_website = company.websites|selectattr('is_primary')|first if company.websites else none %}
|
||||
{% set primary_url = primary_website.url if primary_website else company.website %}
|
||||
{% set _website_hidden = company.is_section_hidden('website') %}
|
||||
{% if not _website_hidden or can_edit_profile or is_admin %}
|
||||
{% if primary_url and (website_analysis or company.websites) %}
|
||||
<div class="company-section">
|
||||
<div class="company-section {% if _website_hidden %}section-hidden{% endif %}">
|
||||
{% if _website_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Strona WWW</h2>
|
||||
|
||||
<!-- Website banners with per-site audit cards -->
|
||||
@ -2796,7 +2856,10 @@
|
||||
</div>
|
||||
{% elif company.website %}
|
||||
<!-- Website URL only (no analysis yet) -->
|
||||
<div class="company-section">
|
||||
<div class="company-section {% if _website_hidden %}section-hidden{% endif %}">
|
||||
{% if _website_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Strona WWW</h2>
|
||||
<div style="padding: var(--spacing-lg); background: linear-gradient(135deg, #3b82f6, #1d4ed8); border-radius: var(--radius-lg); display: flex; align-items: center; gap: var(--spacing-md);">
|
||||
<div style="width: 56px; height: 56px; border-radius: 12px; background: rgba(255,255,255,0.2); display: flex; align-items: center; justify-content: center;">
|
||||
@ -2823,7 +2886,10 @@
|
||||
</div>
|
||||
{% else %}
|
||||
<!-- No Website Section -->
|
||||
<div class="company-section">
|
||||
<div class="company-section {% if _website_hidden %}section-hidden{% endif %}">
|
||||
{% if _website_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">Strona WWW</h2>
|
||||
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--spacing-xl); text-align: center;">
|
||||
<div style="width: 80px; height: 80px; border-radius: 50%; background: linear-gradient(135deg, #f3f4f6, #e5e7eb); display: flex; align-items: center; justify-content: center; margin-bottom: var(--spacing-lg);">
|
||||
@ -2853,10 +2919,15 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}{# website visibility #}
|
||||
|
||||
<!-- SEO Metrics Section - Only show if SEO audit was performed -->
|
||||
{% if website_analysis and website_analysis.seo_audited_at and is_audit_owner %}
|
||||
<div class="company-section" id="seo-metrics">
|
||||
{% set _seo_hidden = company.is_section_hidden('seo_audit') %}
|
||||
{% if website_analysis and website_analysis.seo_audited_at and is_audit_owner and (not _seo_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _seo_hidden %}section-hidden{% endif %}" id="seo-metrics">
|
||||
{% if _seo_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">
|
||||
Analiza SEO
|
||||
<span style="font-size: var(--font-size-sm); font-weight: normal; color: var(--text-secondary); margin-left: var(--spacing-sm);">
|
||||
@ -3186,8 +3257,12 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- GBP Audit Section - Only show if GBP audit was performed -->
|
||||
{% if gbp_audit and gbp_audit.completeness_score is not none and is_audit_owner %}
|
||||
<div class="company-section" id="gbp-audit">
|
||||
{% set _gbp_hidden = company.is_section_hidden('gbp_audit') %}
|
||||
{% if gbp_audit and gbp_audit.completeness_score is not none and is_audit_owner and (not _gbp_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _gbp_hidden %}section-hidden{% endif %}" id="gbp-audit">
|
||||
{% if _gbp_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">
|
||||
Audyt Google Business Profile
|
||||
<span style="font-size: var(--font-size-sm); font-weight: normal; color: var(--text-secondary); margin-left: var(--spacing-sm);">
|
||||
@ -3399,8 +3474,12 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- Social Media Audit Section -->
|
||||
{% if social_media and social_media|length > 0 and is_audit_owner %}
|
||||
<div class="company-section" id="social-media-audit">
|
||||
{% set _social_audit_hidden = company.is_section_hidden('social_audit') %}
|
||||
{% if social_media and social_media|length > 0 and is_audit_owner and (not _social_audit_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _social_audit_hidden %}section-hidden{% endif %}" id="social-media-audit">
|
||||
{% if _social_audit_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">
|
||||
Audyt Social Media
|
||||
</h2>
|
||||
@ -3470,8 +3549,12 @@
|
||||
{% endif %}
|
||||
|
||||
<!-- IT Audit Section - Only show if IT audit was performed -->
|
||||
{% if it_audit and it_audit.overall_score is not none and is_audit_owner %}
|
||||
<div class="company-section" id="it-audit">
|
||||
{% set _it_hidden = company.is_section_hidden('it_audit') %}
|
||||
{% if it_audit and it_audit.overall_score is not none and is_audit_owner and (not _it_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _it_hidden %}section-hidden{% endif %}" id="it-audit">
|
||||
{% if _it_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">
|
||||
Audyt IT
|
||||
<span style="font-size: var(--font-size-sm); font-weight: normal; color: var(--text-secondary); margin-left: var(--spacing-sm);">
|
||||
@ -3643,8 +3726,12 @@
|
||||
{% endif %}
|
||||
|
||||
{# Company Events - UKRYTE (2026-01-11) - do przywrócenia w przyszłości
|
||||
{% if events %}
|
||||
<div class="company-section">
|
||||
{% set _news_hidden = company.is_section_hidden('news') %}
|
||||
{% if events and (not _news_hidden or can_edit_profile or is_admin) %}
|
||||
<div class="company-section {% if _news_hidden %}section-hidden{% endif %}">
|
||||
{% if _news_hidden %}
|
||||
<div class="hidden-section-badge"><i class="fas fa-eye-slash"></i> Ukryta — niewidoczna dla odwiedzających</div>
|
||||
{% endif %}
|
||||
<h2 class="section-title">
|
||||
Aktualności i wydarzenia
|
||||
<a href="{{ url_for('events', company=company.id) }}" style="float: right; font-size: var(--font-size-sm); color: var(--primary); text-decoration: none; font-weight: normal;">
|
||||
|
||||
@ -281,6 +281,57 @@
|
||||
/* Website type select */
|
||||
.website-type-select { flex: 0 0 140px; font-weight: 500; }
|
||||
|
||||
/* Visibility tab */
|
||||
.visibility-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: var(--spacing-md);
|
||||
border-bottom: 1px solid var(--border, #e0e4eb);
|
||||
}
|
||||
.visibility-row:last-child { border-bottom: none; }
|
||||
.visibility-info { flex: 1; min-width: 0; }
|
||||
.visibility-label {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary, #303030);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
.visibility-desc {
|
||||
display: block;
|
||||
font-size: var(--font-size-sm);
|
||||
color: var(--text-secondary, #464646);
|
||||
margin-top: 2px;
|
||||
}
|
||||
.visibility-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 14px;
|
||||
border: 1px solid var(--border, #e0e4eb);
|
||||
border-radius: var(--radius);
|
||||
background: #ecfdf5;
|
||||
color: #059669;
|
||||
font-size: var(--font-size-sm);
|
||||
font-family: var(--font-family);
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.visibility-toggle svg { width: 18px; height: 18px; }
|
||||
.visibility-toggle:hover { opacity: 0.8; }
|
||||
.visibility-toggle.hidden-state {
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
border-color: #fde68a;
|
||||
}
|
||||
.visibility-toggle.saving {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Website primary radio */
|
||||
.website-primary-label {
|
||||
display: flex;
|
||||
@ -362,6 +413,10 @@
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
|
||||
<span class="tab-label">Social Media</span>
|
||||
</button>
|
||||
<button type="button" class="ce-tab" data-tab="visibility">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
<span class="tab-label">Widoczność</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="{{ url_for('public.company_edit_save', company_id=company.id) }}" id="companyEditForm">
|
||||
@ -648,6 +703,38 @@
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<!-- TAB 5: Widoczność -->
|
||||
<div class="ce-tab-content" id="tab-visibility">
|
||||
<div class="ce-info-box">
|
||||
<strong>Zarządzaj widocznością sekcji profilu</strong>
|
||||
Ukryte sekcje nie będą widoczne dla odwiedzających Twój profil.
|
||||
Ty i kadra zarządzająca nadal widzicie ukryte sekcje z oznaczeniem.
|
||||
</div>
|
||||
|
||||
<div id="visibilitySections" style="margin-top: var(--spacing-lg);">
|
||||
{% for key, label, description in section_definitions %}
|
||||
<div class="visibility-row" data-section="{{ key }}">
|
||||
<div class="visibility-info">
|
||||
<span class="visibility-label">{{ label }}</span>
|
||||
<span class="visibility-desc">{{ description }}</span>
|
||||
</div>
|
||||
<button type="button" class="visibility-toggle {% if company.is_section_hidden(key) %}hidden-state{% endif %}"
|
||||
onclick="toggleSection('{{ key }}', this)" title="Kliknij aby zmienić widoczność">
|
||||
{% if company.is_section_hidden(key) %}
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
|
||||
<span>Ukryta</span>
|
||||
{% else %}
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||||
<span>Widoczna</span>
|
||||
{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div id="visibilityStatus" style="margin-top: var(--spacing-md); display: none;" class="ce-info-box"></div>
|
||||
</div>
|
||||
|
||||
<!-- Form actions -->
|
||||
<div class="ce-actions">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
@ -813,4 +900,47 @@ function toggleWebsiteBtn() {
|
||||
toggleWebsiteBtn();
|
||||
}
|
||||
})();
|
||||
|
||||
// Section visibility toggle (AJAX)
|
||||
var hiddenSections = {{ company.hidden_sections | tojson }};
|
||||
|
||||
function toggleSection(key, btn) {
|
||||
btn.classList.add('saving');
|
||||
var idx = hiddenSections.indexOf(key);
|
||||
if (idx >= 0) {
|
||||
hiddenSections.splice(idx, 1);
|
||||
} else {
|
||||
hiddenSections.push(key);
|
||||
}
|
||||
|
||||
fetch('{{ url_for("public.company_edit_visibility", company_id=company.id) }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': '{{ csrf_token() }}'
|
||||
},
|
||||
body: JSON.stringify({ hidden_sections: hiddenSections })
|
||||
})
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
btn.classList.remove('saving');
|
||||
if (data.success) {
|
||||
hiddenSections = data.hidden_sections;
|
||||
var isHidden = hiddenSections.indexOf(key) >= 0;
|
||||
btn.className = 'visibility-toggle' + (isHidden ? ' hidden-state' : '');
|
||||
btn.innerHTML = isHidden
|
||||
? '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg><span>Ukryta</span>'
|
||||
: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg><span>Widoczna</span>';
|
||||
} else {
|
||||
// Revert on error
|
||||
if (idx >= 0) hiddenSections.push(key);
|
||||
else hiddenSections.splice(hiddenSections.indexOf(key), 1);
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
btn.classList.remove('saving');
|
||||
if (idx >= 0) hiddenSections.push(key);
|
||||
else hiddenSections.splice(hiddenSections.indexOf(key), 1);
|
||||
});
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user