## Analytics — Live Activity Feed - Dedicated /stats/live standalone page (mirrors /stats/logs pattern) - Consistent 3-tab navigation across Statistics / Live Feed / Visit Logs - checkForUpdates() with skipRender(): O(1) MAX(id) poll — ~100-byte response on no-change - latestVisitId sentinel (-1) prevents unnecessary first-poll re-render - Cache key versioned by latestVisitId — fixes bug where concurrent users could permanently miss a visit due to stale thundering-herd cache - 3-second thundering-herd cache (key: url_id + date + filters + latestVisitId) - Country flags via flagcdn.com (precomputed in PHP, Alpine.js CSP-safe onerror) - time_ago precomputed in PHP — no Carbon::parse() double-instantiation in Blade - SELECT only 12 needed columns instead of SELECT *; limit 25 rows - wire:poll.5s.visible — polling stops when widget is off-screen ## Link Organization - Folders: one folder per link, clickable → filtered link list, link count badge - Tags: up to 5 tags per link, clickable → filtered link list, link count badge - Archiving: soft-archive links instead of permanent deletion; restorable ## REST API - Per-key API scopes: links:read-only (GET) / links:read-write (full CRUD) - Per-key rate limiting: individual requests/minute per API key ## Translations - Added stats_live_feed_poll_interval (EN: 'Updates every 5s', PL: 'Aktualizacja co 5s') ## Docs - README.md: corrected API scopes/rate-limiting docs (features were already implemented) - README.md: added Folders, Tags, Archiving to features list - README.md: added v5.0.0 changelog entry
125 lines
3.2 KiB
CSS
125 lines
3.2 KiB
CSS
@import "tailwindcss/theme";
|
|
@import "tailwindcss/utilities";
|
|
|
|
@source "../../src/**/*.php";
|
|
@source "../views/**/*.blade.php";
|
|
@source "packages/filament-short-url/src/**/*.php";
|
|
@source "packages/filament-short-url/resources/views/**/*.blade.php";
|
|
|
|
.short-url-card {
|
|
position: relative !important;
|
|
}
|
|
|
|
.short-url-card:hover {
|
|
z-index: 20 !important;
|
|
}
|
|
|
|
.short-url-card:focus-within {
|
|
z-index: 30 !important;
|
|
}
|
|
|
|
.short-url-card .fi-ta-actions {
|
|
position: absolute !important;
|
|
top: 1.25rem !important;
|
|
right: 1.25rem !important;
|
|
z-index: 10 !important;
|
|
margin: 0 !important;
|
|
padding: 0 !important;
|
|
}
|
|
|
|
.ab-test-slider {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.ab-test-slider .noUi-tooltip {
|
|
position: absolute;
|
|
top: -24px;
|
|
width: 30px;
|
|
height: 20px;
|
|
bottom: inherit !important;
|
|
padding: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 100px;
|
|
font-size: 12px;
|
|
background: #ffffff26;
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
/* 3-dot button trigger styling */
|
|
.action-trigger-btn {
|
|
border: 1px solid transparent !important;
|
|
background-color: transparent !important;
|
|
transition: all 0.2s ease-in-out;
|
|
}
|
|
|
|
/* On card hover, show a subtle border */
|
|
.short-url-card:hover .action-trigger-btn {
|
|
border-color: #e5e7eb !important;
|
|
background-color: #f9fafb !important;
|
|
}
|
|
|
|
.dark .short-url-card:hover .action-trigger-btn {
|
|
border-color: #374151 !important;
|
|
background-color: #1f2937 !important;
|
|
}
|
|
|
|
/* When the dropdown is open (trigger has focus or aria-expanded="true"), show active border */
|
|
.action-trigger-btn[aria-expanded="true"] {
|
|
border-color: #9ca3af !important;
|
|
background-color: #f3f4f6 !important;
|
|
box-shadow: 0 0 0 4px rgba(229, 230, 235, 0.5) !important;
|
|
}
|
|
|
|
.dark .action-trigger-btn[aria-expanded="true"] {
|
|
border-color: #4b5563 !important;
|
|
background-color: #111827 !important;
|
|
box-shadow: 0 0 0 4px rgba(55, 65, 81, 0.5) !important;
|
|
}
|
|
|
|
.custom-fused .fi-input-wrp {
|
|
border: 0 !important;
|
|
}
|
|
|
|
/* Ukrycie strzałki rozwijania selecta, gdy jest zablokowany */
|
|
select.fi-select-input:disabled,
|
|
.fi-select-input .fi-select-input-btn[disabled],
|
|
.fi-select-input .fi-select-input-btn.fi-disabled {
|
|
background-image: none !important;
|
|
padding-right: 0.75rem !important;
|
|
}
|
|
|
|
/* Folder Card overrides to reset default Filament record-content padding and force height/width stretch */
|
|
.folder-card .fi-ta-record-content,
|
|
.folder-card .fi-ta-record-content-ctn {
|
|
padding-left: 0 !important;
|
|
padding-right: 0 !important;
|
|
padding-top: 0 !important;
|
|
padding-bottom: 0 !important;
|
|
height: 100% !important;
|
|
width: 100% !important;
|
|
}
|
|
|
|
.folder-card .fi-ta-record-content {
|
|
display: flex !important;
|
|
flex-direction: column !important;
|
|
}
|
|
|
|
/* Position action buttons absolute on the card wrapper to keep dropdown aligned */
|
|
.folder-card .fi-ta-actions {
|
|
position: absolute !important;
|
|
top: 1rem !important;
|
|
right: 1rem !important;
|
|
z-index: 20 !important;
|
|
margin: 0 !important;
|
|
padding: 0 !important;
|
|
}
|
|
|
|
/* Force height down the Filament table layout tree so justify-between works */
|
|
.folder-card .fi-ta-stack,
|
|
.folder-card .fi-ta-stack > div,
|
|
.folder-card .fi-ta-text,
|
|
.folder-card .fi-ta-text > div {
|
|
height: 100% !important;
|
|
} |