feat: Laitteet-moduuli (inventaario) + sijaintien hallinta + login-fix

- Uusi "Laitteet" välilehti navigaatiossa (devices-moduuli)
  - Taulukko: Nimi, Hallintaosoite, Serial, Sijainti, Funktio, Tyyppi, Malli, Ping
  - Lisää/muokkaa/poista laitteita modaali-lomakkeella
  - Hakupalkki suodattaa kaikista kentistä
  - Ping-check täppä valmiina tulevaa toteutusta varten
- Sijainnit (Sites) -hallinta yrityksen asetuksissa
  - Lisää/muokkaa/poista sijainteja (toimipisteet, konesalit)
  - Sijainnit näkyvät laitelomakkeen dropdownissa
- Laitteet-moduuli lisätty moduulijärjestelmään (checkbox yritysasetuksissa)
- DB: sites + devices taulut, CRUD-funktiot
- Fix: Login-näkymä ei enää vilku refreshissä (piilotettu oletuksena)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 19:00:26 +02:00
parent a135aaaaef
commit 18d378be63
4 changed files with 546 additions and 3 deletions

View File

@@ -8,7 +8,7 @@
</head>
<body>
<!-- Login -->
<div id="login-screen" class="login-screen">
<div id="login-screen" class="login-screen" style="display:none">
<div class="login-box">
<img id="login-logo" src="" alt="Logo" style="height:48px;margin-bottom:0.75rem;display:none;">
<h1 id="login-title">Noxus Intra</h1>
@@ -79,6 +79,7 @@
<button class="tab" data-tab="support">Asiakaspalvelu</button>
<button class="tab active" data-tab="customers">Asiakkaat</button>
<button class="tab" data-tab="leads">Liidit</button>
<button class="tab" data-tab="devices">Laitteet</button>
<button class="tab" data-tab="archive">Arkisto</button>
<button class="tab" data-tab="changelog">Muutosloki</button>
<button class="tab" data-tab="settings" id="tab-settings" style="display:none">API</button>
@@ -192,6 +193,40 @@
</div>
</div>
<!-- Tab: Laitteet -->
<div class="tab-content" id="tab-content-devices">
<div class="main-container">
<div class="search-bar" style="display:flex;gap:0.5rem;align-items:center;">
<input type="text" id="device-search-input" placeholder="Hae laitteita..." style="flex:1;">
<button class="btn-primary" id="btn-add-device" style="white-space:nowrap;">+ Lisää laite</button>
</div>
<div class="table-card">
<table id="device-table">
<thead>
<tr>
<th data-sort="nimi">Nimi &#8597;</th>
<th>Hallintaosoite</th>
<th>Serial</th>
<th>Sijainti</th>
<th>Funktio</th>
<th>Tyyppi</th>
<th>Malli</th>
<th>Ping</th>
<th>Toiminnot</th>
</tr>
</thead>
<tbody id="device-tbody"></tbody>
</table>
<div id="no-devices" class="empty-state" style="display:none;">
<p>Ei laitteita vielä. Lisää ensimmäinen laite.</p>
</div>
</div>
<div class="summary-bar">
<span id="device-count">0 laitetta</span>
</div>
</div>
</div>
<!-- Tab: Arkisto -->
<div class="tab-content" id="tab-content-archive">
<div class="main-container">
@@ -620,6 +655,9 @@
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="leads"> Liidit
</label>
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="devices"> Laitteet
</label>
<label style="display:flex;align-items:center;gap:0.5rem;font-size:0.9rem;cursor:pointer;">
<input type="checkbox" data-module="archive" checked> Arkisto
</label>
@@ -689,6 +727,37 @@
</div>
</div>
</div>
<!-- Sijainnit (Sites) -->
<div class="table-card" style="padding:1.5rem;margin-top:1rem;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;">
<h3 style="color:#0f3460;margin:0;">Sijainnit</h3>
<button class="btn-primary" id="btn-add-site" style="font-size:0.85rem;">+ Lisää sijainti</button>
</div>
<p style="color:#888;font-size:0.85rem;margin-bottom:1rem;">Toimipisteet ja konesalit joihin laitteita voidaan sijoittaa.</p>
<div id="sites-list"></div>
<div id="site-form-container" style="display:none;margin-top:1rem;padding:1rem;background:#f8f9fb;border-radius:8px;">
<h4 style="color:#0f3460;margin-bottom:0.75rem;" id="site-form-title">Uusi sijainti</h4>
<input type="hidden" id="site-form-id">
<div class="form-grid" style="max-width:600px;">
<div class="form-group">
<label>Nimi *</label>
<input type="text" id="site-form-nimi" placeholder="esim. Konesali A">
</div>
<div class="form-group">
<label>Osoite</label>
<input type="text" id="site-form-osoite" placeholder="esim. Teollisuuskatu 5">
</div>
<div class="form-group">
<label>Kaupunki</label>
<input type="text" id="site-form-kaupunki" placeholder="esim. Helsinki">
</div>
</div>
<div style="display:flex;gap:0.5rem;margin-top:0.75rem;">
<button class="btn-primary" id="btn-save-site">Tallenna</button>
<button class="btn-secondary" id="btn-cancel-site">Peruuta</button>
</div>
</div>
</div>
<!-- Käyttäjäoikeudet -->
<div class="table-card" style="padding:1.5rem;margin-top:1rem;">
<h3 style="color:#0f3460;margin-bottom:0.5rem;">Käyttäjäoikeudet</h3>
@@ -705,6 +774,66 @@
</div>
<!-- Asiakas-modal -->
<!-- Laite-modaali -->
<div id="device-modal" class="modal" style="display:none">
<div class="modal-content modal-wide">
<div class="modal-header">
<h2 id="device-modal-title">Lisää laite</h2>
<button class="modal-close" id="device-modal-close">&times;</button>
</div>
<form id="device-form">
<input type="hidden" id="device-form-id">
<div class="form-grid">
<div class="form-group">
<label for="device-form-nimi">Nimi *</label>
<input type="text" id="device-form-nimi" required>
</div>
<div class="form-group">
<label for="device-form-hallintaosoite">Hallintaosoite</label>
<input type="text" id="device-form-hallintaosoite" placeholder="10.0.0.1 tai https://...">
</div>
<div class="form-group">
<label for="device-form-serial">Serial</label>
<input type="text" id="device-form-serial">
</div>
<div class="form-group">
<label for="device-form-site">Sijainti</label>
<select id="device-form-site">
<option value="">— Ei sijaintia —</option>
</select>
</div>
<div class="form-group">
<label for="device-form-funktio">Funktio</label>
<input type="text" id="device-form-funktio" placeholder="esim. Reititin, Kytkin, AP">
</div>
<div class="form-group">
<label for="device-form-tyyppi">Tyyppi</label>
<input type="text" id="device-form-tyyppi" placeholder="esim. L3-kytkin">
</div>
<div class="form-group">
<label for="device-form-malli">Malli</label>
<input type="text" id="device-form-malli" placeholder="esim. Cisco C9300">
</div>
<div class="form-group">
<label>Ping-check</label>
<label style="display:flex;align-items:center;gap:0.5rem;font-weight:normal;cursor:pointer;margin-top:0.25rem;">
<input type="checkbox" id="device-form-ping-check">
<span>Päällä</span>
</label>
</div>
<div class="form-group full-width">
<label for="device-form-lisatiedot">Lisätiedot</label>
<textarea id="device-form-lisatiedot" rows="3"></textarea>
</div>
</div>
<div class="form-actions" style="display:flex;gap:0.5rem;margin-top:1rem;">
<button type="submit" class="btn-primary">Tallenna</button>
<button type="button" class="btn-secondary" id="device-form-cancel">Peruuta</button>
</div>
</form>
</div>
</div>
<div id="customer-modal" class="modal" style="display:none">
<div class="modal-content modal-wide">
<div class="modal-header">