Mobile responsiveness + IP allow list comments
Mobile improvements: - Fix overflow issues with global max-width/overflow-x hidden - Stack ticket detail selects on mobile instead of one long row - Compact header: hide less important buttons, scrollable right side - Stat cards in 2-column grid on mobile - Force flex-wrap on inline-styled flex containers - Hide subtitle and user-info on small phones - Ticket selects full-width on small phones IP allow list: - Support # comments after IP addresses (e.g. "192.168.1.1 # Office VPN") - Updated placeholder with comment examples Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
9
api.php
9
api.php
@@ -162,7 +162,14 @@ function getClientIp(): string {
|
|||||||
function isIpAllowed(string $ip, string $allowedIps): bool {
|
function isIpAllowed(string $ip, string $allowedIps): bool {
|
||||||
$allowedIps = trim($allowedIps);
|
$allowedIps = trim($allowedIps);
|
||||||
if ($allowedIps === '' || strtolower($allowedIps) === 'kaikki') return true;
|
if ($allowedIps === '' || strtolower($allowedIps) === 'kaikki') return true;
|
||||||
$entries = preg_split('/[\s,]+/', $allowedIps, -1, PREG_SPLIT_NO_EMPTY);
|
// Tukee kommentteja: "192.168.1.1 # Yritys VPN" — risuaidan jälkeinen osa ohitetaan
|
||||||
|
$lines = preg_split('/\r?\n/', $allowedIps);
|
||||||
|
$entries = [];
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
$line = preg_replace('/#.*$/', '', $line); // Poista kommentti
|
||||||
|
$parts = preg_split('/[\s,]+/', trim($line), -1, PREG_SPLIT_NO_EMPTY);
|
||||||
|
foreach ($parts as $p) $entries[] = $p;
|
||||||
|
}
|
||||||
|
|
||||||
// Normalisoi IP: IPv4-mapped IPv6 (::ffff:1.2.3.4) → myös IPv4 muotoon
|
// Normalisoi IP: IPv4-mapped IPv6 (::ffff:1.2.3.4) → myös IPv4 muotoon
|
||||||
$ipBin = @inet_pton($ip);
|
$ipBin = @inet_pton($ip);
|
||||||
|
|||||||
@@ -1726,8 +1726,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="company-allowed-ips-section" class="form-group" style="margin-top:1rem;display:none;">
|
<div id="company-allowed-ips-section" class="form-group" style="margin-top:1rem;display:none;">
|
||||||
<label style="font-weight:600;font-size:0.9rem;">Sallitut IP-osoitteet</label>
|
<label style="font-weight:600;font-size:0.9rem;">Sallitut IP-osoitteet</label>
|
||||||
<textarea id="company-edit-allowed-ips" rows="3" style="font-family:monospace;font-size:0.85rem;" placeholder="192.168.1.100 10.0.0.0/8"></textarea>
|
<textarea id="company-edit-allowed-ips" rows="4" style="font-family:monospace;font-size:0.85rem;" placeholder="192.168.1.100 # Toimisto 10.0.0.0/8 # Yritys VPN 85.76.123.45 # Jukan koti"></textarea>
|
||||||
<small style="color:#888;">Yksi IP tai CIDR per rivi. "kaikki" = ei rajoitusta.</small>
|
<small style="color:#888;">Yksi IP tai CIDR per rivi. Kommentti #-merkin jälkeen. "kaikki" = ei rajoitusta.</small>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn-primary" id="btn-save-company-settings" style="font-size:0.85rem;">Tallenna asetukset</button>
|
<button class="btn-primary" id="btn-save-company-settings" style="font-size:0.85rem;">Tallenna asetukset</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
150
style.css
150
style.css
@@ -1223,6 +1223,156 @@ span.empty {
|
|||||||
html {
|
html {
|
||||||
overscroll-behavior: none;
|
overscroll-behavior: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === GLOBAALI OVERFLOW-ESTO === */
|
||||||
|
body, #app, .main-container, .tab-content {
|
||||||
|
max-width: 100vw;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === HEADER: hamburger-tyylinen kompakti === */
|
||||||
|
header {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
scrollbar-width: none;
|
||||||
|
max-width: 60vw;
|
||||||
|
}
|
||||||
|
.header-right::-webkit-scrollbar { display: none; }
|
||||||
|
|
||||||
|
/* Piilota "Käyttäjät" ja "Yritykset" napit mobiilissa — käytettävissä valikosta */
|
||||||
|
#btn-users, #btn-companies {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-selector {
|
||||||
|
max-width: 120px;
|
||||||
|
font-size: 0.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TIKETTI DETAIL: selectit stackiin === */
|
||||||
|
#ticket-detail-header > div:first-child > div:last-child,
|
||||||
|
#ticket-detail-header div[style*="display:flex"][style*="gap:0.5rem"] {
|
||||||
|
flex-wrap: wrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ticket-detail-header select,
|
||||||
|
#ticket-detail-header button {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 48%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TAULUKOT: piilota vähemmän tärkeitä kolumneja === */
|
||||||
|
table {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === CHAT/VIESTIT: kompaktimpi === */
|
||||||
|
.ticket-message {
|
||||||
|
padding: 0.6rem !important;
|
||||||
|
margin-bottom: 0.5rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticket-message .msg-header {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === INLINE-TYYLIT YLIAJO: estä kiinteät leveydet === */
|
||||||
|
[style*="min-width:"] {
|
||||||
|
min-width: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[style*="width:300px"],
|
||||||
|
[style*="width:350px"],
|
||||||
|
[style*="width:400px"],
|
||||||
|
[style*="width:500px"],
|
||||||
|
[style*="width:600px"] {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TAGIT & BADGET: wrappaa === */
|
||||||
|
[style*="display:flex"][style*="gap"] {
|
||||||
|
flex-wrap: wrap !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === TOOLBAR: kompaktimpi === */
|
||||||
|
.toolbar {
|
||||||
|
gap: 0.4rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar select,
|
||||||
|
.toolbar input,
|
||||||
|
.toolbar button {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === STAT CARDS: 2 per rivi === */
|
||||||
|
.sidebar-stats {
|
||||||
|
display: grid !important;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-stats .stat-card {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === LOMAKKEET: koko leveys === */
|
||||||
|
input, select, textarea {
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === ASIAKKAAN DETAIL: stackattu === */
|
||||||
|
.detail-grid {
|
||||||
|
grid-template-columns: 1fr !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === MODAALIT: enemmän scrollvaraa === */
|
||||||
|
.modal-content {
|
||||||
|
max-height: 90vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pieni puhelin - lisäoptimointeja */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
/* Tab-bar: ikoni-tyylinen */
|
||||||
|
.tab {
|
||||||
|
padding: 0.5rem 0.55rem;
|
||||||
|
font-size: 0.68rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header: erittäin kompakti */
|
||||||
|
.header-brand img {
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
.brand-icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Piilota käyttäjäinfo */
|
||||||
|
.user-info {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tiketti selectit: yksi per rivi */
|
||||||
|
#ticket-detail-header select,
|
||||||
|
#ticket-detail-header button {
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab bar */
|
/* Tab bar */
|
||||||
|
|||||||
Reference in New Issue
Block a user