Versioiva dokumentinhallinta + Laitetilat-moduuli

Dokumentit: versioiva tiedostonhallinta asiakkaille (sopimukset, laskut, ohjeet).
Sisältää versiohistorian, tiedostojen latauksen/palautuksen ja asiakas-suodatuksen.

Laitetilat: laitetilojen hallinta kuvagallerialla ja tiedostolistauksella.
Sisältää korttipohjaisen listanäkymän, kuvien esikatselun ja tiedostojen hallinnan.

Molemmat moduulit: 4 DB-taulua, 14 API-endpointtia, täysi CRUD, tiedostoupload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 15:18:32 +02:00
parent 093f40ac09
commit e6fa65165e
5 changed files with 1612 additions and 2 deletions

View File

@@ -82,6 +82,8 @@
<button class="tab active" data-tab="customers">Asiakkaat</button>
<button class="tab" data-tab="leads">Liidit</button>
<button class="tab" data-tab="tekniikka">Tekniikka</button>
<button class="tab" data-tab="documents">Dokumentit</button>
<button class="tab" data-tab="laitetilat">Laitetilat</button>
<button class="tab" data-tab="ohjeet">Ohjeet</button>
<button class="tab" data-tab="archive">Arkisto</button>
<button class="tab" data-tab="changelog">Muutosloki</button>
@@ -725,6 +727,242 @@
</div>
</div>
<!-- Tab: Dokumentit -->
<div class="tab-content" id="tab-content-documents">
<div class="main-container">
<!-- Listanäkymä -->
<div id="docs-list-view">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:0.5rem;">
<h3 style="color:var(--primary-dark);margin:0;">📄 Dokumentit</h3>
<button class="btn-primary" id="btn-new-document">+ Uusi dokumentti</button>
</div>
<div style="display:flex;gap:0.5rem;margin-bottom:1rem;flex-wrap:wrap;">
<input type="text" id="doc-search" placeholder="Hae dokumentteja..." style="flex:1;min-width:150px;">
<select id="doc-filter-customer" style="min-width:140px;">
<option value="">Kaikki asiakkaat</option>
</select>
<select id="doc-filter-category" style="min-width:120px;">
<option value="">Kaikki kategoriat</option>
<option value="sopimus">Sopimus</option>
<option value="lasku">Lasku</option>
<option value="ohje">Ohje</option>
<option value="raportti">Raportti</option>
<option value="muu">Muu</option>
</select>
</div>
<div class="table-card">
<table id="docs-table">
<thead>
<tr>
<th>Otsikko</th>
<th>Asiakas</th>
<th>Kategoria</th>
<th>Versio</th>
<th>Päivitetty</th>
<th>Lataaja</th>
</tr>
</thead>
<tbody id="docs-tbody"></tbody>
</table>
<div id="no-docs" class="empty-state" style="display:none;">
<div class="empty-icon">📄</div>
<p>Ei dokumentteja vielä.</p>
<p class="empty-hint">Klikkaa "+ Uusi dokumentti" aloittaaksesi.</p>
</div>
</div>
</div>
<!-- Lukunäkymä -->
<div id="doc-read-view" style="display:none;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:0.5rem;">
<button class="btn-secondary" id="btn-doc-back">← Takaisin</button>
<div style="display:flex;gap:0.5rem;">
<button class="btn-primary" id="btn-doc-edit">✏️ Muokkaa</button>
<button class="btn-danger" id="btn-doc-delete" style="display:none;">🗑 Poista</button>
</div>
</div>
<div class="table-card" style="padding:1.5rem;">
<h2 id="doc-read-title" style="margin:0 0 0.5rem;color:var(--primary-dark);"></h2>
<div style="display:flex;gap:1rem;flex-wrap:wrap;margin-bottom:1rem;font-size:0.85rem;color:#666;">
<span id="doc-read-customer"></span>
<span id="doc-read-category"></span>
<span id="doc-read-version"></span>
<span id="doc-read-date"></span>
</div>
<p id="doc-read-description" style="color:#555;margin-bottom:1.5rem;"></p>
<!-- Nykyisen version lataus -->
<div style="margin-bottom:1.5rem;">
<button class="btn-primary" id="btn-doc-download" style="font-size:1rem;padding:0.7rem 1.5rem;">⬇️ Lataa tiedosto</button>
</div>
<!-- Uusi versio -->
<div style="background:#f8f9fb;padding:1rem;border-radius:10px;margin-bottom:1.5rem;">
<h4 style="margin:0 0 0.75rem;color:var(--primary-dark);">Lataa uusi versio</h4>
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:end;">
<input type="file" id="doc-version-file" style="flex:1;min-width:200px;">
<input type="text" id="doc-version-notes" placeholder="Muistiinpanot (valinnainen)" style="flex:1;min-width:200px;">
<button class="btn-primary" id="btn-doc-upload-version">Lataa</button>
</div>
</div>
<!-- Versiohistoria -->
<h4 style="color:var(--primary-dark);margin-bottom:0.5rem;">Versiohistoria</h4>
<div class="table-card" style="margin:0;">
<table id="doc-versions-table">
<thead>
<tr>
<th>Versio</th>
<th>Päivämäärä</th>
<th>Lataaja</th>
<th>Muistiinpanot</th>
<th>Koko</th>
<th>Toiminnot</th>
</tr>
</thead>
<tbody id="doc-versions-tbody"></tbody>
</table>
</div>
</div>
</div>
<!-- Muokkausnäkymä -->
<div id="doc-edit-view" style="display:none;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;">
<button class="btn-secondary" id="btn-doc-edit-back">← Takaisin</button>
</div>
<div class="table-card" style="padding:1.5rem;">
<h3 style="color:var(--primary-dark);margin:0 0 1rem;" id="doc-edit-title">Uusi dokumentti</h3>
<form id="doc-edit-form">
<input type="hidden" id="doc-edit-id">
<div class="form-grid" style="grid-template-columns:1fr 1fr;">
<div class="form-group">
<label>Otsikko *</label>
<input type="text" id="doc-edit-name" required placeholder="Esim. Palvelusopimus">
</div>
<div class="form-group">
<label>Kategoria</label>
<select id="doc-edit-category">
<option value="sopimus">Sopimus</option>
<option value="lasku">Lasku</option>
<option value="ohje">Ohje</option>
<option value="raportti">Raportti</option>
<option value="muu">Muu</option>
</select>
</div>
<div class="form-group">
<label>Asiakas (valinnainen)</label>
<select id="doc-edit-customer">
<option value="">Ei asiakasta (yleinen)</option>
</select>
</div>
<div class="form-group">
<label>Tiedosto</label>
<input type="file" id="doc-edit-file">
</div>
<div class="form-group full-width">
<label>Kuvaus</label>
<textarea id="doc-edit-description" rows="3" placeholder="Dokumentin kuvaus..."></textarea>
</div>
</div>
<div style="margin-top:1rem;display:flex;gap:0.5rem;">
<button type="submit" class="btn-primary">Tallenna</button>
<button type="button" class="btn-secondary" id="btn-doc-edit-cancel">Peruuta</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Tab: Laitetilat -->
<div class="tab-content" id="tab-content-laitetilat">
<div class="main-container">
<!-- Listanäkymä -->
<div id="laitetilat-list-view">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:0.5rem;">
<h3 style="color:var(--primary-dark);margin:0;">🏢 Laitetilat</h3>
<button class="btn-primary" id="btn-new-laitetila">+ Uusi laitetila</button>
</div>
<div id="laitetilat-grid" class="laitetilat-grid"></div>
<div id="no-laitetilat" class="empty-state" style="display:none;">
<div class="empty-icon">🏢</div>
<p>Ei laitetiloja vielä.</p>
<p class="empty-hint">Klikkaa "+ Uusi laitetila" aloittaaksesi.</p>
</div>
</div>
<!-- Lukunäkymä -->
<div id="laitetila-read-view" style="display:none;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;flex-wrap:wrap;gap:0.5rem;">
<button class="btn-secondary" id="btn-laitetila-back">← Takaisin</button>
<div style="display:flex;gap:0.5rem;">
<button class="btn-primary" id="btn-laitetila-edit">✏️ Muokkaa</button>
<button class="btn-danger" id="btn-laitetila-delete" style="display:none;">🗑 Poista</button>
</div>
</div>
<div class="table-card" style="padding:1.5rem;">
<h2 id="laitetila-read-nimi" style="margin:0 0 0.25rem;color:var(--primary-dark);"></h2>
<p id="laitetila-read-osoite" style="color:#888;font-size:0.9rem;margin-bottom:1rem;"></p>
<p id="laitetila-read-kuvaus" style="color:#555;margin-bottom:1.5rem;white-space:pre-wrap;"></p>
<!-- Tiedostojen lataus -->
<div style="background:#f8f9fb;padding:1rem;border-radius:10px;margin-bottom:1.5rem;">
<h4 style="margin:0 0 0.75rem;color:var(--primary-dark);">Lisää tiedosto</h4>
<div style="display:flex;gap:0.5rem;flex-wrap:wrap;align-items:end;">
<input type="file" id="laitetila-file-input" multiple style="flex:1;min-width:200px;">
<input type="text" id="laitetila-file-desc" placeholder="Kuvaus (valinnainen)" style="flex:1;min-width:200px;">
<button class="btn-primary" id="btn-laitetila-upload">Lataa</button>
</div>
</div>
<!-- Kuvagalleria -->
<div id="laitetila-gallery" style="display:none;margin-bottom:1.5rem;">
<h4 style="color:var(--primary-dark);margin-bottom:0.5rem;">Kuvat</h4>
<div id="laitetila-gallery-grid" class="gallery-grid"></div>
</div>
<!-- Muut tiedostot -->
<div id="laitetila-files-section" style="display:none;">
<h4 style="color:var(--primary-dark);margin-bottom:0.5rem;">Tiedostot</h4>
<div id="laitetila-files-list"></div>
</div>
</div>
</div>
<!-- Muokkausnäkymä -->
<div id="laitetila-edit-view" style="display:none;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;">
<button class="btn-secondary" id="btn-laitetila-edit-back">← Takaisin</button>
</div>
<div class="table-card" style="padding:1.5rem;">
<h3 style="color:var(--primary-dark);margin:0 0 1rem;" id="laitetila-edit-title">Uusi laitetila</h3>
<form id="laitetila-edit-form">
<input type="hidden" id="laitetila-edit-id">
<div class="form-grid" style="grid-template-columns:1fr 1fr;">
<div class="form-group">
<label>Nimi *</label>
<input type="text" id="laitetila-edit-nimi" required placeholder="Esim. Keskuskatu 5 - Kellari">
</div>
<div class="form-group">
<label>Osoite</label>
<input type="text" id="laitetila-edit-osoite" placeholder="Katuosoite">
</div>
<div class="form-group full-width">
<label>Kuvaus</label>
<textarea id="laitetila-edit-kuvaus" rows="4" placeholder="Laitetilan kuvaus..."></textarea>
</div>
</div>
<div style="margin-top:1rem;display:flex;gap:0.5rem;">
<button type="submit" class="btn-primary">Tallenna</button>
<button type="button" class="btn-secondary" id="btn-laitetila-edit-cancel">Peruuta</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Tab: Muutosloki -->
<div class="tab-content" id="tab-content-changelog">
<div class="main-container">
@@ -1161,6 +1399,12 @@
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="todo"> Tehtävät
</label>
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="documents"> Dokumentit
</label>
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="laitetilat"> Laitetilat
</label>
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="settings" checked> Asetukset / API
</label>