diff --git a/.gitignore b/.gitignore index 0bad889..23bc2e0 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,27 @@ build/ #data data/ +# Local database backups / restore points. +# These contain REAL production data (users, password hashes, player feedback). +# They must never leave the host — keep them on disk only. +backups/ +restore-points/ + +# Generated documents (regenerate with documentatie/convert_manual.sh) +documentatie/*.docx + +# Screenshots are shipped with the app under app/static/help/screenshots/. +# The copy in documentatie/ is the editing source; ignore it to avoid committing +# ~4 MB twice. +documentatie/screenshots/ + +# Local notes / scratch files +inportant info .txt +important info.txt + +# Legacy pre-sanitization archive (also covered as docs/old_code_documentation/) +old_code_documentation/ + # Local archive / restore-point snapshots. # Kept on disk for reference (see docs/SANITIZATION-REVIEW.md) but deliberately # NOT tracked: docs/legacy code/ is a full pre-sanitization repo snapshot and diff --git a/app/blueprints/main.py b/app/blueprints/main.py index 7d9fd45..784655a 100644 --- a/app/blueprints/main.py +++ b/app/blueprints/main.py @@ -89,6 +89,50 @@ def dashboard(): ) +@main_bp.route('/help') +@login_required +def help_page(): + """User manual / help page. + + The manual lives at ``app/static/help/_manual_body.html`` — a pre-rendered + HTML fragment generated from ``documentatie/Manual-Utilizare-DigiServer.md`` + with ``pandoc`` (see ``documentatie/convert_help_page.sh``). + + It is shipped as a static asset rather than parsed at runtime on purpose: + it keeps the runtime free of a Markdown dependency and means the help page + renders identically regardless of what is installed in the container. + """ + import os + import re + + base_dir = os.path.dirname(os.path.dirname(__file__)) # -> app/ + manual_path = os.path.join(base_dir, 'static', 'help', '_manual_body.html') + + manual_html = '' + toc = [] + try: + with open(manual_path, 'r', encoding='utf-8') as f: + manual_html = f.read() + + # Build the sidebar from the level-2 headings (`

