fix(admin): Naprawiono błędne nazwy endpointów w breadcrumbs
Zmieniono admin_dashboard i admin_zopk_dashboard na admin_zopk Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d0dda10bd7
commit
6d1f75bce5
288
docs/PLAN_ZOPK_KNOWLEDGE_BASE_IMPROVEMENTS.md
Normal file
288
docs/PLAN_ZOPK_KNOWLEDGE_BASE_IMPROVEMENTS.md
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
# Plan rozwoju bazy wiedzy ZOPK
|
||||||
|
|
||||||
|
**Data utworzenia:** 2026-01-17
|
||||||
|
**Status:** W trakcie realizacji
|
||||||
|
|
||||||
|
## Stan obecny (przed rozpoczęciem)
|
||||||
|
|
||||||
|
| Komponent | Status | Wartość |
|
||||||
|
|-----------|--------|---------|
|
||||||
|
| Artykuły scraped | ✅ | 132/163 (81%) |
|
||||||
|
| Artykuły extracted | ✅ | 120/132 (91%) |
|
||||||
|
| Chunks | ✅ | 412 |
|
||||||
|
| Fakty | ✅ | 3,414 |
|
||||||
|
| Encje | ✅ | 1,309 |
|
||||||
|
| Embeddings | ✅ | 412/412 (100%) |
|
||||||
|
| Integracja NordaGPT | ✅ | Semantic search działa |
|
||||||
|
| Automatyczny pipeline | ✅ | Cron co 1h |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Priorytet 1: Panel admina bazy wiedzy
|
||||||
|
|
||||||
|
**Status:** 🔄 W trakcie
|
||||||
|
**Szacowany czas:** 1-2 dni
|
||||||
|
|
||||||
|
### Cel
|
||||||
|
Dashboard w `/admin/zopk/knowledge` z podglądem i zarządzaniem bazą wiedzy.
|
||||||
|
|
||||||
|
### Wymagane funkcje
|
||||||
|
|
||||||
|
1. **Dashboard główny** (`/admin/zopk/knowledge`)
|
||||||
|
- Statystyki: chunks, fakty, encje, embeddings
|
||||||
|
- Wykresy: ekstrakcje w czasie, top encje
|
||||||
|
- Przyciski szybkich akcji (scraping, ekstrakcja, embeddings)
|
||||||
|
|
||||||
|
2. **Lista chunks** (`/admin/zopk/knowledge/chunks`)
|
||||||
|
- Tabela z paginacją
|
||||||
|
- Filtrowanie po artykule źródłowym
|
||||||
|
- Podgląd treści chunk
|
||||||
|
- Edycja/usunięcie chunk
|
||||||
|
- Status embeddingu (✓/✗)
|
||||||
|
|
||||||
|
3. **Lista faktów** (`/admin/zopk/knowledge/facts`)
|
||||||
|
- Tabela z paginacją
|
||||||
|
- Filtrowanie po typie faktu (financial, date, decision, etc.)
|
||||||
|
- Weryfikacja faktu (✓ zweryfikowany / ✗ błędny)
|
||||||
|
- Edycja faktu
|
||||||
|
- Link do źródłowego artykułu
|
||||||
|
|
||||||
|
4. **Lista encji** (`/admin/zopk/knowledge/entities`)
|
||||||
|
- Tabela z paginacją
|
||||||
|
- Filtrowanie po typie (company, person, place, project)
|
||||||
|
- Liczba wzmianek
|
||||||
|
- Możliwość łączenia duplikatów (Priorytet 4)
|
||||||
|
- Edycja opisu encji
|
||||||
|
|
||||||
|
5. **Szczegóły artykułu** (`/admin/zopk/knowledge/article/<id>`)
|
||||||
|
- Pełna treść scraped
|
||||||
|
- Lista wyekstraktowanych chunks
|
||||||
|
- Lista wyekstraktowanych faktów
|
||||||
|
- Lista encji
|
||||||
|
- Możliwość re-ekstrakcji
|
||||||
|
|
||||||
|
### Pliki do utworzenia
|
||||||
|
- `templates/admin/zopk_knowledge_dashboard.html`
|
||||||
|
- `templates/admin/zopk_knowledge_chunks.html`
|
||||||
|
- `templates/admin/zopk_knowledge_facts.html`
|
||||||
|
- `templates/admin/zopk_knowledge_entities.html`
|
||||||
|
|
||||||
|
### Pliki do modyfikacji
|
||||||
|
- `app.py` - nowe endpointy
|
||||||
|
- `zopk_knowledge_service.py` - metody CRUD
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Priorytet 2: Poprawa jakości odpowiedzi
|
||||||
|
|
||||||
|
**Status:** ⏳ Oczekuje
|
||||||
|
**Szacowany czas:** 1 dzień
|
||||||
|
|
||||||
|
### Cel
|
||||||
|
Lepsze formatowanie odpowiedzi NordaGPT z linkami do źródeł.
|
||||||
|
|
||||||
|
### Wymagane zmiany
|
||||||
|
|
||||||
|
1. **Linki do źródeł**
|
||||||
|
- Zamiast: "Według Google News z 31 grudnia 2025..."
|
||||||
|
- Ma być: "Według [trojmiasto.pl](https://trojmiasto.pl/...) z 31 grudnia 2025..."
|
||||||
|
|
||||||
|
2. **Formatowanie odpowiedzi**
|
||||||
|
- Nagłówki dla sekcji
|
||||||
|
- Listy wypunktowane dla wielu faktów
|
||||||
|
- Wyróżnienie kluczowych danych (pogrubienie)
|
||||||
|
|
||||||
|
3. **Pewność odpowiedzi**
|
||||||
|
- Gdy brak danych w bazie: "Nie mam informacji na ten temat w bazie wiedzy ZOPK"
|
||||||
|
- Gdy dane niepewne: "Według dostępnych informacji (pewność: średnia)..."
|
||||||
|
|
||||||
|
4. **Źródła na końcu odpowiedzi**
|
||||||
|
```
|
||||||
|
📚 Źródła:
|
||||||
|
- [trojmiasto.pl] Kongsberg zainwestuje na Pomorzu (2025-11-23)
|
||||||
|
- [defence24.pl] Norweska fabryka w Rumi (2025-11-25)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pliki do modyfikacji
|
||||||
|
- `nordabiz_chat.py` - metoda `_get_zopk_knowledge_context()`
|
||||||
|
- `nordabiz_chat.py` - system prompt dla ZOPK
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Priorytet 3: Timeline ZOPK na stronie /zopk
|
||||||
|
|
||||||
|
**Status:** ⏳ Oczekuje
|
||||||
|
**Szacowany czas:** 2-3 dni
|
||||||
|
|
||||||
|
### Cel
|
||||||
|
Wizualna oś czasu projektu ZOPK pokazująca kamienie milowe.
|
||||||
|
|
||||||
|
### Wymagane funkcje
|
||||||
|
|
||||||
|
1. **Tabela `zopk_milestones`**
|
||||||
|
```sql
|
||||||
|
CREATE TABLE zopk_milestones (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
milestone_type VARCHAR(50), -- announcement, decision, construction, completion
|
||||||
|
target_date DATE,
|
||||||
|
actual_date DATE,
|
||||||
|
status VARCHAR(20), -- planned, in_progress, completed, delayed
|
||||||
|
source_news_id INTEGER REFERENCES zopk_news(id),
|
||||||
|
source_fact_id INTEGER REFERENCES zopk_knowledge_facts(id),
|
||||||
|
icon VARCHAR(50),
|
||||||
|
color VARCHAR(7),
|
||||||
|
is_featured BOOLEAN DEFAULT FALSE,
|
||||||
|
display_order INTEGER,
|
||||||
|
created_at TIMESTAMP DEFAULT NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Automatyczne tworzenie milestones**
|
||||||
|
- Ekstrakcja dat z faktów (np. "budowa rozpocznie się w 2027")
|
||||||
|
- Kategoryzacja: announcement, decision, construction_start, completion
|
||||||
|
- Przypisanie do projektów (Kongsberg, PEJ, Baltic Power, Via Pomerania)
|
||||||
|
|
||||||
|
3. **UI Timeline na /zopk**
|
||||||
|
- Pionowa oś czasu (scrollowalna)
|
||||||
|
- Kamienie milowe z ikonami
|
||||||
|
- Kolory: zielony (completed), niebieski (in_progress), szary (planned)
|
||||||
|
- Kliknięcie → szczegóły z linkiem do źródła
|
||||||
|
|
||||||
|
4. **Panel admina dla milestones**
|
||||||
|
- `/admin/zopk/milestones`
|
||||||
|
- Dodawanie/edycja/usuwanie
|
||||||
|
- Zmiana kolejności (drag & drop)
|
||||||
|
|
||||||
|
### Pliki do utworzenia
|
||||||
|
- `database/migrations/016_zopk_milestones.sql`
|
||||||
|
- `templates/admin/zopk_milestones.html`
|
||||||
|
|
||||||
|
### Pliki do modyfikacji
|
||||||
|
- `database.py` - model ZOPKMilestone
|
||||||
|
- `app.py` - endpointy
|
||||||
|
- `templates/zopk.html` - sekcja timeline
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Priorytet 4: Łączenie duplikatów encji
|
||||||
|
|
||||||
|
**Status:** ⏳ Oczekuje
|
||||||
|
**Szacowany czas:** 1 dzień
|
||||||
|
|
||||||
|
### Cel
|
||||||
|
Automatyczne i ręczne łączenie zduplikowanych encji.
|
||||||
|
|
||||||
|
### Znane duplikaty do połączenia
|
||||||
|
|
||||||
|
| Encja główna | Duplikaty | Łączna liczba wzmianek |
|
||||||
|
|--------------|-----------|------------------------|
|
||||||
|
| Morze Bałtyckie | Bałtyk | 58 + 53 = 111 |
|
||||||
|
| Polskie Elektrownie Jądrowe | PEJ | ? |
|
||||||
|
| Władysław Kosiniak-Kamysz | Kosiniak-Kamysz, Wicepremier | ? |
|
||||||
|
| Kongsberg Defence & Aerospace | Kongsberg | ? |
|
||||||
|
|
||||||
|
### Wymagane funkcje
|
||||||
|
|
||||||
|
1. **Automatyczne wykrywanie duplikatów**
|
||||||
|
- Fuzzy matching nazw (pg_trgm similarity > 0.7)
|
||||||
|
- Porównanie typów encji
|
||||||
|
- Sugestie do zatwierdzenia przez admina
|
||||||
|
|
||||||
|
2. **Panel łączenia** (`/admin/zopk/knowledge/entities/merge`)
|
||||||
|
- Lista sugerowanych duplikatów
|
||||||
|
- Wybór encji głównej
|
||||||
|
- Przycisk "Połącz" → aktualizacja wszystkich referencji
|
||||||
|
|
||||||
|
3. **Aliasy encji**
|
||||||
|
- Tabela `zopk_entity_aliases`
|
||||||
|
- Encja "Polskie Elektrownie Jądrowe" ma alias "PEJ"
|
||||||
|
- Wyszukiwanie uwzględnia aliasy
|
||||||
|
|
||||||
|
### Pliki do utworzenia
|
||||||
|
- `database/migrations/017_zopk_entity_aliases.sql`
|
||||||
|
|
||||||
|
### Pliki do modyfikacji
|
||||||
|
- `database.py` - model ZOPKEntityAlias
|
||||||
|
- `zopk_knowledge_service.py` - metody merge_entities(), get_entity_duplicates()
|
||||||
|
- `app.py` - endpointy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Priorytet 5: Graf relacji encji
|
||||||
|
|
||||||
|
**Status:** ⏳ Oczekuje
|
||||||
|
**Szacowany czas:** 2-3 dni
|
||||||
|
|
||||||
|
### Cel
|
||||||
|
Wizualizacja powiązań między encjami (podobna do Mapy Powiązań firm).
|
||||||
|
|
||||||
|
### Typy relacji do ekstrakcji
|
||||||
|
|
||||||
|
| Relacja | Przykład |
|
||||||
|
|---------|----------|
|
||||||
|
| `invests_in` | Kongsberg → Rumia Invest Park |
|
||||||
|
| `manages` | MON → ZOPK |
|
||||||
|
| `builds` | PEJ → Elektrownia Lubiatowo |
|
||||||
|
| `located_in` | Baltic Power → Morze Bałtyckie |
|
||||||
|
| `partners_with` | Westinghouse → Bechtel |
|
||||||
|
| `employs` | Kongsberg → 500 osób |
|
||||||
|
|
||||||
|
### Wymagane funkcje
|
||||||
|
|
||||||
|
1. **Ekstrakcja relacji z faktów**
|
||||||
|
- Analiza AI faktów typu: "Kongsberg zainwestuje w Rumi"
|
||||||
|
- Prompt: "Wyodrębnij relacje: subject → predicate → object"
|
||||||
|
|
||||||
|
2. **Wypełnienie tabeli `zopk_knowledge_relations`**
|
||||||
|
- Tabela już istnieje (obecnie pusta)
|
||||||
|
- Kolumny: source_entity_id, target_entity_id, relation_type, confidence_score
|
||||||
|
|
||||||
|
3. **Wizualizacja grafu** (`/zopk/graph` lub modal na /zopk)
|
||||||
|
- Użycie D3.js lub vis.js (jak Mapa Powiązań)
|
||||||
|
- Węzły = encje (kolorowane po typie)
|
||||||
|
- Krawędzie = relacje (etykiety)
|
||||||
|
- Filtrowanie po typie relacji
|
||||||
|
|
||||||
|
4. **Panel admina** (`/admin/zopk/knowledge/relations`)
|
||||||
|
- Lista relacji z paginacją
|
||||||
|
- Dodawanie/edycja/usuwanie
|
||||||
|
- Weryfikacja (✓/✗)
|
||||||
|
|
||||||
|
### Pliki do modyfikacji
|
||||||
|
- `zopk_knowledge_service.py` - metoda extract_relations()
|
||||||
|
- `app.py` - endpointy
|
||||||
|
- `templates/zopk.html` - sekcja graf lub modal
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Harmonogram realizacji
|
||||||
|
|
||||||
|
| Priorytet | Zadanie | Szacowany czas | Status |
|
||||||
|
|-----------|---------|----------------|--------|
|
||||||
|
| 1 | Panel admina bazy wiedzy | 1-2 dni | 🔄 W trakcie |
|
||||||
|
| 2 | Poprawa jakości odpowiedzi | 1 dzień | ⏳ Oczekuje |
|
||||||
|
| 3 | Timeline ZOPK | 2-3 dni | ⏳ Oczekuje |
|
||||||
|
| 4 | Łączenie duplikatów encji | 1 dzień | ⏳ Oczekuje |
|
||||||
|
| 5 | Graf relacji encji | 2-3 dni | ⏳ Oczekuje |
|
||||||
|
|
||||||
|
**Łączny szacowany czas:** 7-10 dni
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notatki techniczne
|
||||||
|
|
||||||
|
### Istniejące tabele bazy wiedzy
|
||||||
|
- `zopk_knowledge_chunks` - fragmenty tekstu z embeddingami
|
||||||
|
- `zopk_knowledge_facts` - wyekstraktowane fakty
|
||||||
|
- `zopk_knowledge_entities` - rozpoznane encje
|
||||||
|
- `zopk_knowledge_relations` - relacje między encjami (pusta)
|
||||||
|
|
||||||
|
### Istniejące serwisy
|
||||||
|
- `zopk_knowledge_service.py` - ekstrakcja i wyszukiwanie
|
||||||
|
- `zopk_content_scraper.py` - scraping treści artykułów
|
||||||
|
|
||||||
|
### Istniejący pipeline (cron)
|
||||||
|
- `scripts/zopk_knowledge_pipeline.py` - uruchamiany co godzinę
|
||||||
|
- Logi: `/var/log/nordabiznes/knowledge_pipeline.log`
|
||||||
91
scripts/run_migration.py
Normal file
91
scripts/run_migration.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Run SQL migrations using DATABASE_URL from .env
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python scripts/run_migration.py database/migrations/016_zopk_milestones.sql
|
||||||
|
python scripts/run_migration.py database/migrations/*.sql # Run all
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Add parent directory to path for imports
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
def load_env():
|
||||||
|
"""Load .env file from project root"""
|
||||||
|
env_path = Path(__file__).parent.parent / '.env'
|
||||||
|
if env_path.exists():
|
||||||
|
with open(env_path, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#') and '=' in line:
|
||||||
|
key, value = line.split('=', 1)
|
||||||
|
os.environ[key] = value.strip()
|
||||||
|
|
||||||
|
if not os.environ.get('DATABASE_URL'):
|
||||||
|
print("ERROR: DATABASE_URL not found in .env")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def run_migration(sql_file: str) -> bool:
|
||||||
|
"""Run a single SQL migration file"""
|
||||||
|
from sqlalchemy import create_engine, text
|
||||||
|
|
||||||
|
if not os.path.exists(sql_file):
|
||||||
|
print(f"ERROR: File not found: {sql_file}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print(f"Running migration: {sql_file}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
engine = create_engine(os.environ['DATABASE_URL'])
|
||||||
|
with engine.connect() as conn:
|
||||||
|
with open(sql_file, 'r') as f:
|
||||||
|
sql = f.read()
|
||||||
|
conn.execute(text(sql))
|
||||||
|
conn.commit()
|
||||||
|
print(f"✅ {sql_file} - SUCCESS")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ {sql_file} - FAILED: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
load_env()
|
||||||
|
|
||||||
|
# Handle glob patterns
|
||||||
|
sql_files = []
|
||||||
|
for arg in sys.argv[1:]:
|
||||||
|
if '*' in arg:
|
||||||
|
sql_files.extend(sorted(glob.glob(arg)))
|
||||||
|
else:
|
||||||
|
sql_files.append(arg)
|
||||||
|
|
||||||
|
if not sql_files:
|
||||||
|
print("No migration files found")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f"Found {len(sql_files)} migration(s) to run\n")
|
||||||
|
|
||||||
|
success = 0
|
||||||
|
failed = 0
|
||||||
|
|
||||||
|
for sql_file in sql_files:
|
||||||
|
if run_migration(sql_file):
|
||||||
|
success += 1
|
||||||
|
else:
|
||||||
|
failed += 1
|
||||||
|
|
||||||
|
print(f"\n{'='*50}")
|
||||||
|
print(f"Results: {success} success, {failed} failed")
|
||||||
|
|
||||||
|
sys.exit(0 if failed == 0 else 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@ -323,9 +323,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<a href="{{ url_for('admin_dashboard') }}">Panel Admina</a>
|
<a href="{{ url_for('admin_zopk') }}">Panel Admina</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_dashboard') }}">ZOP Kaszubia</a>
|
<a href="{{ url_for('admin_zopk') }}">ZOP Kaszubia</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
|
<a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
|
|||||||
@ -277,9 +277,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<a href="{{ url_for('admin_dashboard') }}">Panel Admina</a>
|
<a href="{{ url_for('admin_zopk') }}">Panel Admina</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_dashboard') }}">ZOP Kaszubia</a>
|
<a href="{{ url_for('admin_zopk') }}">ZOP Kaszubia</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<span>Baza Wiedzy</span>
|
<span>Baza Wiedzy</span>
|
||||||
</div>
|
</div>
|
||||||
@ -360,7 +360,7 @@
|
|||||||
<div class="quick-link-desc">Wektory dla chunków bez embeddingów</div>
|
<div class="quick-link-desc">Wektory dla chunków bez embeddingów</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ url_for('admin_zopk_dashboard') }}" class="quick-link">
|
<a href="{{ url_for('admin_zopk') }}" class="quick-link">
|
||||||
<div class="quick-link-icon">📊</div>
|
<div class="quick-link-icon">📊</div>
|
||||||
<div class="quick-link-text">
|
<div class="quick-link-text">
|
||||||
<div class="quick-link-title">Dashboard ZOPK</div>
|
<div class="quick-link-title">Dashboard ZOPK</div>
|
||||||
|
|||||||
@ -253,9 +253,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<a href="{{ url_for('admin_dashboard') }}">Panel Admina</a>
|
<a href="{{ url_for('admin_zopk') }}">Panel Admina</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_dashboard') }}">ZOP Kaszubia</a>
|
<a href="{{ url_for('admin_zopk') }}">ZOP Kaszubia</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
|
<a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
|
|||||||
@ -243,9 +243,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<a href="{{ url_for('admin_dashboard') }}">Panel Admina</a>
|
<a href="{{ url_for('admin_zopk') }}">Panel Admina</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_dashboard') }}">ZOP Kaszubia</a>
|
<a href="{{ url_for('admin_zopk') }}">ZOP Kaszubia</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
<a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
|
<a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
|
||||||
<span>›</span>
|
<span>›</span>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user