`), which + # is exactly the printed table of contents of the manual. Nested

+ # entries would make the sidebar unwieldy, so they are left out. + for anchor, title in re.findall( + r'

]*>(.*?)

', manual_html, re.DOTALL + ): + clean = re.sub(r'<[^>]+>', '', title).strip() + if clean: + toc.append({'anchor': anchor, 'title': clean}) + except FileNotFoundError: + manual_html = ( + '

Manual indisponibil

' + '

Fișierul manualului nu a fost găsit. ' + 'Rulați documentatie/convert_help_page.sh pentru a-l genera.

' + ) + + return render_template('help.html', manual_html=manual_html, toc=toc) + + @main_bp.route('/health') def health(): """Health check endpoint""" diff --git a/app/static/help/_manual_body.html b/app/static/help/_manual_body.html new file mode 100644 index 0000000..4219093 --- /dev/null +++ b/app/static/help/_manual_body.html @@ -0,0 +1,1056 @@ +

Manual de Utilizare – DigiServer v2

+

Versiune document: 1.0 Data: Septembrie 2026 Aplicație: DigiServer v2 – Sistem de management al conținutului pentru ecrane digitale (Digital Signage)

+
+

Cuprins

+
    +
  1. Introducere
  2. +
  3. Autentificare în aplicație
  4. +
  5. Dashboard (Panoul principal)
  6. +
  7. Biblioteca de Media
  8. +
  9. Adăugarea de Media în sistem
  10. +
  11. Managementul Playlist-urilor
  12. +
  13. Adăugarea de conținut într-un Playlist
  14. +
  15. Ștergerea unui fișier din Playlist
  16. +
  17. Reordonarea conținutului în Playlist
  18. +
  19. Managementul Playerelelor
  20. +
  21. Vizualizarea fișierelor editate pe Player (funcție avansată)
  22. +
  23. Administrare
  24. +
  25. Întrebări frecvente și depanare
  26. +
+
+

1. Introducere

+

DigiServer v2 este o aplicație web folosită pentru a gestiona conținutul afișat pe ecranele digitale (playere). Cu ajutorul ei puteți:

+ +

Structura generală a aplicației

+
┌─────────────────────────────────────────────────────────┐
+│  UTILIZATOR (browser)                                   │
+│         │                                               │
+│         ▼                                               │
+│  DigiServer (interfață web)                             │
+│         │                                               │
+│         ├──► Biblioteca de Media (fișiere)              │
+│         ├──► Playlist-uri (liste de redare)             │
+│         └──► Playere (ecrane fizice)                    │
+└─────────────────────────────────────────────────────────┘
+

Roluri de utilizator

+ ++++ + + + + + + + + + + + + + + + + + + + + +
RolDrepturi
AdminAcces complet: utilizatori, setări sistem, HTTPS, playere, conținut
EditorPoate încărca conținut, crea playlist-uri și edita playere
UtilizatorPoate vizualiza conținut și playlists
+
+

2. Autentificare în aplicație

+

2.1. Deschiderea aplicației

+

Deschideți un browser (Chrome, Firefox sau Edge) și accesați una dintre adresele:

+ +
+

Notă: Dacă browserul afișează un avertisment de certificat („Conexiunea nu este privată”), acest lucru este normal pentru rețeaua internă. Apăsați „Avansat” → „Continuă către…“. Administratorul de rețea poate instala certificatul intern pentru a elimina acest avertisment.

+
+

2.2. Ecranul de autentificare

+
+Ecranul de autentificare + +
+

Figura 1 – Ecranul de login

+

Introduceți:

+
    +
  1. Nume utilizator (username)
  2. +
  3. Parolă
  4. +
  5. Apăsați butonul „Autentificare” / „Login”
  6. +
+
+

Important: Dacă ați uitat parola, contactați administratorul sistemului. Parola poate fi schimbată ulterior din meniul de cont.

+
+

2.3. Schimbarea parolei

+

După prima autentificare, se recomandă schimbarea parolei:

+
    +
  1. Accesați meniul de utilizator (colț dreapta-sus)
  2. +
  3. Selectați „Schimbă parola” / „Change Password”
  4. +
  5. Introduceți parola veche, apoi parola nouă (de două ori)
  6. +
  7. Confirmați
  8. +
+
+Formularul de schimbare a parolei + +
+

Figura 2 – Schimbarea parolei

+
+

3. Dashboard (Panoul principal)

+

După autentificare, sunteți redirecționat către Dashboard – pagina principală a aplicației.

+
+Dashboard după autentificare + +
+

Figura 3 – Dashboard-ul principal

+

3.1. Elementele Dashboard-ului

+

Dashboard-ul oferă o imagine de ansamblu asupra sistemului:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ElementDescriere
StatisticiNumăr de playere, playlist-uri, fișiere media
Stare playereCare playere sunt online / offline
Acțiuni rapideButoane pentru adăugare rapidă de conținut
Meniu de navigareAcces către toate secțiunile aplicației
+

3.2. Meniul principal de navigare

+

Meniul din partea stângă (sau de sus) conține:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SecțiuneFuncție
DashboardPagina principală cu statistici
Media Library (Biblioteca de Media)Toate fișierele încărcate
PlaylistsGestionarea listelor de redare
Players (Playere)Gestionarea ecranelor
AdminSetări de sistem (doar pentru administratori)
+

3.3. Cum citiți statisticile

+
    +
  1. Playere (Players): Numărul total de ecrane configurate
  2. +
  3. Playlist-uri: Numărul de liste de redare existente
  4. +
  5. Media: Numărul total de fișiere încărcate
  6. +
+

Apăsați pe orice statistică pentru a accesa secțiunea corespunzătoare.

+
+

4. Biblioteca de Media

+

Biblioteca de Media conține toate fișierele încărcate în sistem: imagini, videoclipuri, documente PDF și prezentări.

+
+Biblioteca de Media + +
+

Figura 4 – Bibliotecac de Media

+

4.1. Accesarea bibliotecii

+

Din meniul principal, selectați „Media Library” sau accesați direct /media-library.

+

4.2. Informații afișate pentru fiecare fișier

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Coloană / ElementSemnificație
Nume fișierNumele original al fișierului încărcat
TipImagine / Video / PDF / Prezentare
DimensiuneMărimea fișierului
Data încărcăriiCând a fost adăugat în sistem
PrevizualizareMiniatură pentru imagini și videoclipuri
+

4.3. Filtrarea și căutarea

+ +

4.4. Ștergerea unui fișier din bibliotecă

+
+

Atenție: Ștergerea din bibliotecă este permanentă. Dacă fișierul este folosit într-un playlist, acesta va apărea ca lipsă.

+
+
    +
  1. Găsiți fișierul în listă
  2. +
  3. Apăsați butonul Ștergere (iconiță coș de gunoi / X)
  4. +
  5. Confirmați ștergerea
  6. +
+
+Accesarea opțiunii de ștergere + +
+

Figura 5 – Accesarea butonului de ștergere

+
+Confirmarea ștergerii unui fișier + +
+

Figura 6 – Confirmarea ștergerii

+
+

5. Adăugarea de Media în sistem

+

5.1. Deschiderea formularului de încărcare

+

Din meniul principal selectați „Upload Media” sau accesați pagina de încărcare.

+
+Formularul de încărcare media + +
+

Figura 7 – Pagina de încărcare media

+

5.2. Tipuri de fișiere acceptate

+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategorieFormate acceptate
ImaginiPNG, JPG, JPEG, GIF, BMP
VideoMP4, AVI, MKV, MOV, WEBM
DocumentePDF
PrezentăriPPT, PPTX
+

5.3. Pașii pentru încărcare

+
    +
  1. Apăsați zona de selecție sau butonul „Alege fișier”
  2. +
  3. Selectați fișierul (sau mai multe fișiere) din calculator
  4. +
  5. Așteptați finalizarea încărcării
  6. +
  7. Veți primi confirmarea că fișierul a fost adăugat
  8. +
+
+Selectarea fișierului de încărcat + +
+

Figura 8 – Selectarea fișierului

+

5.4. Confirmarea încărcării

+

După finalizarea încărcării, aplicația afișează un banner verde de confirmare cu mesajul „Successfully uploaded”, care indică playlist-ul în care a fost adăugat fișierul.

+
+Banner de confirmare a încărcării + +
+

Figura 9 – Bannerul „Successfully uploaded”

+ +

Pe lângă fișiere, puteți adăuga și adrese web care să fie afișate pe ecrane.

+
    +
  1. Selectați opțiunea „Add Web Link” / „Adaugă link web”
  2. +
  3. Introduceți URL-ul complet (ex: https://www.exemplu.ro)
  4. +
  5. Dați un titlu pentru link
  6. +
  7. Salvați
  8. +
+
+Adăugarea unui link web + +
+

Figura 10 – Adăugarea unui link web

+
+

Sfat: Limita maximă pentru un fișier este de 2 GB. Pentru fișiere foarte mari, împărțiți-le sau contactați administratorul.

+
+
+

6. Managementul Playlist-urilor

+

Un playlist este o listă ordonată de conținut care se redă pe un player. Puteți avea mai multe playlist-uri pentru diferite ecrane sau situații.

+

6.1. Vizualizarea playlist-urilor

+

Din meniul principal selectați „Playlists”.

+
+Lista playlist-urilor + +
+

Figura 9 – Lista playlist-urilor

+

Aici vedeți toate playlist-urile existente, cu:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ElementDescriere
NumeDenumirea playlist-ului
Nr. elementeCâte fișiere conține
Player atribuitPe ce ecran se redă
AcțiuniEditare, gestionare conținut, ștergere
+

6.2. Crearea unui playlist nou

+
    +
  1. Apăsați butonul „Creează Playlist” / „Create Playlist”
  2. +
  3. Introduceți numele playlist-ului (ex: „Ecran Recepție”)
  4. +
  5. Opțional: adăugați o descriere
  6. +
  7. Apăsați „Salvează”
  8. +
+
+Crearea unui playlist nou + +
+

Figura 10 – Crearea unui playlist

+

6.3. Gestionarea conținutului unui playlist

+

Pentru a vedea și edita conținutul unui playlist:

+
    +
  1. Găsiți playlist-ul în listă
  2. +
  3. Apăsați butonul „Gestionare” / „Manage” (sau numele playlist-ului)
  4. +
  5. Se deschide pagina de management a conținutului
  6. +
+
+Pagina de management a playlist-ului + +
+

Figura 12 – Accesarea managementului

+
+Conținutul playlist-ului + +
+

Figura 13 – Conținutul playlist-ului

+

6.4. Ștergerea unui playlist

+
    +
  1. Găsiți playlist-ul în listă
  2. +
  3. Apăsați butonul Ștergere
  4. +
  5. Confirmați
  6. +
+
+

Atenție: Ștergerea unui playlist nu șterge fișierele media. Doar lista de redare este eliminată.

+
+
+

7. Adăugarea de conținut într-un Playlist

+

7.1. Pași pentru adăugare

+
    +
  1. Deschideți playlist-ul (secțiunea Management)
  2. +
  3. Apăsați „Adaugă conținut” / „Add Content”
  4. +
  5. Se afișează lista cu toate fișierele disponibile
  6. +
  7. Bifați fișierele dorite (puteți selecta mai multe)
  8. +
  9. Apăsați „Adaugă”
  10. +
+
+Selectarea conținutului de adăugat + +
+

Figura 12 – Adăugarea conținutului

+

7.2. Opțiuni per element

+

După adăugare, pentru fiecare element puteți configura:

+ + + + + + + + + + + + + + + + + + + + + +
OpțiuneDescriere
Durată afișareCât timp se afișează elementul (secunde)
Fără sunet (Muted)Dezactivează sunetul pentru acel element
Editare permisăPermite player-ului să editeze fișierul local
+
+Opțiunile fiecărui element + +
+

Figura 13 – Opțiunile elementelor

+ +
    +
  1. În pagina de management a playlist-ului, apăsați „Adaugă link web”
  2. +
  3. Introduceți URL-ul și titlul
  4. +
  5. Salvați – link-ul apare în listă ca orice alt element
  6. +
+
+

8. Ștergerea unui fișier din Playlist

+

8.1. Ștergerea unui singur element

+
    +
  1. Deschideți playlist-ul în modul Management
  2. +
  3. Găsiți elementul dorit în listă
  4. +
  5. Apăsați iconița Ștergere (X / coș de gunoi) de pe rândul respectiv
  6. +
  7. Confirmați dacă vi se cere
  8. +
+
+Ștergerea unui element din playlist + +
+

Figura 14 – Ștergerea unui element

+
+

Important: Ștergerea din playlist nu șterge fișierul din Biblioteca de Media. Fișierul rămâne disponibil pentru alte playlist-uri.

+
+

8.2. Ștergerea mai multor elemente simultan (Bulk Remove)

+

Pentru a șterge mai multe fișiere dintr-un playlist:

+
    +
  1. În pagina de management, bifați elementele dorite
  2. +
  3. Apăsați butonul „Șterge selectate” / „Bulk Remove”
  4. +
  5. Confirmați operațiunea
  6. +
+
+Ștergerea în masă + +
+

Figura 15 – Ștergerea în masă

+

8.3. Diferența: ștergere playlist vs. ștergere fișier

+ ++++ + + + + + + + + + + + + + + + + + + + + +
AcțiuneEfect
Ștergere element din playlistElementul dispare din listă; fișierul rămâne în bibliotecă
Ștergere fișier din bibliotecăFișierul dispare complet; apare ca lipsă în toate playlist-urile
Ștergere playlistLista dispare; toate fișierele rămân în bibliotecă
+
+

9. Reordonarea conținutului în Playlist

+

Ordinea elementelor determină ordinea de afișare pe ecran.

+

9.1. Reordonare prin tragere (drag & drop)

+
    +
  1. Deschideți playlist-ul în modul Management
  2. +
  3. Apăsați și țineți apăsat pe iconița de mâner (⋮⋮) din dreptul unui element
  4. +
  5. Trageți elementul în poziția dorită
  6. +
  7. Ordinea se salvează automat
  8. +
+
+Reordonarea elementelor + +
+

Figura 16 – Reordonarea elementelor

+

9.2. Verificarea ordinii

+

După reordonare, verificați că numerele de ordine (1, 2, 3…) corespund intenției dvs.

+
+

10. Managementul Playerelelor

+

Playerele sunt ecranele fizice care afișează conținutul.

+

10.1. Lista playerelor

+

Din meniul principal selectați „Players”.

+
+Lista playerelor + +
+

Figura 17 – Lista playerelor

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ColoanăSemnificație
NumeDenumirea player-ului
LocațieUnde este amplasat ecranul
Adresă IPAdresa de rețea a player-ului
Playlist atribuitCe conținut redă
StareOnline / Offline / Stare deploy
+

10.2. Adăugarea unui player nou

+
    +
  1. Apăsați „Adaugă Player” / „Add Player”
  2. +
  3. Completați: +
  4. +
  5. Salvați
  6. +
+
+Adăugarea unui player + +
+

Figura 20 – Formularul de adăugare player

+
+Player completat + +
+

Figura 21 – Formularul completat

+

10.3. Editarea unui player

+
    +
  1. Apăsați „Editare” / „Edit” pe rândul player-ului
  2. +
  3. Modificați câmpurile dorite
  4. +
  5. Salvați
  6. +
+

10.4. Atribuirea unui playlist unui player

+
    +
  1. În lista de playere, găsiți player-ul dorit
  2. +
  3. Apăsați „Atribuie Playlist” / „Assign Playlist”
  4. +
  5. Selectați playlist-ul din listă
  6. +
  7. Confirmați
  8. +
+
+Atribuirea unui playlist + +
+

Figura 22 – Selectarea playlist-ului

+
+Atribuire confirmată + +
+

Figura 23 – Confirmarea atribuirii

+
+

Notă: După atribuire, player-ul va prelua noul conținut la următoarea sincronizare.

+
+

10.5. Starea de deployment

+

Fiecare player are o stare de deployment care arată dacă conținutul a fost trimis cu succes:

+ + + + + + + + + + + + + + + + + + + + + +
StareSemnificație
SuccesConținutul a fost trimis cu succes
În așteptareSe așteaptă sincronizarea
EroareTrimiterea a eșuat – verificați mesajul
+

10.6. Regenerarea cheii de autentificare

+

Dacă un player nu se mai poate conecta:

+
    +
  1. Găsiți player-ul în listă
  2. +
  3. Apăsați „Regenerează autentificare” / „Regenerate Auth”
  4. +
  5. Confirmați – se va genera o cheie nouă
  6. +
+
+

Atenție: Va trebui să actualizați cheia și pe player-ul fizic.

+
+
+

11. Vizualizarea fișierelor editate pe Player (funcție avansată)

+

Această funcție vă permite să vedeți ce versiuni editate ale fișierelor există pe fiecare player. Este utilă când un player modifică local fișierele (de exemplu, suprapune informații, ajustează rezoluția etc.).

+

11.1. Accesarea raportului de fișiere editate

+
    +
  1. Accesați secțiunea Players
  2. +
  3. Găsiți player-ul dorit
  4. +
  5. Apăsați „Fișiere editate” / „Edited Media”
  6. +
+
+Lista fișierelor editate + +
+

Figura 20 – Fișierele editate

+

11.2. Ce afișează această pagină

+ + + + + + + + + + + + + + + + + + + + + + + + + +
ElementDescriere
Fișier originalFișierul din biblioteca centrală
Versiune editatăFișierul modificat pe player
Data edităriiCând a fost modificat
StatusSincronizat / Diferit / Lipsă
+

11.3. Raportul detaliat

+

Pentru o vedere completă:

+
    +
  1. Apăsați „Raport fișiere editate” / „Edited Media Report”
  2. +
  3. Se generează un raport cu toate diferențele
  4. +
+
+Raportul fișierelor editate + +
+

Figura 26 – Raportul fișierelor editate

+
+Detaliu raport + +
+

Figura 27 – Detaliu din raport

+

11.4. Interpretarea statusurilor

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + +
StatusCe înseamnăCe faceți
SincronizatFișierul de pe player corespunde cu cel centralNimic – este în regulă
DiferitFișierul a fost editat pe playerDecideți dacă păstrați sau resincronizați
LipsăFișierul lipsește de pe playerResincronizați player-ul
+

11.5. Vizualizare în mod ecran complet (Fullscreen)

+

Pentru a vedea cum arată conținutul pe player:

+
    +
  1. În lista de playere, apăsați „Ecran complet” / „Fullscreen”
  2. +
  3. Se deschide o previzualizare la scară
  4. +
+
+Previzualizarea fullscreen + +
+

Figura 22 – Previzualizarea fullscreen

+
+

12. Administrare

+
+

Această secțiune este disponibilă doar pentru administratori.

+
+

12.1. Managementul utilizatorilor

+

Admin → Users

+ +
+Managementul utilizatorilor + +
+

Figura 28 – Lista utilizatorilor

+
+Editarea unui utilizator + +
+

Figura 29 – Editarea unui utilizator

+

12.2. Setări HTTPS

+

Admin → HTTPS Configuration

+

Aici configurați certificatul SSL/TLS pentru acces securizat:

+
    +
  1. Hostname – numele serverului
  2. +
  3. Adresă IP – IP-ul serverului
  4. +
  5. Domeniu – domeniul (lăsați gol pentru rețea internă)
  6. +
  7. Email – pentru notificări certificat
  8. +
+
+Configurarea HTTPS + +
+

Figura 24 – Configurarea HTTPS

+
+

Important: Când mutați serverul în rețeaua de producție, setați IP-ul corect (10.76.152.164).

+
+ +

Admin → Customize Logos

+ +

12.4. Dependențe și unelte

+

Admin → Dependencies

+

Permite instalarea de unelte opționale:

+ + + + + + + + + + + + + + + + + +
UnealtăRol
LibreOfficeConversie automată PPT/PPTX în imagini
Emoji FontsAfișarea corectă a emoji-urilor
+
+Instalarea dependențelor + +
+

Figura 25 – Instalarea dependențelor

+

12.5. Media rămasă fără utilizare

+

Admin → Leftover Media

+

Afișează fișierele care nu mai sunt folosite în niciun playlist. Le puteți șterge pentru a elibera spațiu.

+

12.6. Jurnale de sistem (Logs)

+

Admin → System Info / Logs

+

Vedeți activitatea sistemului și eventualele erori.

+
+

13. Întrebări frecvente și depanare

+

13.1. Nu mă pot autentifica

+

Simptom: Parola este respinsă. Soluție: 1. Verificați că scrieți corect numele de utilizator și parola (atenție la majuscule) 2. Dacă ați uitat parola, contactați administratorul 3. Verificați că accesați adresa corectă (cu https://)

+

13.2. Browserul afișează avertisment de certificat

+

Simptom: „Conexiunea nu este privată” / „Nu este sigur”. Soluție: Acest lucru este normal pentru rețeaua internă. Apăsați „Avansat” → „Continuă către…“. Administratorul de rețea poate furniza un certificat intern pentru a elimina avertismentul.

+

13.3. Fișierul nu se încarcă

+

Simptom: Încărcarea eșuează sau se blochează. Soluție: 1. Verificați că fișierul este sub limita de 2 GB 2. Verificați că formatul este acceptat (PNG, JPG, MP4, PDF, PPT etc.) 3. Verificați conexiunea la rețea 4. Încercați din nou; dacă persistă, contactați administratorul

+

13.4. Player-ul nu afișează conținutul nou

+

Simptom: Ați schimbat playlist-ul, dar ecranul afișează vechiul conținut. Soluție: 1. Verificați că playlist-ul este atribuit player-ului 2. Verificați starea de deployment a player-ului 3. Așteptați următoarea sincronizare (poate dura câteva minute) 4. Dacă persistă, verificați că player-ul este online și accesibil în rețea

+

13.5. Am șters un fișier din bibliotecă din greșeală

+

Simptom: Fișierul apare ca „lipsă” în playlist-uri. Soluție: Reîncărcați fișierul în bibliotecă și adăugați-l din nou în playlist. Dacă aveți un backup, contactați administratorul.

+

13.6. Playlist-ul se redă în ordine greșită

+

Simptom: Elementele apar în altă ordine decât ați stabilit. Soluție: Verificați ordinea în pagina de Management a playlist-ului și reordonați folosind drag & drop. Confirmați că ordinea s-a salvat.

+

13.7. Fișierele editate nu corespund

+

Simptom: Raportul de fișiere editate arată diferențe neașteptate. Soluție: Consultați secțiunea 11.4 pentru interpretarea statusurilor. Decideți dacă resincronizați player-ul.

+
+

Anexă A – Glosar de termeni

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TermenExplicație
MediaFișier (imagine, video, document) încărcat în sistem
PlaylistListă ordonată de conținut care se redă pe un ecran
PlayerDispozitivul/ecranul fizic care afișează conținutul
DeploymentProcesul de trimitere a conținutului către player
DashboardPagina principală cu statistici
Bibliotecă de MediaColecția tuturor fișierelor încărcate
Bulk RemoveȘtergerea mai multor elemente simultan
Edited MediaVersiunile modificate local ale fișierelor, de pe player
Web LinkAdresă web afișată ca element în playlist
+
+

Anexă B – Lista capturilor de ecran necesare

+

Salvați capturile în folderul documentatie/screenshots/ cu numele exacte de mai jos:

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Nr.Nume fișierSecțiuneCe trebuie să conțină
101-login.png2.2Ecranul de autentificare
202-change-password.png2.3Formularul de schimbare parolă
303-dashboard.png3Dashboard-ul complet
404-media-library.png4Lista fișierelor media
505-delete-file.png4.4Confirmarea ștergerii
606-upload-media.png5.1Formularul de încărcare
707-upload-progress.png5.3Progresul încărcării
808-add-weblink.png5.4Formularul de link web
909-playlists-list.png6.1Lista playlist-urilor
1010-create-playlist.png6.2Crearea unui playlist
1111-manage-playlist.png6.3Managementul conținutului
1212-add-content-to-playlist.png7.1Selectarea conținutului
1313-content-options.png7.2Opțiunile unui element
1414-remove-from-playlist.png8.1Ștergerea unui element
1515-bulk-remove.png8.2Ștergerea în masă
1616-reorder-playlist.png9.1Reordonarea elementelor
1717-players-list.png10.1Lista playerelor
1818-add-player.png10.2Adăugarea unui player
1919-assign-playlist.png10.4Atribuirea unui playlist
2020-edited-media.png11.1Fișierele editate
2121-edited-media-report.png11.3Raportul detaliat
2222-player-fullscreen.png11.5Previzualizarea fullscreen
2323-user-management.png12.1Managementul utilizatorilor
2424-https-config.png12.2Configurarea HTTPS
2525-dependencies.png12.4Instalarea dependențelor
+
+

Sfârșitul documentului

diff --git a/app/static/help/screenshots/01-login.png b/app/static/help/screenshots/01-login.png new file mode 100644 index 0000000..b581479 Binary files /dev/null and b/app/static/help/screenshots/01-login.png differ diff --git a/app/static/help/screenshots/02-change-password.png b/app/static/help/screenshots/02-change-password.png new file mode 100644 index 0000000..efcdf5a Binary files /dev/null and b/app/static/help/screenshots/02-change-password.png differ diff --git a/app/static/help/screenshots/03-dashboard.png b/app/static/help/screenshots/03-dashboard.png new file mode 100644 index 0000000..3cefc26 Binary files /dev/null and b/app/static/help/screenshots/03-dashboard.png differ diff --git a/app/static/help/screenshots/04-media-library.png b/app/static/help/screenshots/04-media-library.png new file mode 100644 index 0000000..d56c83a Binary files /dev/null and b/app/static/help/screenshots/04-media-library.png differ diff --git a/app/static/help/screenshots/05-1-delete-file.png b/app/static/help/screenshots/05-1-delete-file.png new file mode 100644 index 0000000..ce4d5fb Binary files /dev/null and b/app/static/help/screenshots/05-1-delete-file.png differ diff --git a/app/static/help/screenshots/05-2-delete-file-confirm.png b/app/static/help/screenshots/05-2-delete-file-confirm.png new file mode 100644 index 0000000..e2f435c Binary files /dev/null and b/app/static/help/screenshots/05-2-delete-file-confirm.png differ diff --git a/app/static/help/screenshots/06-1-upload-media.png b/app/static/help/screenshots/06-1-upload-media.png new file mode 100644 index 0000000..5bc0be4 Binary files /dev/null and b/app/static/help/screenshots/06-1-upload-media.png differ diff --git a/app/static/help/screenshots/06-2-upload-media-select.png b/app/static/help/screenshots/06-2-upload-media-select.png new file mode 100644 index 0000000..852ca23 Binary files /dev/null and b/app/static/help/screenshots/06-2-upload-media-select.png differ diff --git a/app/static/help/screenshots/07-upload-success.png b/app/static/help/screenshots/07-upload-success.png new file mode 100644 index 0000000..04290db Binary files /dev/null and b/app/static/help/screenshots/07-upload-success.png differ diff --git a/app/static/help/screenshots/08-add-weblink.png b/app/static/help/screenshots/08-add-weblink.png new file mode 100644 index 0000000..bf236b4 Binary files /dev/null and b/app/static/help/screenshots/08-add-weblink.png differ diff --git a/app/static/help/screenshots/09-playlists-list.png b/app/static/help/screenshots/09-playlists-list.png new file mode 100644 index 0000000..93f5c3d Binary files /dev/null and b/app/static/help/screenshots/09-playlists-list.png differ diff --git a/app/static/help/screenshots/10-create-playlist.png b/app/static/help/screenshots/10-create-playlist.png new file mode 100644 index 0000000..9e66972 Binary files /dev/null and b/app/static/help/screenshots/10-create-playlist.png differ diff --git a/app/static/help/screenshots/11-1-manage-playlist.png b/app/static/help/screenshots/11-1-manage-playlist.png new file mode 100644 index 0000000..d3c8bdf Binary files /dev/null and b/app/static/help/screenshots/11-1-manage-playlist.png differ diff --git a/app/static/help/screenshots/11-2-manage-playlist-content.png b/app/static/help/screenshots/11-2-manage-playlist-content.png new file mode 100644 index 0000000..bece719 Binary files /dev/null and b/app/static/help/screenshots/11-2-manage-playlist-content.png differ diff --git a/app/static/help/screenshots/12-add-content-to-playlist.png b/app/static/help/screenshots/12-add-content-to-playlist.png new file mode 100644 index 0000000..dea27cd Binary files /dev/null and b/app/static/help/screenshots/12-add-content-to-playlist.png differ diff --git a/app/static/help/screenshots/13-content-options.png b/app/static/help/screenshots/13-content-options.png new file mode 100644 index 0000000..bece719 Binary files /dev/null and b/app/static/help/screenshots/13-content-options.png differ diff --git a/app/static/help/screenshots/14-remove-from-playlist.png b/app/static/help/screenshots/14-remove-from-playlist.png new file mode 100644 index 0000000..d3856ca Binary files /dev/null and b/app/static/help/screenshots/14-remove-from-playlist.png differ diff --git a/app/static/help/screenshots/15-bulk-remove.png b/app/static/help/screenshots/15-bulk-remove.png new file mode 100644 index 0000000..d78868e Binary files /dev/null and b/app/static/help/screenshots/15-bulk-remove.png differ diff --git a/app/static/help/screenshots/16-reorder-playlist.png b/app/static/help/screenshots/16-reorder-playlist.png new file mode 100644 index 0000000..2465c2b Binary files /dev/null and b/app/static/help/screenshots/16-reorder-playlist.png differ diff --git a/app/static/help/screenshots/17-players-list.png b/app/static/help/screenshots/17-players-list.png new file mode 100644 index 0000000..1ed63cf Binary files /dev/null and b/app/static/help/screenshots/17-players-list.png differ diff --git a/app/static/help/screenshots/18-1-add-player.png b/app/static/help/screenshots/18-1-add-player.png new file mode 100644 index 0000000..01f5eb0 Binary files /dev/null and b/app/static/help/screenshots/18-1-add-player.png differ diff --git a/app/static/help/screenshots/18-2-add-player-filled.png b/app/static/help/screenshots/18-2-add-player-filled.png new file mode 100644 index 0000000..e68cc16 Binary files /dev/null and b/app/static/help/screenshots/18-2-add-player-filled.png differ diff --git a/app/static/help/screenshots/19-1-assign-playlist.png b/app/static/help/screenshots/19-1-assign-playlist.png new file mode 100644 index 0000000..ca28107 Binary files /dev/null and b/app/static/help/screenshots/19-1-assign-playlist.png differ diff --git a/app/static/help/screenshots/19-2-assign-playlist-done.png b/app/static/help/screenshots/19-2-assign-playlist-done.png new file mode 100644 index 0000000..73241fc Binary files /dev/null and b/app/static/help/screenshots/19-2-assign-playlist-done.png differ diff --git a/app/static/help/screenshots/20-edited-media.png b/app/static/help/screenshots/20-edited-media.png new file mode 100644 index 0000000..f7cda8d Binary files /dev/null and b/app/static/help/screenshots/20-edited-media.png differ diff --git a/app/static/help/screenshots/21-1-edited-media-report.png b/app/static/help/screenshots/21-1-edited-media-report.png new file mode 100644 index 0000000..11cd1a5 Binary files /dev/null and b/app/static/help/screenshots/21-1-edited-media-report.png differ diff --git a/app/static/help/screenshots/21-2-edited-media-report-detail.png b/app/static/help/screenshots/21-2-edited-media-report-detail.png new file mode 100644 index 0000000..1b8af6d Binary files /dev/null and b/app/static/help/screenshots/21-2-edited-media-report-detail.png differ diff --git a/app/static/help/screenshots/22-player-fullscreen.png b/app/static/help/screenshots/22-player-fullscreen.png new file mode 100644 index 0000000..3820485 Binary files /dev/null and b/app/static/help/screenshots/22-player-fullscreen.png differ diff --git a/app/static/help/screenshots/23-1-user-management.png b/app/static/help/screenshots/23-1-user-management.png new file mode 100644 index 0000000..c2804a2 Binary files /dev/null and b/app/static/help/screenshots/23-1-user-management.png differ diff --git a/app/static/help/screenshots/23-2-user-management-edit.png b/app/static/help/screenshots/23-2-user-management-edit.png new file mode 100644 index 0000000..d8ea38a Binary files /dev/null and b/app/static/help/screenshots/23-2-user-management-edit.png differ diff --git a/app/static/help/screenshots/24-https-config.png b/app/static/help/screenshots/24-https-config.png new file mode 100644 index 0000000..da5bca8 Binary files /dev/null and b/app/static/help/screenshots/24-https-config.png differ diff --git a/app/static/help/screenshots/25-dependencies.png b/app/static/help/screenshots/25-dependencies.png new file mode 100644 index 0000000..40ac6d4 Binary files /dev/null and b/app/static/help/screenshots/25-dependencies.png differ diff --git a/app/static/icons/help.svg b/app/static/icons/help.svg new file mode 100644 index 0000000..7088514 --- /dev/null +++ b/app/static/icons/help.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/templates/base.html b/app/templates/base.html index a242638..d3b6fe0 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -393,6 +393,10 @@ Playlists + + + Ajutor + Admin Logout ({{ current_user.username }}) + + +{% endblock %} diff --git a/backup_players_playlists.sh b/backup_players_playlists.sh new file mode 100755 index 0000000..3de185c --- /dev/null +++ b/backup_players_playlists.sh @@ -0,0 +1,240 @@ +#!/bin/bash +# ============================================================================ +# DigiServer - Database Backup (restore-ready for Docker image / host upgrades) +# ---------------------------------------------------------------------------- +# Produces a timestamped, self-contained bundle under ./backups//: +# +# dashboard.db.gz - CONSISTENT full snapshot of the SQLite database +# (player, playlist, playlist_content, +# player_feedback and all other tables) +# players_playlists.sql.gz - logical dump of player/playlist tables +# (secondary safety net; human-readable) +# SHA256SUMS - integrity check +# MANIFEST.txt - row counts, sizes, checksums, app version +# RESTORE.md - copy-paste restore instructions for this bundle +# +# The bundle is designed so that after a `docker compose build` + host upgrade +# you can run ./restore_database.sh and be back exactly as before. +# +# Usage: +# ./backup_players_playlists.sh # full restore-ready backup +# ./backup_players_playlists.sh --logical-only # SQL dump only (no 2.2GB copy) +# ============================================================================ +set -euo pipefail + +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE="docker compose -f $PROJECT_DIR/docker-compose.yml" +CONTAINER="digiserver-v2" +DB_HOST="$PROJECT_DIR/data/instance/dashboard.db" +DB_CTR="/app/instance/dashboard.db" +SNAP_CTR="/app/instance/__snapshot.db" +BACKUP_ROOT="$PROJECT_DIR/backups" +TS="$(date +%Y%m%d_%H%M%S)" +DEST="$BACKUP_ROOT/$TS" + +ALL_DUMP_TABLES=(player playlist playlist_content player_user player_edit content group group_content) + +LOGICAL_ONLY=0 +[ "${1:-}" = "--logical-only" ] && LOGICAL_ONLY=1 + +mkdir -p "$DEST" +echo "============================================================" +echo " DigiServer restore-ready backup" +echo " Target: $DEST" +echo "============================================================" + +if [ ! -f "$DB_HOST" ]; then + echo "ERROR: database not found at $DB_HOST" + exit 1 +fi + +# --------------------------------------------------------------------------- +# 1. Consistent snapshot via SQLite online backup API (safe while app runs) +# --------------------------------------------------------------------------- +if [ "$LOGICAL_ONLY" -eq 0 ]; then + echo + echo "[1/5] Creating consistent DB snapshot (online backup API)..." + $COMPOSE exec -T digiserver-app python - <<'PYEOF' +import sqlite3 +src = sqlite3.connect('/app/instance/dashboard.db') +dst = sqlite3.connect('/app/instance/__snapshot.db') +with dst: + src.backup(dst) +dst.close(); src.close() +print(" snapshot created") +PYEOF + + docker cp "$CONTAINER:$SNAP_CTR" "$DEST/dashboard.db" + $COMPOSE exec -T digiserver-app rm -f "$SNAP_CTR" + echo " -> size: $(du -h "$DEST/dashboard.db" | cut -f1)" + + echo + echo "[2/5] Compressing snapshot..." + gzip -f "$DEST/dashboard.db" + echo " -> $(ls -lh "$DEST/dashboard.db.gz" | awk '{print $5}')" +else + echo + echo "[1/5] Skipping full snapshot (--logical-only)" + echo "[2/5] Skipping compression" +fi + +# --------------------------------------------------------------------------- +# 3. Logical SQL dump (secondary safety net) +# --------------------------------------------------------------------------- +echo +echo "[3/5] Creating logical SQL dump of player/playlist tables..." +TABLE_LIST=$(printf '"%s",' "${ALL_DUMP_TABLES[@]}") +TABLE_LIST="[${TABLE_LIST%,}]" + +$COMPOSE exec -T digiserver-app python - "$TABLE_LIST" > "$DEST/players_playlists.sql" <<'PYEOF' +import sqlite3, sys +tables = eval(sys.argv[1]) +con = sqlite3.connect('/app/instance/dashboard.db') +o = sys.stdout +o.write("-- DigiServer logical backup: players & playlists\n") +o.write("-- Tables: %s\n\n" % ", ".join(tables)) +o.write("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n\n") +for t in tables: + row = con.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name=?", (t,)).fetchone() + if not row or not row[0]: + continue + o.write("DROP TABLE IF EXISTS \"%s\";\n" % t) + o.write(row[0].rstrip() + ";\n") + cur = con.execute('SELECT * FROM "%s"' % t) + cols = [d[0] for d in cur.description] + collist = ",".join('"%s"' % c for c in cols) + batch = [] + def flush(b): + if b: + o.write("INSERT INTO \"%s\" (%s) VALUES\n%s;\n" % (t, collist, ",\n".join(b))) + for rec in cur: + vals = [] + for v in rec: + if v is None: vals.append("NULL") + elif isinstance(v, (int, float)): vals.append(str(v)) + elif isinstance(v, bytes): vals.append("X'%s'" % v.hex()) + else: vals.append("'" + str(v).replace("'", "''") + "'") + batch.append("(%s)" % ",".join(vals)) + if len(batch) >= 500: + flush(batch); batch = [] + flush(batch) + o.write("\n") +o.write("COMMIT;\n") +PYEOF + +gzip -f "$DEST/players_playlists.sql" +echo " -> $(ls -lh "$DEST/players_playlists.sql.gz" | awk '{print $5}')" + +# --------------------------------------------------------------------------- +# 4. Checksums +# --------------------------------------------------------------------------- +echo +echo "[4/5] Writing checksums..." +( cd "$DEST" && sha256sum *.gz > SHA256SUMS ) +sed 's/^/ /' "$DEST/SHA256SUMS" + +# --------------------------------------------------------------------------- +# 5. Manifest + restore instructions +# --------------------------------------------------------------------------- +echo +echo "[5/5] Writing MANIFEST.txt and RESTORE.md..." +{ + echo "DigiServer backup manifest" + echo "==========================" + echo "Created: $(date -Iseconds)" + echo "Host: $(hostname)" + echo "Backup ID: $TS" + echo "Source DB: $DB_HOST" + echo "Source DB size: $(du -h "$DB_HOST" | cut -f1)" + echo "" + echo "Row counts at backup time:" + $COMPOSE exec -T digiserver-app python - <<'PYEOF' 2>/dev/null || echo " (unavailable)" +import sqlite3 +con = sqlite3.connect('/app/instance/dashboard.db') +for t in ['player','playlist','playlist_content','player_user','player_edit', + 'player_feedback','content','group','group_content','user']: + try: + n = con.execute('SELECT COUNT(*) FROM "%s"' % t).fetchone()[0] + print(' %-20s %9d' % (t, n)) + except Exception as e: + print(' %-20s ERROR %s' % (t, e)) +PYEOF + echo "" + echo "Files:" + ( cd "$DEST" && ls -lh | tail -n +2 | sed 's/^/ /' ) +} > "$DEST/MANIFEST.txt" + +cat > "$DEST/RESTORE.md" < data/instance/dashboard.db + +# 4. Fix ownership (container runs as uid 1000) +sudo chown 1000:1000 data/instance/dashboard.db +chmod 644 data/instance/dashboard.db + +# 5. Remove any stale journal file +rm -f data/instance/dashboard.db-journal + +# 6. Rebuild/start the upgraded image +docker compose up -d --build + +# 7. Re-run migrations (new schema may have been added) +docker compose exec -T digiserver-app python /app/migrations/add_https_config_table.py +docker compose exec -T digiserver-app python /app/migrations/add_player_user_table.py +docker compose exec -T digiserver-app python /app/migrations/add_email_to_https_config.py +docker compose exec -T digiserver-app python /app/migrations/migrate_player_user_global.py + +# 8. Verify +docker compose exec -T digiserver-app python -c " +import sqlite3 +c=sqlite3.connect('/app/instance/dashboard.db') +print('players: ', c.execute('SELECT COUNT(*) FROM player').fetchone()[0]) +print('playlists:', c.execute('SELECT COUNT(*) FROM playlist').fetchone()[0]) +print('items: ', c.execute('SELECT COUNT(*) FROM playlist_content').fetchone()[0]) +" +\`\`\` + +## Important notes + +- The container's **entrypoint only creates a DB if one is missing** - dropping in this + file bypasses re-initialisation, which is what we want. +- Ownership **must be uid/gid 1000** (host \`pi:pi\` == container \`appuser\`). +- If the new app version changed the schema, the migration step (7) is mandatory. +EOF + +echo +echo "============================================================" +echo " Backup complete and restore-ready: $DEST" +echo " To restore later: ./restore_database.sh $TS" +echo "============================================================" diff --git a/documentatie/CONVERSIE-DOCX.md b/documentatie/CONVERSIE-DOCX.md new file mode 100644 index 0000000..6db6c66 --- /dev/null +++ b/documentatie/CONVERSIE-DOCX.md @@ -0,0 +1,225 @@ +# Cum convertesc acest manual în format .DOCX + +Acest fișier explică pașii pentru a transforma `Manual-Utilizare-DigiServer.md` într-un document Word (`.docx`) gata de printat sau distribuit. + +--- + +## Metoda 1 – Pandoc (recomandată) + +Pandoc este cea mai bună soluție: convertește Markdown în DOCX păstrând titluri, tabele, liste și imagini. + +### 1.1. Instalare Pandoc + +Pe Debian/Ubuntu (inclusiv pe acest server): + +```bash +sudo apt-get update +sudo apt-get install -y pandoc +``` + +Verificare: + +```bash +pandoc --version +``` + +### 1.2. Conversie simplă + +Din folderul `documentatie/`: + +```bash +cd /srv/digiserver-v2/documentatie +pandoc Manual-Utilizare-DigiServer.md -o Manual-Utilizare-DigiServer.docx +``` + +### 1.3. Conversie cu cuprins automat (Table of Contents) + +```bash +pandoc Manual-Utilizare-DigiServer.md \ + --toc \ + --toc-depth=2 \ + --number-sections \ + -o Manual-Utilizare-DigiServer.docx +``` + +| Opțiune | Efect | +|---------|-------| +| `--toc` | Adaugă cuprins automat | +| `--toc-depth=2` | Cuprinsul include titluri de nivel 1 și 2 | +| `--number-sections` | Numerotează secțiunile (1, 1.1, 1.2...) | + +### 1.4. Conversie cu șablon personalizat (logo, fonturi corporate) + +Dacă doriți un aspect personalizat: + +1. Generați un șablon de referință: + ```bash + pandoc -o template-referinta.docx --print-default-data-file reference.docx + ``` +2. Deschideți `template-referinta.docx` în Word +3. Modificați stilurile (fonturi, culori, antet, logo) +4. Salvați și folosiți-l la conversie: + ```bash + pandoc Manual-Utilizare-DigiServer.md \ + --toc --number-sections \ + --reference-doc=template-referinta.docx \ + -o Manual-Utilizare-DigiServer.docx + ``` + +### 1.5. Conversie cu imagini redimensionate (pentru capturile de ecran) + +```bash +pandoc Manual-Utilizare-DigiServer.md \ + --toc --number-sections \ + --resource-path=screenshots \ + -o Manual-Utilizare-DigiServer.docx +``` + +> **Notă:** Pentru ca imaginile să apară în document, ele trebuie să existe în folderul +> `screenshots/` cu numele exacte din Anexa B și trebuie referite în Markdown. + +--- + +## Metoda 2 – VS Code (fără instalări suplimentare) + +Dacă editați în VS Code: + +1. Instalați extensia **„Markdown PDF"** sau **„Markdown Preview Enhanced"** +2. Deschideți `Manual-Utilizare-DigiServer.md` +3. Click dreapta → **„Markdown: Export to DOCX"** (sau PDF) +4. Salvați documentul rezultat + +Alternativ, extensia **„Markdown All in One"** + **„Pandoc"** permite export direct DOCX din Command Palette. + +--- + +## Metoda 3 – Online (fără instalare) + +Pentru conversie rapidă fără a instala nimic: + +1. Accesați un convertor online (ex: `https://www.markdowntodocx.com`) +2. Încărcați sau lipiți conținutul din `Manual-Utilizare-DigiServer.md` +3. Descărcați fișierul `.docx` rezultat + +> **Atenție:** Nu folosiți convertizoare online pentru documente cu informații sensibile (adrese IP interne, credențiale). Preferați Metoda 1 sau 2. + +--- + +## Pașii compleți pentru un document final (cu capturi de ecran) + +### Pasul 1 – Faceți capturile de ecran + +Deschideți aplicația în browser și faceți capturi pentru fiecare punct din **Anexa B** a manualului. + +**Sfaturi pentru capturi bune:** +- Folosiți rezoluția completă a ferestrei (nu tăiați meniurile) +- Evitați să apară date sensibile (parole, IP-uri reale dacă nu e necesar) +- Salvați în format PNG pentru claritate +- Denumiți exact ca în Anexa B (ex: `01-login.png`) + +### Pasul 2 – Salvați capturile + +Puneți toate fișierele în: + +``` +/srv/digiserver-v2/documentatie/screenshots/ +``` + +### Pasul 3 – Referiți imaginile în Markdown + +Înlocuiți liniile de tip: + +```markdown +**[SCREENSHOT: 03-dashboard.png – Dashboard după autentificare]** +``` + +cu: + +```markdown +![Dashboard după autentificare](screenshots/03-dashboard.png) + +*Figura 1 – Dashboard-ul principal al aplicației* +``` + +### Pasul 4 – Convertiți în DOCX + +```bash +cd /srv/digiserver-v2/documentatie +pandoc Manual-Utilizare-DigiServer.md \ + --toc \ + --toc-depth=2 \ + --number-sections \ + --resource-path=screenshots \ + -o Manual-Utilizare-DigiServer.docx +``` + +### Pasul 5 – Verificați documentul + +Deschideți `Manual-Utilizare-DigiServer.docx` în Word / LibreOffice și verificați: + +- [ ] Cuprinsul este corect și complet +- [ ] Toate capturile de ecran apar +- [ ] Tabelele sunt formatate corect +- [ ] Numerotarea secțiunilor este consecventă +- [ ] Textul diacriticilor românești (ă, â, î, ș, ț) se afișează corect + +--- + +## Script automat de conversie + +Un script care face totul automat: + +```bash +#!/bin/bash +# convert_manual.sh - Converteste manualul in DOCX cu cuprins si imagini + +cd "$(dirname "$0")" + +echo "Verificare Pandoc..." +if ! command -v pandoc &> /dev/null; then + echo "Pandoc nu este instalat. Rulati: sudo apt-get install -y pandoc" + exit 1 +fi + +echo "Numar capturi de ecran disponibile:" +ls -1 screenshots/*.png 2>/dev/null | wc -l + +echo "Conversie in DOCX..." +pandoc Manual-Utilizare-DigiServer.md \ + --toc \ + --toc-depth=2 \ + --number-sections \ + --resource-path=screenshots \ + -o Manual-Utilizare-DigiServer.docx + +if [ -f Manual-Utilizare-DigiServer.docx ]; then + echo "✓ Document creat: Manual-Utilizare-DigiServer.docx" + ls -lh Manual-Utilizare-DigiServer.docx +else + echo "✗ Eroare la conversie" + exit 1 +fi +``` + +Salvați ca `convert_manual.sh`, apoi: + +```bash +chmod +x convert_manual.sh +./convert_manual.sh +``` + +--- + +## Rezumat rapid + +| Metodă | Necesită | Calitate | Recomandat pentru | +|--------|----------|----------|-------------------| +| **Pandoc** | instalare | ★★★★★ | Document final profesional | +| **VS Code** | extensie | ★★★★ | Utilizatori VS Code | +| **Online** | browser | ★★★ | Conversie rapidă, documente nesensibile | + +**Recomandare:** Folosiți **Pandoc cu `--toc` și `--number-sections`** și un șablon de referință personalizat pentru un document final profesionist. + +--- + +*Pentru întrebări despre conversie, consultați documentația Pandoc: https://pandoc.org/MANUAL.html* diff --git a/documentatie/Manual-Utilizare-DigiServer.md b/documentatie/Manual-Utilizare-DigiServer.md new file mode 100644 index 0000000..d206e0a --- /dev/null +++ b/documentatie/Manual-Utilizare-DigiServer.md @@ -0,0 +1,711 @@ +# Manual de Utilizare – DigiServer v2 + +**Versiune document:** 1.0 +**Data:** Septembrie 2026 +**Aplicație:** DigiServer v2 – Sistem de management al conținutului pentru ecrane digitale (Digital Signage) + +--- + +## Cuprins + +1. [Introducere](#1-introducere) +2. [Autentificare în aplicație](#2-autentificare-în-aplicație) +3. [Dashboard (Panoul principal)](#3-dashboard-panoul-principal) +4. [Biblioteca de Media](#4-biblioteca-de-media) +5. [Adăugarea de Media în sistem](#5-adăugarea-de-media-în-sistem) +6. [Managementul Playlist-urilor](#6-managementul-playlist-urilor) +7. [Adăugarea de conținut într-un Playlist](#7-adăugarea-de-conținut-într-un-playlist) +8. [Ștergerea unui fișier din Playlist](#8-ștergerea-unui-fișier-din-playlist) +9. [Reordonarea conținutului în Playlist](#9-reordonarea-conținutului-în-playlist) +10. [Managementul Playerelelor](#10-managementul-playerelelor) +11. [Vizualizarea fișierelor editate pe Player (funcție avansată)](#11-vizualizarea-fișierelor-editate-pe-player-funcție-avansată) +12. [Administrare](#12-administrare) +13. [Întrebări frecvente și depanare](#13-întrebări-frecvente-și-depanare) + +--- + +## 1. Introducere + +**DigiServer v2** este o aplicație web folosită pentru a gestiona conținutul afișat pe ecranele digitale (playere). Cu ajutorul ei puteți: + +- Încărca fișiere media (imagini, videoclipuri, documente PDF, prezentări PowerPoint) +- Crea **playlist-uri** – liste ordonate de conținut care se afișează pe ecrane +- Atribui playlist-uri către playere specifice +- Urmări automatizarea și starea playerelor +- Vizualiza și gestiona versiunile editate ale fișierelor de pe playere + +### Structura generală a aplicației + +``` +┌─────────────────────────────────────────────────────────┐ +│ UTILIZATOR (browser) │ +│ │ │ +│ ▼ │ +│ DigiServer (interfață web) │ +│ │ │ +│ ├──► Biblioteca de Media (fișiere) │ +│ ├──► Playlist-uri (liste de redare) │ +│ └──► Playere (ecrane fizice) │ +└─────────────────────────────────────────────────────────┘ +``` + +### Roluri de utilizator + +| Rol | Drepturi | +|-----|----------| +| **Admin** | Acces complet: utilizatori, setări sistem, HTTPS, playere, conținut | +| **Editor** | Poate încărca conținut, crea playlist-uri și edita playere | +| **Utilizator** | Poate vizualiza conținut și playlists | + +--- + +## 2. Autentificare în aplicație + +### 2.1. Deschiderea aplicației + +Deschideți un browser (Chrome, Firefox sau Edge) și accesați una dintre adresele: + +- **Prin adresă IP:** `https://10.76.152.164` +- **Prin nume gazdă:** `https://digiserver` +- **Prin domeniu:** `https://digiserver.sibiusb.harting.intra` + +> **Notă:** Dacă browserul afișează un avertisment de certificat („Conexiunea nu este privată"), acest lucru este normal pentru rețeaua internă. Apăsați **„Avansat" → „Continuă către..."**. Administratorul de rețea poate instala certificatul intern pentru a elimina acest avertisment. + +### 2.2. Ecranul de autentificare + +![Ecranul de autentificare](screenshots/01-login.png) + +*Figura 1 – Ecranul de login* + +Introduceți: + +1. **Nume utilizator** (username) +2. **Parolă** +3. Apăsați butonul **„Autentificare"** / **„Login"** + +> **Important:** Dacă ați uitat parola, contactați administratorul sistemului. Parola poate fi schimbată ulterior din meniul de cont. + +### 2.3. Schimbarea parolei + +După prima autentificare, se recomandă schimbarea parolei: + +1. Accesați **meniul de utilizator** (colț dreapta-sus) +2. Selectați **„Schimbă parola"** / **„Change Password"** +3. Introduceți parola veche, apoi parola nouă (de două ori) +4. Confirmați + +![Formularul de schimbare a parolei](screenshots/02-change-password.png) + +*Figura 2 – Schimbarea parolei* + +--- + +## 3. Dashboard (Panoul principal) + +După autentificare, sunteți redirecționat către **Dashboard** – pagina principală a aplicației. + +![Dashboard după autentificare](screenshots/03-dashboard.png) + +*Figura 3 – Dashboard-ul principal* + +### 3.1. Elementele Dashboard-ului + +Dashboard-ul oferă o imagine de ansamblu asupra sistemului: + +| Element | Descriere | +|---------|-----------| +| **Statistici** | Număr de playere, playlist-uri, fișiere media | +| **Stare playere** | Care playere sunt online / offline | +| **Acțiuni rapide** | Butoane pentru adăugare rapidă de conținut | +| **Meniu de navigare** | Acces către toate secțiunile aplicației | + +### 3.2. Meniul principal de navigare + +Meniul din partea stângă (sau de sus) conține: + +| Secțiune | Funcție | +|----------|---------| +| **Dashboard** | Pagina principală cu statistici | +| **Media Library** (Biblioteca de Media) | Toate fișierele încărcate | +| **Playlists** | Gestionarea listelor de redare | +| **Players** (Playere) | Gestionarea ecranelor | +| **Admin** | Setări de sistem (doar pentru administratori) | + +### 3.3. Cum citiți statisticile + +1. **Playere (Players):** Numărul total de ecrane configurate +2. **Playlist-uri:** Numărul de liste de redare existente +3. **Media:** Numărul total de fișiere încărcate + +Apăsați pe orice statistică pentru a accesa secțiunea corespunzătoare. + +--- + +## 4. Biblioteca de Media + +Biblioteca de Media conține **toate fișierele** încărcate în sistem: imagini, videoclipuri, documente PDF și prezentări. + +![Biblioteca de Media](screenshots/04-media-library.png) + +*Figura 4 – Bibliotecac de Media* + +### 4.1. Accesarea bibliotecii + +Din meniul principal, selectați **„Media Library"** sau accesați direct `/media-library`. + +### 4.2. Informații afișate pentru fiecare fișier + +| Coloană / Element | Semnificație | +|-------------------|--------------| +| **Nume fișier** | Numele original al fișierului încărcat | +| **Tip** | Imagine / Video / PDF / Prezentare | +| **Dimensiune** | Mărimea fișierului | +| **Data încărcării** | Când a fost adăugat în sistem | +| **Previzualizare** | Miniatură pentru imagini și videoclipuri | + +### 4.3. Filtrarea și căutarea + +- Folosiți **bara de căutare** pentru a găsi un fișier după nume +- Folosiți **filtrele** pentru a afișa doar un anumit tip (imagini, videoclipuri etc.) + +### 4.4. Ștergerea unui fișier din bibliotecă + +> **Atenție:** Ștergerea din bibliotecă este permanentă. Dacă fișierul este folosit într-un playlist, acesta va apărea ca lipsă. + +1. Găsiți fișierul în listă +2. Apăsați butonul **Ștergere** (iconiță coș de gunoi / X) +3. Confirmați ștergerea + +![Accesarea opțiunii de ștergere](screenshots/05-1-delete-file.png) + +*Figura 5 – Accesarea butonului de ștergere* + +![Confirmarea ștergerii unui fișier](screenshots/05-2-delete-file-confirm.png) + +*Figura 6 – Confirmarea ștergerii* + +--- + +## 5. Adăugarea de Media în sistem + +### 5.1. Deschiderea formularului de încărcare + +Din meniul principal selectați **„Upload Media"** sau accesați pagina de încărcare. + +![Formularul de încărcare media](screenshots/06-1-upload-media.png) + +*Figura 7 – Pagina de încărcare media* + +### 5.2. Tipuri de fișiere acceptate + +| Categorie | Formate acceptate | +|-----------|-------------------| +| **Imagini** | PNG, JPG, JPEG, GIF, BMP | +| **Video** | MP4, AVI, MKV, MOV, WEBM | +| **Documente** | PDF | +| **Prezentări** | PPT, PPTX | + +### 5.3. Pașii pentru încărcare + +1. **Apăsați zona de selecție** sau butonul **„Alege fișier"** +2. Selectați fișierul (sau mai multe fișiere) din calculator +3. Așteptați finalizarea încărcării +4. Veți primi confirmarea că fișierul a fost adăugat + +![Selectarea fișierului de încărcat](screenshots/06-2-upload-media-select.png) + +*Figura 8 – Selectarea fișierului* + +### 5.4. Confirmarea încărcării + +După finalizarea încărcării, aplicația afișează un banner verde de confirmare cu mesajul **„Successfully uploaded"**, care indică playlist-ul în care a fost adăugat fișierul. + +![Banner de confirmare a încărcării](screenshots/07-upload-success.png) + +*Figura 9 – Bannerul „Successfully uploaded"* + +### 5.5. Adăugarea unui link web (Web Link) + +Pe lângă fișiere, puteți adăuga și **adrese web** care să fie afișate pe ecrane. + +1. Selectați opțiunea **„Add Web Link"** / **„Adaugă link web"** +2. Introduceți **URL-ul complet** (ex: `https://www.exemplu.ro`) +3. Dați un **titlu** pentru link +4. Salvați + +![Adăugarea unui link web](screenshots/08-add-weblink.png) + +*Figura 10 – Adăugarea unui link web* + +> **Sfat:** Limita maximă pentru un fișier este de 2 GB. Pentru fișiere foarte mari, împărțiți-le sau contactați administratorul. + +--- + +## 6. Managementul Playlist-urilor + +Un **playlist** este o listă ordonată de conținut care se redă pe un player. Puteți avea mai multe playlist-uri pentru diferite ecrane sau situații. + +### 6.1. Vizualizarea playlist-urilor + +Din meniul principal selectați **„Playlists"**. + +![Lista playlist-urilor](screenshots/09-playlists-list.png) + +*Figura 9 – Lista playlist-urilor* + +Aici vedeți toate playlist-urile existente, cu: + +| Element | Descriere | +|---------|-----------| +| **Nume** | Denumirea playlist-ului | +| **Nr. elemente** | Câte fișiere conține | +| **Player atribuit** | Pe ce ecran se redă | +| **Acțiuni** | Editare, gestionare conținut, ștergere | + +### 6.2. Crearea unui playlist nou + +1. Apăsați butonul **„Creează Playlist"** / **„Create Playlist"** +2. Introduceți **numele playlist-ului** (ex: „Ecran Recepție") +3. Opțional: adăugați o **descriere** +4. Apăsați **„Salvează"** + +![Crearea unui playlist nou](screenshots/10-create-playlist.png) + +*Figura 10 – Crearea unui playlist* + +### 6.3. Gestionarea conținutului unui playlist + +Pentru a vedea și edita conținutul unui playlist: + +1. Găsiți playlist-ul în listă +2. Apăsați butonul **„Gestionare"** / **„Manage"** (sau numele playlist-ului) +3. Se deschide pagina de management a conținutului + +![Pagina de management a playlist-ului](screenshots/11-1-manage-playlist.png) + +*Figura 12 – Accesarea managementului* + +![Conținutul playlist-ului](screenshots/11-2-manage-playlist-content.png) + +*Figura 13 – Conținutul playlist-ului* + +### 6.4. Ștergerea unui playlist + +1. Găsiți playlist-ul în listă +2. Apăsați butonul **Ștergere** +3. Confirmați + +> **Atenție:** Ștergerea unui playlist nu șterge fișierele media. Doar lista de redare este eliminată. + +--- + +## 7. Adăugarea de conținut într-un Playlist + +### 7.1. Pași pentru adăugare + +1. Deschideți playlist-ul (secțiunea **Management**) +2. Apăsați **„Adaugă conținut"** / **„Add Content"** +3. Se afișează lista cu toate fișierele disponibile +4. **Bifați** fișierele dorite (puteți selecta mai multe) +5. Apăsați **„Adaugă"** + +![Selectarea conținutului de adăugat](screenshots/12-add-content-to-playlist.png) + +*Figura 12 – Adăugarea conținutului* + +### 7.2. Opțiuni per element + +După adăugare, pentru fiecare element puteți configura: + +| Opțiune | Descriere | +|---------|-----------| +| **Durată afișare** | Cât timp se afișează elementul (secunde) | +| **Fără sunet (Muted)** | Dezactivează sunetul pentru acel element | +| **Editare permisă** | Permite player-ului să editeze fișierul local | + +![Opțiunile fiecărui element](screenshots/13-content-options.png) + +*Figura 13 – Opțiunile elementelor* + +### 7.3. Adăugarea unui link web direct în playlist + +1. În pagina de management a playlist-ului, apăsați **„Adaugă link web"** +2. Introduceți URL-ul și titlul +3. Salvați – link-ul apare în listă ca orice alt element + +--- + +## 8. Ștergerea unui fișier din Playlist + +### 8.1. Ștergerea unui singur element + +1. Deschideți playlist-ul în modul **Management** +2. Găsiți elementul dorit în listă +3. Apăsați iconița **Ștergere** (X / coș de gunoi) de pe rândul respectiv +4. Confirmați dacă vi se cere + +![Ștergerea unui element din playlist](screenshots/14-remove-from-playlist.png) + +*Figura 14 – Ștergerea unui element* + +> **Important:** Ștergerea din playlist **nu șterge fișierul** din Biblioteca de Media. Fișierul rămâne disponibil pentru alte playlist-uri. + +### 8.2. Ștergerea mai multor elemente simultan (Bulk Remove) + +Pentru a șterge mai multe fișiere dintr-un playlist: + +1. În pagina de management, **bifați** elementele dorite +2. Apăsați butonul **„Șterge selectate"** / **„Bulk Remove"** +3. Confirmați operațiunea + +![Ștergerea în masă](screenshots/15-bulk-remove.png) + +*Figura 15 – Ștergerea în masă* + +### 8.3. Diferența: ștergere playlist vs. ștergere fișier + +| Acțiune | Efect | +|---------|-------| +| **Ștergere element din playlist** | Elementul dispare din listă; fișierul rămâne în bibliotecă | +| **Ștergere fișier din bibliotecă** | Fișierul dispare complet; apare ca lipsă în toate playlist-urile | +| **Ștergere playlist** | Lista dispare; toate fișierele rămân în bibliotecă | + +--- + +## 9. Reordonarea conținutului în Playlist + +Ordinea elementelor determină ordinea de afișare pe ecran. + +### 9.1. Reordonare prin tragere (drag & drop) + +1. Deschideți playlist-ul în modul **Management** +2. Apăsați și țineți apăsat pe iconița de **mâner** (⋮⋮) din dreptul unui element +3. Trageți elementul în poziția dorită +4. Ordinea se salvează automat + +![Reordonarea elementelor](screenshots/16-reorder-playlist.png) + +*Figura 16 – Reordonarea elementelor* + +### 9.2. Verificarea ordinii + +După reordonare, verificați că numerele de ordine (1, 2, 3...) corespund intenției dvs. + +--- + +## 10. Managementul Playerelelor + +**Playerele** sunt ecranele fizice care afișează conținutul. + +### 10.1. Lista playerelor + +Din meniul principal selectați **„Players"**. + +![Lista playerelor](screenshots/17-players-list.png) + +*Figura 17 – Lista playerelor* + +| Coloană | Semnificație | +|---------|--------------| +| **Nume** | Denumirea player-ului | +| **Locație** | Unde este amplasat ecranul | +| **Adresă IP** | Adresa de rețea a player-ului | +| **Playlist atribuit** | Ce conținut redă | +| **Stare** | Online / Offline / Stare deploy | + +### 10.2. Adăugarea unui player nou + +1. Apăsați **„Adaugă Player"** / **„Add Player"** +2. Completați: + - **Nume** (ex: „Ecran Hol Principal") + - **Adresă IP** + - **Locație** (opțional) +3. Salvați + +![Adăugarea unui player](screenshots/18-1-add-player.png) + +*Figura 20 – Formularul de adăugare player* + +![Player completat](screenshots/18-2-add-player-filled.png) + +*Figura 21 – Formularul completat* + +### 10.3. Editarea unui player + +1. Apăsați **„Editare"** / **„Edit"** pe rândul player-ului +2. Modificați câmpurile dorite +3. Salvați + +### 10.4. Atribuirea unui playlist unui player + +1. În lista de playere, găsiți player-ul dorit +2. Apăsați **„Atribuie Playlist"** / **„Assign Playlist"** +3. Selectați playlist-ul din listă +4. Confirmați + +![Atribuirea unui playlist](screenshots/19-1-assign-playlist.png) + +*Figura 22 – Selectarea playlist-ului* + +![Atribuire confirmată](screenshots/19-2-assign-playlist-done.png) + +*Figura 23 – Confirmarea atribuirii* + +> **Notă:** După atribuire, player-ul va prelua noul conținut la următoarea sincronizare. + +### 10.5. Starea de deployment + +Fiecare player are o **stare de deployment** care arată dacă conținutul a fost trimis cu succes: + +| Stare | Semnificație | +|-------|--------------| +| ✓ **Succes** | Conținutul a fost trimis cu succes | +| ⏳ **În așteptare** | Se așteaptă sincronizarea | +| ✗ **Eroare** | Trimiterea a eșuat – verificați mesajul | + +### 10.6. Regenerarea cheii de autentificare + +Dacă un player nu se mai poate conecta: + +1. Găsiți player-ul în listă +2. Apăsați **„Regenerează autentificare"** / **„Regenerate Auth"** +3. Confirmați – se va genera o cheie nouă + +> **Atenție:** Va trebui să actualizați cheia și pe player-ul fizic. + +--- + +## 11. Vizualizarea fișierelor editate pe Player (funcție avansată) + +Această funcție vă permite să vedeți **ce versiuni editate** ale fișierelor există pe fiecare player. Este utilă când un player modifică local fișierele (de exemplu, suprapune informații, ajustează rezoluția etc.). + +### 11.1. Accesarea raportului de fișiere editate + +1. Accesați secțiunea **Players** +2. Găsiți player-ul dorit +3. Apăsați **„Fișiere editate"** / **„Edited Media"** + +![Lista fișierelor editate](screenshots/20-edited-media.png) + +*Figura 20 – Fișierele editate* + +### 11.2. Ce afișează această pagină + +| Element | Descriere | +|---------|-----------| +| **Fișier original** | Fișierul din biblioteca centrală | +| **Versiune editată** | Fișierul modificat pe player | +| **Data editării** | Când a fost modificat | +| **Status** | Sincronizat / Diferit / Lipsă | + +### 11.3. Raportul detaliat + +Pentru o vedere completă: + +1. Apăsați **„Raport fișiere editate"** / **„Edited Media Report"** +2. Se generează un raport cu toate diferențele + +![Raportul fișierelor editate](screenshots/21-1-edited-media-report.png) + +*Figura 26 – Raportul fișierelor editate* + +![Detaliu raport](screenshots/21-2-edited-media-report-detail.png) + +*Figura 27 – Detaliu din raport* + +### 11.4. Interpretarea statusurilor + +| Status | Ce înseamnă | Ce faceți | +|--------|-------------|-----------| +| **Sincronizat** | Fișierul de pe player corespunde cu cel central | Nimic – este în regulă | +| **Diferit** | Fișierul a fost editat pe player | Decideți dacă păstrați sau resincronizați | +| **Lipsă** | Fișierul lipsește de pe player | Resincronizați player-ul | + +### 11.5. Vizualizare în mod ecran complet (Fullscreen) + +Pentru a vedea cum arată conținutul pe player: + +1. În lista de playere, apăsați **„Ecran complet"** / **„Fullscreen"** +2. Se deschide o previzualizare la scară + +![Previzualizarea fullscreen](screenshots/22-player-fullscreen.png) + +*Figura 22 – Previzualizarea fullscreen* + +--- + +## 12. Administrare + +> Această secțiune este disponibilă **doar pentru administratori**. + +### 12.1. Managementul utilizatorilor + +**Admin → Users** + +- Creați utilizatori noi +- Modificați roluri (Admin / Editor / Utilizator) +- Resetați parole +- Ștergeți utilizatori + +![Managementul utilizatorilor](screenshots/23-1-user-management.png) + +*Figura 28 – Lista utilizatorilor* + +![Editarea unui utilizator](screenshots/23-2-user-management-edit.png) + +*Figura 29 – Editarea unui utilizator* + +### 12.2. Setări HTTPS + +**Admin → HTTPS Configuration** + +Aici configurați certificatul SSL/TLS pentru acces securizat: + +1. **Hostname** – numele serverului +2. **Adresă IP** – IP-ul serverului +3. **Domeniu** – domeniul (lăsați gol pentru rețea internă) +4. **Email** – pentru notificări certificat + +![Configurarea HTTPS](screenshots/24-https-config.png) + +*Figura 24 – Configurarea HTTPS* + +> **Important:** Când mutați serverul în rețeaua de producție, setați IP-ul corect (`10.76.152.164`). + +### 12.3. Personalizare logo + +**Admin → Customize Logos** + +- Încărcați logo pentru antet (header) +- Încărcați logo pentru ecranul de login + +### 12.4. Dependențe și unelte + +**Admin → Dependencies** + +Permite instalarea de unelte opționale: + +| Unealtă | Rol | +|---------|-----| +| **LibreOffice** | Conversie automată PPT/PPTX în imagini | +| **Emoji Fonts** | Afișarea corectă a emoji-urilor | + +![Instalarea dependențelor](screenshots/25-dependencies.png) + +*Figura 25 – Instalarea dependențelor* + +### 12.5. Media rămasă fără utilizare + +**Admin → Leftover Media** + +Afișează fișierele care nu mai sunt folosite în niciun playlist. Le puteți șterge pentru a elibera spațiu. + +### 12.6. Jurnale de sistem (Logs) + +**Admin → System Info / Logs** + +Vedeți activitatea sistemului și eventualele erori. + +--- + +## 13. Întrebări frecvente și depanare + +### 13.1. Nu mă pot autentifica + +**Simptom:** Parola este respinsă. +**Soluție:** +1. Verificați că scrieți corect numele de utilizator și parola (atenție la majuscule) +2. Dacă ați uitat parola, contactați administratorul +3. Verificați că accesați adresa corectă (cu `https://`) + +### 13.2. Browserul afișează avertisment de certificat + +**Simptom:** „Conexiunea nu este privată" / „Nu este sigur". +**Soluție:** Acest lucru este normal pentru rețeaua internă. Apăsați **„Avansat" → „Continuă către..."**. Administratorul de rețea poate furniza un certificat intern pentru a elimina avertismentul. + +### 13.3. Fișierul nu se încarcă + +**Simptom:** Încărcarea eșuează sau se blochează. +**Soluție:** +1. Verificați că fișierul este sub limita de **2 GB** +2. Verificați că formatul este acceptat (PNG, JPG, MP4, PDF, PPT etc.) +3. Verificați conexiunea la rețea +4. Încercați din nou; dacă persistă, contactați administratorul + +### 13.4. Player-ul nu afișează conținutul nou + +**Simptom:** Ați schimbat playlist-ul, dar ecranul afișează vechiul conținut. +**Soluție:** +1. Verificați că playlist-ul este **atribuit** player-ului +2. Verificați **starea de deployment** a player-ului +3. Așteptați următoarea sincronizare (poate dura câteva minute) +4. Dacă persistă, verificați că player-ul este **online** și accesibil în rețea + +### 13.5. Am șters un fișier din bibliotecă din greșeală + +**Simptom:** Fișierul apare ca „lipsă" în playlist-uri. +**Soluție:** Reîncărcați fișierul în bibliotecă și adăugați-l din nou în playlist. Dacă aveți un backup, contactați administratorul. + +### 13.6. Playlist-ul se redă în ordine greșită + +**Simptom:** Elementele apar în altă ordine decât ați stabilit. +**Soluție:** Verificați ordinea în pagina de **Management** a playlist-ului și reordonați folosind drag & drop. Confirmați că ordinea s-a salvat. + +### 13.7. Fișierele editate nu corespund + +**Simptom:** Raportul de fișiere editate arată diferențe neașteptate. +**Soluție:** Consultați secțiunea [11.4](#114-interpretarea-statusurilor) pentru interpretarea statusurilor. Decideți dacă resincronizați player-ul. + +--- + +## Anexă A – Glosar de termeni + +| Termen | Explicație | +|--------|------------| +| **Media** | Fișier (imagine, video, document) încărcat în sistem | +| **Playlist** | Listă ordonată de conținut care se redă pe un ecran | +| **Player** | Dispozitivul/ecranul fizic care afișează conținutul | +| **Deployment** | Procesul de trimitere a conținutului către player | +| **Dashboard** | Pagina principală cu statistici | +| **Bibliotecă de Media** | Colecția tuturor fișierelor încărcate | +| **Bulk Remove** | Ștergerea mai multor elemente simultan | +| **Edited Media** | Versiunile modificate local ale fișierelor, de pe player | +| **Web Link** | Adresă web afișată ca element în playlist | + +--- + +## Anexă B – Lista capturilor de ecran necesare + +Salvați capturile în folderul `documentatie/screenshots/` cu numele exacte de mai jos: + +| Nr. | Nume fișier | Secțiune | Ce trebuie să conțină | +|-----|-------------|----------|------------------------| +| 1 | `01-login.png` | 2.2 | Ecranul de autentificare | +| 2 | `02-change-password.png` | 2.3 | Formularul de schimbare parolă | +| 3 | `03-dashboard.png` | 3 | Dashboard-ul complet | +| 4 | `04-media-library.png` | 4 | Lista fișierelor media | +| 5 | `05-delete-file.png` | 4.4 | Confirmarea ștergerii | +| 6 | `06-upload-media.png` | 5.1 | Formularul de încărcare | +| 7 | `07-upload-progress.png` | 5.3 | Progresul încărcării | +| 8 | `08-add-weblink.png` | 5.4 | Formularul de link web | +| 9 | `09-playlists-list.png` | 6.1 | Lista playlist-urilor | +| 10 | `10-create-playlist.png` | 6.2 | Crearea unui playlist | +| 11 | `11-manage-playlist.png` | 6.3 | Managementul conținutului | +| 12 | `12-add-content-to-playlist.png` | 7.1 | Selectarea conținutului | +| 13 | `13-content-options.png` | 7.2 | Opțiunile unui element | +| 14 | `14-remove-from-playlist.png` | 8.1 | Ștergerea unui element | +| 15 | `15-bulk-remove.png` | 8.2 | Ștergerea în masă | +| 16 | `16-reorder-playlist.png` | 9.1 | Reordonarea elementelor | +| 17 | `17-players-list.png` | 10.1 | Lista playerelor | +| 18 | `18-add-player.png` | 10.2 | Adăugarea unui player | +| 19 | `19-assign-playlist.png` | 10.4 | Atribuirea unui playlist | +| 20 | `20-edited-media.png` | 11.1 | Fișierele editate | +| 21 | `21-edited-media-report.png` | 11.3 | Raportul detaliat | +| 22 | `22-player-fullscreen.png` | 11.5 | Previzualizarea fullscreen | +| 23 | `23-user-management.png` | 12.1 | Managementul utilizatorilor | +| 24 | `24-https-config.png` | 12.2 | Configurarea HTTPS | +| 25 | `25-dependencies.png` | 12.4 | Instalarea dependențelor | + +--- + +*Sfârșitul documentului* diff --git a/documentatie/capture_screenshots.sh b/documentatie/capture_screenshots.sh new file mode 100755 index 0000000..64a2dac --- /dev/null +++ b/documentatie/capture_screenshots.sh @@ -0,0 +1,167 @@ +#!/bin/bash +# ============================================================================ +# capture_screenshots.sh - Helper pentru capturile de ecran ale manualului +# ---------------------------------------------------------------------------- +# Ghideaza pas-cu-pas captura celor 25 de ecrane necesare pentru manual. +# Foloseste Flameshot (recomandat) sau scrot. +# +# Utilizare: +# ./capture_screenshots.sh # mod ghidat, pas cu pas +# ./capture_screenshots.sh --list # doar listeaza ce trebuie capturat +# ./capture_screenshots.sh --check # verifica ce capturi exista deja +# ============================================================================ +set -u + +SCREENSHOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/screenshots" +mkdir -p "$SCREENSHOT_DIR" + +# Cele 25 de capturi necesare: nume|descriere|secțiune manual +CAPTURES=( + "01-login|Ecranul de autentificare (login)|2.2" + "02-change-password|Formularul de schimbare parola|2.3" + "03-dashboard|Dashboard-ul complet cu statistici|3" + "04-media-library|Lista fisierelor din Biblioteca de Media|4" + "05-delete-file|Confirmarea stergerii unui fisier|4.4" + "06-upload-media|Formularul de incarcare media|5.1" + "07-upload-progress|Progresul incarcarii unui fisier|5.3" + "08-add-weblink|Formularul de adaugare link web|5.4" + "09-playlists-list|Lista tuturor playlist-urilor|6.1" + "10-create-playlist|Crearea unui playlist nou|6.2" + "11-manage-playlist|Pagina de management a continutului|6.3" + "12-add-content-to-playlist|Selectarea continutului de adaugat|7.1" + "13-content-options|Optiunile per element (durata, muted)|7.2" + "14-remove-from-playlist|Stergerea unui element din playlist|8.1" + "15-bulk-remove|Stergerea in masa a elementelor|8.2" + "16-reorder-playlist|Reordonarea elementelor (drag & drop)|9.1" + "17-players-list|Lista playerelor|10.1" + "18-add-player|Adaugarea unui player nou|10.2" + "19-assign-playlist|Atribuirea unui playlist unui player|10.4" + "20-edited-media|Lista fisierelor editate pe player|11.1" + "21-edited-media-report|Raportul detaliat al fisierelor editate|11.3" + "22-player-fullscreen|Previzualizarea in mod ecran complet|11.5" + "23-user-management|Managementul utilizatorilor|12.1" + "24-https-config|Configurarea HTTPS|12.2" + "25-dependencies|Instalarea dependentelor|12.4" +) + +# --------------------------------------------------------------------------- +# Mod --list +# --------------------------------------------------------------------------- +if [ "${1:-}" = "--list" ]; then + echo "============================================================" + echo " Capturi de ecran necesare pentru manual (25 total)" + echo "============================================================" + echo + printf "%-6s %-34s %-36s %s\n" "NR" "FISIER" "CE SA CONTINA" "SECTIUNE" + echo "--------------------------------------------------------------------------" + i=1 + for entry in "${CAPTURES[@]}"; do + IFS='|' read -r name desc section <<< "$entry" + printf "%-6s %-34s %-36s %s\n" "$i." "${name}.png" "$desc" "$section" + i=$((i+1)) + done + echo + echo "Salveaza toate capturile in:" + echo " $SCREENSHOT_DIR" + exit 0 +fi + +# --------------------------------------------------------------------------- +# Mod --check +# --------------------------------------------------------------------------- +if [ "${1:-}" = "--check" ]; then + echo "============================================================" + echo " Verificare capturi de ecran existente" + echo "============================================================" + echo + found=0; missing=0 + for entry in "${CAPTURES[@]}"; do + IFS='|' read -r name desc section <<< "$entry" + if [ -f "$SCREENSHOT_DIR/${name}.png" ]; then + size=$(du -h "$SCREENSHOT_DIR/${name}.png" | cut -f1) + printf " \033[0;32m✓\033[0m %-32s %s\n" "${name}.png" "$size" + found=$((found+1)) + else + printf " \033[0;31m✗\033[0m %-32s LIPSA\n" "${name}.png" + missing=$((missing+1)) + fi + done + echo + echo "-------------------------------------------------------------" + echo " Gasite: $found / 25" + echo " Lipsa: $missing / 25" + echo "-------------------------------------------------------------" + if [ "$missing" -eq 0 ]; then + echo + echo " Toate capturile sunt prezente! Puteti rula:" + echo " ./convert_manual.sh" + fi + exit 0 +fi + +# --------------------------------------------------------------------------- +# Mod ghidat +# --------------------------------------------------------------------------- +echo "============================================================" +echo " Ghid capturi de ecran - Manual DigiServer" +echo "============================================================" +echo + +if ! command -v scrot &> /dev/null && ! command -v flameshot &> /dev/null; then + echo "✗ Nu exista tool de capturi. Instalati cu:" + echo " sudo apt-get install -y flameshot scrot" + exit 1 +fi + +echo "Deschideti aplicatia in browser: https://10.76.152.164" +echo "Autentificati-va ca admin, apoi urmati pasii." +echo +echo "Pentru fiecare ecran vi se va cere sa apasati Enter," +echo "apoi se face captura. Daca ati facut-o deja, scrieti 's' (skip)." +echo + +completed=0 +for entry in "${CAPTURES[@]}"; do + IFS='|' read -r name desc section <<< "$entry" + target="$SCREENSHOT_DIR/${name}.png" + + echo "-------------------------------------------------------------" + echo " ${name}.png" + echo " Ce: $desc" + echo " Sectiune manual: $section" + + if [ -f "$target" ]; then + echo " (exista deja - scrieti 'r' pentru a reface, Enter pentru skip)" + fi + + read -r -p " Enter = captura | s = skip | q = iesire: " action + case "$action" in + q|Q) echo; echo "Iesire. Capturi realizate: $completed"; exit 0 ;; + r|R) : ;; + s|S) echo " skipped"; continue ;; + esac + + echo " Captura in 3 secunde... (treceti la fereastra dorita)" + sleep 3 + + if command -v scrot &> /dev/null; then + scrot "$target" + else + flameshot full -p "$target" + fi + + if [ -f "$target" ]; then + echo " ✓ Salvat: $target" + completed=$((completed+1)) + else + echo " ✗ Captura a esuat" + fi +done + +echo +echo "============================================================" +echo " Ghid terminat. Capturi realizate: $completed" +echo "============================================================" +echo +echo "Verificati cu: ./capture_screenshots.sh --check" +echo "Apoi convertiti: ./convert_manual.sh" diff --git a/documentatie/convert_help_page.sh b/documentatie/convert_help_page.sh new file mode 100755 index 0000000..3aa40b8 --- /dev/null +++ b/documentatie/convert_help_page.sh @@ -0,0 +1,93 @@ +#!/bin/bash +# ============================================================================ +# convert_help_page.sh - Regenerates the in-app help page content +# ---------------------------------------------------------------------------- +# Converts documentatie/Manual-Utilizare-DigiServer.md into the HTML fragment +# that the Flask app serves at /help, and refreshes the screenshot copies. +# +# Run this whenever the manual is edited, then rebuild the image: +# ./documentatie/convert_help_page.sh +# cd .. && docker compose up -d --build +# ============================================================================ +set -euo pipefail + +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +SRC_MD="$PROJECT_DIR/documentatie/Manual-Utilizare-DigiServer.md" +SRC_IMG_DIR="$PROJECT_DIR/documentatie/screenshots" +DEST_DIR="$PROJECT_DIR/app/static/help" +DEST_IMG_DIR="$DEST_DIR/screenshots" +DEST_HTML="$DEST_DIR/_manual_body.html" + +echo "============================================================" +echo " Regenerare pagina Ajutor (/help)" +echo "============================================================" +echo + +# --------------------------------------------------------------------------- +# Checks +# --------------------------------------------------------------------------- +if ! command -v pandoc &> /dev/null; then + echo "✗ Pandoc nu este instalat." + echo " Instalati cu: sudo apt-get install -y pandoc" + exit 1 +fi +if [ ! -f "$SRC_MD" ]; then + echo "✗ Nu am gasit manualul: $SRC_MD" + exit 1 +fi + +mkdir -p "$DEST_IMG_DIR" + +# --------------------------------------------------------------------------- +# 1. Convert Markdown -> HTML fragment +# --------------------------------------------------------------------------- +echo "[1/3] Conversie Markdown -> HTML..." +pandoc "$SRC_MD" \ + -t html5 \ + --no-highlight \ + --wrap=none \ + -o "$DEST_HTML" +echo " ✓ $(basename "$DEST_HTML")" + +# --------------------------------------------------------------------------- +# 2. Copy screenshots and rewrite their paths for Flask's static route +# --------------------------------------------------------------------------- +echo +echo "[2/3] Copiere capturi de ecran si rescriere cai..." +cp "$SRC_IMG_DIR"/*.png "$DEST_IMG_DIR"/ 2>/dev/null || { + echo " ⚠ Nicio captura gasita in $SRC_IMG_DIR" +} +COUNT=$(ls -1 "$DEST_IMG_DIR"/*.png 2>/dev/null | wc -l) +echo " ✓ $COUNT capturi copiate" + +# Markdown references images as "screenshots/x.png"; the app serves them from +# /static/help/screenshots/, so the prefix has to be made explicit. +sed -i 's|src="screenshots/|src="/static/help/screenshots/|g' "$DEST_HTML" +REFS=$(grep -c '/static/help/screenshots/' "$DEST_HTML" || true) +echo " ✓ $REFS referinte de imagini rescrise" + +# --------------------------------------------------------------------------- +# 3. Sanity check: every referenced image must exist +# --------------------------------------------------------------------------- +echo +echo "[3/3] Verificare consistenta..." +MISSING=0 +while IFS= read -r ref; do + [ -z "$ref" ] && continue + if [ ! -f "$DEST_IMG_DIR/$(basename "$ref")" ]; then + echo " ✗ lipsa: $ref" + MISSING=$((MISSING + 1)) + fi +done < <(grep -oE '/static/help/screenshots/[^"]+' "$DEST_HTML" | sort -u || true) + +if [ "$MISSING" -eq 0 ]; then + echo " ✓ toate imaginile referite exista" +else + echo " ⚠ $MISSING imagini lipsa" +fi + +echo +echo "============================================================" +echo " Gata. Rebuild imaginea pentru a aplica modificarile:" +echo " cd $PROJECT_DIR && docker compose up -d --build" +echo "============================================================" diff --git a/documentatie/convert_manual.sh b/documentatie/convert_manual.sh new file mode 100755 index 0000000..6210b4a --- /dev/null +++ b/documentatie/convert_manual.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# ============================================================================ +# convert_manual.sh - Converteste manualul DigiServer in format DOCX +# ---------------------------------------------------------------------------- +# Genereaza un document Word cu: +# - Cuprins automat +# - Secțiuni numerotate +# - Capturi de ecran incluse (din folderul screenshots/) +# +# Utilizare: +# ./convert_manual.sh +# ============================================================================ +set -e + +cd "$(dirname "$0")" + +echo "============================================================" +echo " Conversie Manual DigiServer -> DOCX" +echo "============================================================" +echo + +# --------------------------------------------------------------------------- +# Verificare Pandoc +# --------------------------------------------------------------------------- +if ! command -v pandoc &> /dev/null; then + echo "✗ Pandoc nu este instalat." + echo + echo " Instalati cu:" + echo " sudo apt-get update && sudo apt-get install -y pandoc" + echo + exit 1 +fi + +echo "✓ Pandoc detectat: $(pandoc --version | head -1)" +echo + +# --------------------------------------------------------------------------- +# Verificare fisiere sursa +# --------------------------------------------------------------------------- +if [ ! -f "Manual-Utilizare-DigiServer.md" ]; then + echo "✗ Fisierul Manual-Utilizare-DigiServer.md nu a fost gasit." + exit 1 +fi +echo "✓ Manual gasit" + +mkdir -p screenshots +SCREENSHOT_COUNT=$(ls -1 screenshots/*.png screenshots/*.jpg 2>/dev/null | wc -l) +echo "✓ Capturi de ecran disponibile: $SCREENSHOT_COUNT" +if [ "$SCREENSHOT_COUNT" -eq 0 ]; then + echo " (Nu exista capturi - documentul va fi generat doar cu text)" +fi +echo + +# --------------------------------------------------------------------------- +# Conversie +# --------------------------------------------------------------------------- +echo "Conversie in curs..." +echo + +pandoc Manual-Utilizare-DigiServer.md \ + --toc \ + --toc-depth=2 \ + --number-sections \ + --resource-path=screenshots \ + --metadata title="Manual de Utilizare – DigiServer v2" \ + --metadata lang="ro-RO" \ + -o Manual-Utilizare-DigiServer.docx + +# --------------------------------------------------------------------------- +# Verificare rezultat +# --------------------------------------------------------------------------- +echo +if [ -f "Manual-Utilizare-DigiServer.docx" ]; then + echo "============================================================" + echo " ✓ Document creat cu succes!" + echo "============================================================" + ls -lh Manual-Utilizare-DigiServer.docx + echo + echo "Deschideti cu: libreoffice Manual-Utilizare-DigiServer.docx" + echo " sau deschideti in Microsoft Word." +else + echo "✗ Eroare: documentul nu a fost creat." + exit 1 +fi diff --git a/restore_database.sh b/restore_database.sh new file mode 100755 index 0000000..c4908de --- /dev/null +++ b/restore_database.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# ============================================================================ +# DigiServer - Database Restore +# ---------------------------------------------------------------------------- +# Restores a database snapshot created by ./backup_players_playlists.sh. +# +# Usage: +# ./restore_database.sh # restore the latest backup +# ./restore_database.sh 20260915_143000 # restore a specific backup ID +# ./restore_database.sh --list # list available backups +# ./restore_database.sh --skip-migrations +# +# Typical use: run AFTER upgrading the Docker image / docker host. +# ============================================================================ +set -euo pipefail + +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE="docker compose -f $PROJECT_DIR/docker-compose.yml" +BACKUP_ROOT="$PROJECT_DIR/backups" +DB_HOST="$PROJECT_DIR/data/instance/dashboard.db" + +SKIP_MIGRATIONS=0 +BACKUP_ID="" +for arg in "$@"; do + case "$arg" in + --list) ls -1 "$BACKUP_ROOT" 2>/dev/null | sort || echo "(no backups found)"; exit 0 ;; + --skip-migrations) SKIP_MIGRATIONS=1 ;; + -*) echo "Unknown option: $arg"; exit 1 ;; + *) BACKUP_ID="$arg" ;; + esac +done + +if [ -z "$BACKUP_ID" ]; then + BACKUP_ID="$(ls -1 "$BACKUP_ROOT" 2>/dev/null | sort | tail -1 || true)" +fi +if [ -z "$BACKUP_ID" ]; then + echo "ERROR: no backups found in $BACKUP_ROOT" + exit 1 +fi + +DEST="$BACKUP_ROOT/$BACKUP_ID" +if [ ! -d "$DEST" ]; then + echo "ERROR: backup '$BACKUP_ID' not found in $BACKUP_ROOT" + echo "Available:" + ls -1 "$BACKUP_ROOT" 2>/dev/null | sed 's/^/ /' + exit 1 +fi + +echo "============================================================" +echo " DigiServer database restore" +echo " Backup: $BACKUP_ID" +echo "============================================================" + +# --------------------------------------------------------------------------- +# 1. Verify integrity +# --------------------------------------------------------------------------- +if [ -f "$DEST/SHA256SUMS" ]; then + echo + echo "[1/6] Verifying checksums..." + ( cd "$DEST" && sha256sum -c SHA256SUMS ) +else + echo + echo "[1/6] No SHA256SUMS found, skipping verification" +fi + +# --------------------------------------------------------------------------- +# 2. Stop the app (so nothing writes during restore) +# --------------------------------------------------------------------------- +echo +echo "[2/6] Stopping application container..." +$COMPOSE stop digiserver-app + +# --------------------------------------------------------------------------- +# 3. Back up the CURRENT database before overwriting it +# --------------------------------------------------------------------------- +if [ -f "$DB_HOST" ]; then + SAFETY="$BACKUP_ROOT/pre_restore_$(date +%Y%m%d_%H%M%S)_dashboard.db" + echo + echo "[3/6] Saving current DB as a safety copy -> $(basename "$SAFETY")" + cp "$DB_HOST" "$SAFETY" +else + echo + echo "[3/6] No existing DB to preserve" +fi + +# --------------------------------------------------------------------------- +# 4. Restore the snapshot +# --------------------------------------------------------------------------- +echo +echo "[4/6] Restoring database snapshot..." +if [ -f "$DEST/dashboard.db.gz" ]; then + gunzip -c "$DEST/dashboard.db.gz" > "$DB_HOST" +elif [ -f "$DEST/dashboard.db" ]; then + cp "$DEST/dashboard.db" "$DB_HOST" +else + echo "ERROR: no dashboard.db(.gz) in backup $BACKUP_ID" + exit 1 +fi + +# Remove any stale journal left over from the old DB +rm -f "$DB_HOST-journal" "$DB_HOST-wal" "$DB_HOST-shm" + +# Ownership: container runs as uid 1000; host files are pi:pi (1000) +if [ "$(id -u)" -eq 0 ]; then + chown 1000:1000 "$DB_HOST" +else + sudo chown 1000:1000 "$DB_HOST" +fi +chmod 644 "$DB_HOST" +echo " -> restored $(du -h "$DB_HOST" | cut -f1)" + +# --------------------------------------------------------------------------- +# 5. Start the (upgraded) app +# --------------------------------------------------------------------------- +echo +echo "[5/6] Starting application..." +$COMPOSE up -d --build +sleep 8 + +# --------------------------------------------------------------------------- +# 6. Re-run migrations so any new schema is applied to the restored data +# --------------------------------------------------------------------------- +if [ "$SKIP_MIGRATIONS" -eq 0 ]; then + echo + echo "[6/6] Re-running migrations..." + for m in add_https_config_table add_player_user_table add_email_to_https_config migrate_player_user_global; do + if $COMPOSE exec -T digiserver-app test -f "/app/migrations/$m.py"; then + echo " - $m" + $COMPOSE exec -T digiserver-app python "/app/migrations/$m.py" || \ + echo " (warning: $m reported an issue - often means it was already applied)" + fi + done +else + echo + echo "[6/6] Migrations skipped (--skip-migrations)" +fi + +# --------------------------------------------------------------------------- +# Verify +# --------------------------------------------------------------------------- +echo +echo "Verification:" +$COMPOSE exec -T digiserver-app python -c " +import sqlite3 +c = sqlite3.connect('/app/instance/dashboard.db') +for t in ['player','playlist','playlist_content']: + try: + print(' %-18s %d' % (t, c.execute('SELECT COUNT(*) FROM \"%s\"' % t).fetchone()[0])) + except Exception as e: + print(' %-18s ERROR %s' % (t, e)) +" + +echo +echo "============================================================" +echo " Restore complete: $BACKUP_ID" +echo "============================================================"