Commit graph

105 commits

Author SHA1 Message Date
3fa41c25a3 feat(status): 24-hour activity sparklines on worker pulse cards
Each worker card on /status now renders a stacked-bar histogram of the
last 24 hourly buckets — successes from the bottom up in primary blue,
failures from the top down in destructive red, idle hours as a thin
baseline.  Heights normalise to the loudest hour in the series so quiet
workers still show shape.

- /api/status/workers: extended the response with activity24h per
  worker, computed via a generate_series CTE joined to analyzer_jobs /
  rmm_executions / sync_history (zero-fill so the 24-bucket shape is
  consistent regardless of activity).
- ActivitySparkline (components/status/activity-sparkline.tsx) — pure
  flex-end bar strip, no recharts dependency, 32px tall by default.
- WorkerPulse renders the strip below the in-flight / 1h tiles with
  "24h ago" / "now" labels.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:03:54 -04:00
e1427b62d7 feat(admin): DB-backed integration toggles + sticky cols + dark contrast
Builds on the env-var INTEGRATIONS_DISABLED shipped with the nav-design
overhaul.  Adds a DB-backed admin UI so operators can flip integrations
without editing .env and restarting the container, plus the remaining
visual cleanup items from the design backlog.

Integration toggles
- Migration 081 — integration_settings table (key PK, disabled flag,
  reason, disabled_by audit, disabled_at).  Seeded with all 13 known
  integrations as enabled.
- GET / PATCH /api/admin/integrations — gated by requirePermission
  (admin, access).  PATCH clears the in-process integration-health
  cache so toggles take effect within seconds.
- /admin/integrations admin page with a Switch per integration, optional
  reason input, audit-info subtitle (disabled by, when, why), live
  status light from /api/dashboard/integration-health.
- integration-health service merges env-var disable list with DB rows;
  degrades gracefully if migration unapplied / DB unreachable.
- Wired into the Admin nav dropdown (eight items now).
- CLAUDE.md describes both env + DB sources.

Sticky first column on tables
- Table primitive accepts stickyFirstColumn?: boolean.  When true, TH
  and TD :first-child stay pinned during horizontal scroll, with
  background inheritance preserving hover and selected row tints.
- DataTable exposes the prop too — on by default for paginated tables.
- /addigy-devices opts in.

Dark-mode contrast
- --border lifted from 10% to 14% in .dark; --input from 15% to 18%;
  --sidebar-border to 14%.
- StatusLight outline ring lifted from /10 to /15 (light) and /20 (dark).
- DetailModal empty-cell em-dash lifted from /40 to /70 so missing
  values are legible on dark surfaces.

DESIGN.md
- Closed sticky-first-column, dark-mode contrast, and palette-audit
  items (palette deprioritized — most uses are semantic).
- Skeleton helpers documented as preferred for new code; existing
  ad-hoc patterns left in place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 09:55:22 -04:00
9bfb57553d feat(design): nav/visual overhaul — brand layer, /status route, KPI dashboard, TanStack DataTable
Major UI refresh on the nav-design-improvements branch.  Drops 2013-era
inline styles and consolidates patterns behind shared primitives.

Foundation
- New Wulf brand layer in app/styles/brand.css repointing --primary to
  the standards-guide blue (#0075AD) with utility classes for numerics
  (.num / .num-lg / .num-xl), metric labels, surface tints, and the
  wolf-mark watermark
- Switch primary face to IBM Plex Sans + IBM Plex Mono via next/font;
  Helvetica/Arial stays in the fallback chain for brand fidelity
- Wordmark subtitle changed from "PSA Management System" to
  "Operations console" everywhere it appeared
- Tagline footer ("Don't be afraid to cry") on every non-mobile page

Status moved out of /dashboard
- New /status route with integration tiles grouped by category, sync
  health table, worker pulse cards (analyzer / RMM / sync scheduler),
  token-expiry section, conditional alert banner
- Top-bar StatusIndicator polls integration health every 60s and links
  to /status
- INTEGRATIONS_DISABLED env var suppresses operator-disabled
  integrations (e.g. SentinelOne) — no failure noise from broken-on-
  purpose entries.  Aliases supported (sentinelone → s1, etc.)

Dashboard rebuilt around KPIs
- /api/dashboard/overview adds today snapshot (opened, resolved, open
  total, SLA breaches) with delta math
- /api/dashboard/trends backs queue × priority heatmap, 30-day volume
  area chart, 30-day mean resolution time line chart, today's active
  engineers leaderboard

Components
- StatusBadge driven by lib/status-registry.ts (priority, ticket
  status, classification, source, company type, publish, active /
  yes-no / billable / approved registries)
- StatusLight (8px geometric square, five states, three sizes)
- EmptyState (shared dashed panel with icon + headline + optional CTA)
- KpiCard with delta indicator and tonal left border
- WulfMark (mark / wordmark variants from /public/branding)
- Skeleton helpers (SkeletonRow / Rows / Card / Chart / Header / Table)

Navigation
- Admin flat link → dropdown with seven shortcuts
- New UserMenu (initials avatar, role badge, settings + sign-out)
- Active-route highlight is now a 2px Wulf-blue underline echoing the
  PageHeader rule (consistent across flat links and submenu triggers);
  active children inside dropdowns use bg-primary/10
- Submenu width is content-driven (min-w 320 / max-w 440, single col)
- Mobile hamburger via Sheet, reuses the same nav config

Pages migrated
- 16 admin sub-pages adopt PageHeader (with accent prop)
- /addigy-devices: shadcn Table + Checkbox; PageHeader; status badges
- 10 raw <table> blocks across admin/sync/* migrated to shadcn Table
- /veeam-analysis migrated to shadcn Table (kept its expansion logic)
- Detail routes (analyzer ticket, analyzer analysis) get breadcrumbs

DataTable
- Rewritten on @tanstack/react-table v8 in manual mode; external API
  unchanged so all 10+ data-browser pages keep working
- New optional props for drill-down rows: getRowCanExpand + renderSubRow

Mobile
- Multi-select Popover gets max-w-[calc(100vw-1rem)] and
  collisionPadding so dropdowns can't overflow narrow viewports
- CI filter bar wraps and shrinks; stat pill flows below

Docs
- New ARCHITECTURE.md (load-bearing reference for runtime, data flow,
  workers, analyzer pipeline, auth, deployment, gotchas)
- New DESIGN.md (tokens, layout, navigation IA, component vocabulary,
  rolling backlog of remaining cleanup)
- CLAUDE.md refreshed with pointers to the two new docs and the
  INTEGRATIONS_DISABLED operator config note
- shadcn registry registered as project-level MCP server (.mcp.json)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 09:33:13 -04:00
1112a06afe feat: RMM Overshell, IT Glue audit/write-back, LogLift, link-aware bundles, dashboard overhaul
- RMM Overshell (migration 077): admin page, dispatch UI, executor/worker, target
  resolver, script registry (AD/DHCP/DNS/event-log/services/software/network/loglift)
- LogLift evidence pipeline (migration 078): upload webhook, B2 storage client,
  receiver/matcher, EventLogCollector PowerShell script
- IT Glue audit + write-back (migrations 075, 076): asset-audit runner, ticket
  xrefs, applications/configurations browse pages + apply/revert/audit endpoints
- Link-aware analyzer bundles (migration 073) + provider toggle (migration 074):
  link-discovery service, OpenRouter LLM provider, related-tickets/itglue-suggestion
  panels, analyze-bundle endpoint
- Endpoint data model + device-link reconciliation (migrations 079, 080): conflicts
  admin page, reconciler service, resolve endpoints
- Dashboard overhaul: integration-health service + alerts, overview/health endpoints
- Permissions: add itglue + rmm scopes; middleware: public /api/rmm/loglift route

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:13:18 -04:00
98843a80ba fix(analyzer): multi-select option click swallowed by nested Radix button
Radix Checkbox renders as <button role="checkbox">, which we were nesting
inside the option <button>. Browsers can swallow the outer click in that
arrangement despite pointer-events-none on the inner element. Replaced the
option with <div role="option" tabIndex={0}> and an inline non-button
visual checkbox (square + Check icon when selected). Keyboard support
(Enter/Space) preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:26:50 -04:00
bd3401df1c feat(analyzer): Phase 2 — full stage persistence, fingerprints, aggregate reports, cost guards
Eight sub-phases per docs/ticket-analyzer-phase2-spec.md:

2.1 Schema (migration 070): analyzer_stage_executions table; source_snapshot,
    aggregate_fingerprint, fingerprint_generated_at columns on analyzer_analyses.
    model_traces marked LEGACY (kept for back-compat).
2.2 Every pipeline stage records a row to analyzer_stage_executions, success
    or failure. Worker persists a status='failed' analyzer_analyses row when
    the pipeline throws so partial stage records have a parent. Pipeline
    exposes raw triage/sonnet/opus responses for downstream stages.
2.3 Stage 3 prompt updated with markdown formatting rules + banned filler
    phrases. Added react-markdown + remark-gfm + @tailwindcss/typography.
    New <AnalysisMarkdown> component replaces <ProseText>; coerces stray
    headers to bold paragraphs.
2.4 Stage 6 fingerprint (Haiku) runs after persistence, failure-tolerant.
    scripts/backfill-fingerprints.ts reconstructs Stage 6 input from the
    legacy model_traces blob.
2.5 Browse UI rebuild at /analyzer/tickets: multi-select for client/issue/
    queue/status/priority/assignee, sticky filter bar, active-filter chips,
    bulk selection persisted via localStorage, "Analyze N selected" +
    "Generate aggregate report" actions. New <MultiSelect> primitive.
    Staleness uses last_activity_date > completed_at heuristic per spec C.1.
2.6 Aggregate reports (migration 071): runner is fire-and-forget, persists
    SQL distributions immediately so UI shows partial state during the
    Sonnet reduce call. Three endpoints, three pages (/analyzer/reports[/new
    /:id]). IT Glue context fetcher capped at 200 doc titles.
2.7 Cost guards (migration 072): per-request $5 confirmation, soft-warn at
    $20/day, hard-block at $50/day with ANALYZER_DAILY_COST_OVERRIDE_USERS
    override. Every gating decision audited.
2.8 Runbook + build notes updated.

128 vitest tests passing, tsc clean. Migrations 070/071/072 idempotent
(IF NOT EXISTS). model_traces double-write retained — drop in a future
migration once aggregate reports have soaked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:00:22 -04:00
b20c94ea1a feat(analyzer): browse-tickets page + analysis-view typography
- /analyzer/tickets — period chips (today/yesterday/this+last
  week/30d/60d/all), client + issue-type Selects, debounced search,
  per-row Analyze/Re-analyze plus View shortcut when an analysis
  already exists.
- API: /api/analyzer/tickets/list (period/companyId/issueType/search,
  paginated via COUNT(*) OVER) and /filter-options (companies that
  actually have tickets, active issue types).
- ProseText helper in analysis-view splits on blank lines and renders
  each chunk with leading-7 — Summary, Next Step, rationale, and
  Post-Resolution now have proper paragraph rhythm. Next Step card
  re-styled with bg-primary/5 tint, ArrowRight icon, and an indented
  rationale block.
- Top-level "Analyzer" nav menu (Browse Tickets + Needs Review).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:25:16 -04:00
ed3b363d02 feat(analyzer): phase 7 — share-via-email
sendAnalysisShareEmail() reuses the existing nodemailer SMTP transport
(same path as magic-link/invitation mail). Share route persists the
audit row first, then attempts send; on failure returns
{share, emailSent:false, emailError} at HTTP 200 so the audit log
stays intact. Modal surfaces send failures as a warning toast.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 11:03:11 -04:00
8f8b5ab7be feat: AI ticket analyzer (phases 1-6)
Multi-stage LLM pipeline that produces structured analyses of Autotask
tickets from local Postgres. Migration 069 + Zod schemas, Stage 0
preprocessor, IT Glue redaction + search, Anthropic SDK wrapper, Stages
1/3/4 (Haiku/Sonnet/Opus), pipeline + cost circuit breaker, job worker
(opt-in autostart), 6 API routes, 3 frontend pages, share-row
persistence (email send deferred to phase 7). 128 vitest tests, tsc
clean. Build journal in docs/wulf-pulse-ticket-analyzer-build-notes.md.

Sync: adds syncTicketNotes() + ticket_notes to ordered/date-filtered
entities so the analyzer's local mirror stays current via scheduler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 10:59:40 -04:00
ea3471d38d feat: Veeam RPO analysis, comparison, ticket analysis + company teams table
- Add Veeam RPO analysis page (/veeam-analysis) and comparison page (/veeam-comparison)
- Add API routes: /api/veeam/rpo-analyze, rpo-comparison, rpo-offline-log, ticket-analysis
- Add veeam-rpo-service.ts enhancements (RPO logic, offline detection, comparison)
- Add veeam-analysis-state.ts and rmm-device-resolver.ts services
- Add migrations 065-068: company_teams, veeam_rpo_offline_log, rpo_comparison_tables, veeam_ticket_analysis
- Add backup-status page updates and nav links for new Veeam pages
- Add scripts: deactivate-cis-for-inactive-companies, workstation category updates
- Add docs: mimecast-api-guide, veeam-backup-alerting-recommendation, workstation-backup-overview, ticket-analyzer-prompt
- Minor: webhook-service, entity-sync, entity-mapper, sync-helpers, sync.ts, middleware.ts updates
2026-04-29 09:16:46 -04:00
07067bef19 feat: Display Settings UI + Company Category/Type sync
- Add /admin/display-settings page with Kiosk and Mobile sections
- Company category checkbox filter + excluded companies searchable multi-select
- New DB tables: company_categories, company_types (migration 064)
- Sync COMPANY_CATEGORIES via CompanyCategories entity (id/name/isActive)
- Sync COMPANY_TYPES via Companies.companyType picklist
- Add to EntityType, ENTITY_DEPENDENCIES, sync-helpers, entity-mapper, entity-sync
- New API routes: /api/admin/display-settings (GET/POST), /api/data/company-categories, /api/data/companies-list
- Update all 4 routes (kiosk/stats, kiosk/activity, mobile/tickets, mobile/dashboard)
  to filter by kiosk_settings company_category_ids + excluded_company_ids
- Add Display Settings nav link (SlidersHorizontal icon) to Admin menu
- Seed kiosk_settings: kiosk_company_category_ids=1, mobile_company_category_ids=1
2026-04-06 09:03:19 -04:00
a98c0daf15 feat: classification labels in data browser + kiosk recurring revenue filter
- data-browser/companies: resolve classification picklist IDs to labels in
  table column and detail modal; also added to DetailModal COMPANY_GROUPS
- DetailModal: add 'classification' FieldType with color-coded badge map
- kiosk stats + activity: switch from label-based exclusion to ID-based
  allowlist (included_classifications). Only shows companies with
  classification IN (15,16,17,18,203,205,206,207,202,5,12)
  = managed service / recurring revenue tiers only
2026-03-30 14:56:02 -04:00
fea62382de feat: mobile nav page + suppress desktop header on /mobile/* routes
- AppNavigation returns null on /mobile/* (no more horizontal scroll)
- Mobile header: 'Pulse' title (links home) + Menu icon (links to /mobile/nav)
- /mobile/nav: full-screen nav page with touch-friendly cards
  - Mobile Views: Dashboard, Tickets, Finance (large icon cards)
  - Full Site: Quotes, Config Items, Backup, Engagement, Ticket Digest, Admin
  - Sign out button
- Bottom tab bar unchanged (Dashboard / Tickets / Finance)
2026-03-23 12:58:09 -04:00
011ae559de feat: Mail icon for Service Desk Notification notes (noteType=2), violet color 2026-03-23 11:57:39 -04:00
7872171035 fix: INTERNAL_PUBLISH 1->2 (publish=2 is Internal Users Only in Autotask) 2026-03-23 11:48:33 -04:00
ba493b708a fix: URLs display as 'link', hide internal notes (publish=1) by default with toggle 2026-03-23 11:42:03 -04:00
f0da6b203a feat: sticky modal header with Autotask icon + close X, remove bottom nav bar
- Header always visible: ticket icon, number, title (truncated), ExternalLink icon
  to Autotask, X close button — all in a fixed top bar
- showCloseButton={false} on DialogContent, replaced with custom header buttons
- Modal is now flex-col h-85vh: header shrinks-to-content, body scrolls
- Removed Close/Open in Autotask bottom action bar entirely
2026-03-23 11:30:31 -04:00
be61c30204 fix: correct Autotask URL format and strip bracket artifacts from link rendering 2026-03-23 11:24:54 -04:00
21a41ef8ef fix: URL-to-link rendering, fix horizontal overflow in timeline
- LinkedText component splits on newlines and converts raw URLs to clickable
  links showing just the hostname (e.g. 'ct.sendgrid.net' instead of full URL)
- [overflow-wrap:anywhere] on all text content (more aggressive than break-words)
- w-0 flex-1 on timeline item content divs to prevent flex children expanding
  past container boundary
- Applied to description, resolution, note bodies, time entry notes
2026-03-23 11:21:01 -04:00
df50c3868d fix: widen modal to 90vw/max-4xl, add break-words to prevent horizontal scroll 2026-03-23 11:15:52 -04:00
5dfd68affd perf: switch ticket modal from live API to Postgres
- New GET /api/tickets/by-number/[ticketNumber]: single query with resources
  join, returns ticket + picklist labels (status/priority cached per deploy)
- /api/tickets/[id]/notes: Postgres ticket_notes + resources join (was N+1 API calls)
- /api/tickets/[id]/time-entries: Postgres time_entries + resources join (was N+1 API calls)
- Modal: replaces 2-step fetch (all tickets → by id) with single by-number lookup
2026-03-23 11:09:29 -04:00
cb4552a3eb feat: unified Activity Timeline with system note toggle
- Merge notes + time entries into single chronological timeline
- Time entries: blue clock icon, hours badge, resource name, summary
- Human notes: green user icon, creator name, title + body
- System notes (noteType 13/91/93/94/99/101): bot icon, dimmed, hidden by default
- 'Show/Hide system notes' toggle with count badge appears only when system notes exist
- Both data sources fetched in parallel on first expand, cached for session
2026-03-23 10:37:57 -04:00
b72fe2c70e feat: ticket modal collapsible notes and time entries
- New GET /api/tickets/[id]/notes: fetches TicketNotes from Autotask,
  enriches with creator resource names, sorted newest first
- Modal: collapsible Notes section (lazy fetch on expand, shows count badge)
- Modal: collapsible Time Entries section (lazy fetch, count + total hours in header)
- Both sections fetch once and cache for the modal session
2026-03-23 10:27:31 -04:00
0a318fb9d6 fix: ticket modal — picklist labels for status/priority, compact layout
- Ticket [id] route: resolve statusLabel/priorityLabel via getTicketStatusPicklist()
  and getTicketPriorityPicklist() with module-level cache (fetched once per deploy)
- Modal: remove subtitle, move ticket# and title into header, compact single-row
  metadata (status badge + priority badge + assigned resource), dates in 2-col grid,
  smaller buttons
2026-03-23 10:14:12 -04:00
7792e91587 ui: clarify date range doesn't apply to configuration items and other non-date entities 2026-03-17 15:59:19 -04:00
02c81bf4e4 feat: enable Entra ID authentication
- Enable Better Auth middleware (was bypassed with return NextResponse.next())
- Re-enable AuthProvider in root layout
- Add public routes for webhooks, sync, kiosk, QBO, legal, health endpoints
- Set Microsoft Entra ID credentials and production Better Auth URLs
- Hide Engagement and Admin nav sections from non-super-admins
- Fix auth DB columns: snake_case → camelCase for Better Auth compatibility
- Add twoFactorEnabled column to user table
2026-03-17 08:49:20 -04:00
b98c67482a feat: QuickBooks Online integration
- Add QBO OAuth2 client with token refresh (lib/services/qbo-client.ts)
- Add QBO sync service for invoices, payments, deposits, purchases, journal entries, reports (lib/services/qbo-sync-service.ts)
- Add QBO types (lib/types/qbo.ts)
- Add API routes: /api/qbo/auth, /api/qbo/sync, /api/qbo/disconnect
- Add /admin/qbo status and sync management page
- Add legal pages: /legal/eula, /legal/privacy (Intuit app assessment)
- Add QBO nav link under Admin
- Fix reports: remove invalid summarize_column_by, add accounting_method from Preferences API, add showrows=all&showcols=all
- Add CashFlow report type alongside P&L and BalanceSheet
- Add NoReportData check to skip empty report months
- Add intuit_tid capture in error messages
- Add redirect: follow for cluster routing
- Migration 051: qbo_tokens, qbo_invoices, qbo_payments, qbo_deposits, qbo_transactions, qbo_reports tables

Also includes earlier work:
- Ping flap suppression pipeline step
- Ticket digest reports with LLM analysis
- Zabbix WAN monitor and gap analysis
- Kiosk is_deleted filter fixes
- Datto RMM ping target enrichment
- Entity sync soft-delete detection
2026-03-17 07:39:55 -04:00
c518eefdb2 feat: Morning NOC Summary adaptive card for Teams
- Add MorningSummaryService with Zabbix aggregation and adaptive card builder
- Add webhook delivery system with Teams incoming webhooks
- Add admin UI at /admin/morning-summary for webhook/config management
- Add API routes: /send, /test, /webhooks, /webhooks/[id], /config, /history
- Register morning-summary cron job in SyncScheduler (Mon-Fri 6:30 AM)
- Add outages_only filter (Unavailable triggers only)
- Fix host resolution: use getTriggerEnabledHosts to exclude disabled hosts
- Fix resolved events: event.get value:1 scoped to window with r_eventid filter
- Remove emojis from fact rows and section headers in card
- Remove Open Zabbix button (duplicate of View Problems)
- Add migrations: morning_summary_config + morning_summaries tables
- Add outages_only column to morning_summary_config
2026-03-11 09:34:51 -04:00
19605f82aa feat: IT Glue integration, workflow engine, pipelines, Zabbix WAN, notification channels, backup status UI improvements, nav alignment fixes 2026-02-27 14:52:14 -05:00
ed6c4a8b65 feat: Add SentinelOne integration
- Add SentinelOne API client (lib/services/sentinelone-client.ts)
  - Paginated fetching for sites, agents, threats
  - JWT token auth via S1_API_URL / S1_API_TOKEN env vars

- Add SentinelOne sync service (lib/services/sentinelone-sync-service.ts)
  - Full sync: sites, agents, threats into s1_* tables
  - Sync history tracking with per-entity results

- Add DB migration 038: s1_sites, s1_agents, s1_threats,
  s1_company_mappings, s1_sync_history tables

- Add API routes:
  - POST/GET /api/sentinelone/sync
  - GET/POST/DELETE /api/sentinelone/company-mappings
  - GET /api/sentinelone/coverage (fixed Cartesian product bug)

- Add UI pages:
  - /admin/sync/sentinelone — sync admin with history + stats
  - /sentinelone/coverage — AV coverage report per site
  - /sentinelone/mappings — map S1 sites to Autotask companies

- Wire SentinelOne into admin sync overview card grid
- Add SentinelOne Sync to app navigation
- Fix docker-compose: remove explicit S1 env var entries that
  were overwriting env_file values with empty strings
2026-02-27 05:31:31 -05:00
d7c3dc7168 feat: Autotask webhook integration, TicketNotes, Datto RMM, workflow engine, Veeam agents/alarms, AI triage, misc improvements 2026-02-20 10:28:15 -05:00
347cf4e298 feat: dual-tab DetailModal with Formatted and Raw views
- Formatted tab: grouped sections (Overview, Parties, Classification, Dates, System)
- ID-to-label resolution for status, priority, source, queue, company type
- Elegant bordered table layout with muted label column
- Clickable phone/URL fields, monospace IDs, formatted dates
- Description rendered in its own block for tickets
- Raw tab: all fields with monospace keys, copy-on-hover
- Auto-detects ticket vs company data for appropriate grouping
- Shadcn Tabs, Separator, Badge used throughout
2026-02-19 21:00:33 -05:00
6ccdb156ba fix: remove hardcoded sm:max-w-lg from DialogContent so className overrides work
- Removed sm:max-w-lg default that was overriding max-w-7xl in DetailModal
- DialogContent now respects whatever max-w class is passed via className
- Fixes data browser detail modal not widening as expected
2026-02-19 20:51:57 -05:00
2eee5e09f0 style: widen data browser detail modal from max-w-4xl to max-w-7xl 2026-02-19 20:46:41 -05:00
3c13defacb feat: kiosk UI updates - new cards, gauge chart, performance improvements
- Updated kiosk stats API with expanded metrics
- New components: company-tickets-card, gauge-chart, service-desk-card, ticket-leaders-card
- Updated cycling-display, kpi-card, and ticker components
- Added performance.css for kiosk optimizations
- Added Wulf logo asset
2026-02-19 15:31:23 -05:00
5dc7a7e66b feat: Veeam VSPC backup integration - sync, compliance, UI
- Database: 7 Veeam tables + backup_type_udf column on configuration_items
- API Client: VSPC REST API v3 client with pagination, rate limiting, Bearer auth
- Sync Service: full/incremental sync for orgs, servers, repos, jobs, agent jobs, workloads
- Scheduler: veeam-incremental (30min) and veeam-full (daily 2AM) schedules
- Compliance Engine: cross-references Autotask config items vs Veeam workloads
- API Endpoints: backup-status, companies, workloads, jobs, repos, compliance, sync
- UI: Backup Status page with Overview + Contract Compliance tabs
- Navigation: added Backup Status link with HardDrive icon
- Docker: added VEEAM_VSPC_URL and VEEAM_VSPC_API_KEY env vars to compose
2026-02-11 21:04:28 -05:00
a1e0e7c7c0 feat: improve ticker layout and speed controls
- Restructured ticker to show ticket number and title on first line
- Company name now displays on second line below ticket
- Adjusted ticker speed slider range: 8s-120s (was 10s-120s)
- Changed step from 5s to 2s for finer speed control
- Allows 25% faster speed adjustment (down to 8s)
- Better two-line layout for improved readability
2026-02-05 08:13:25 -05:00
73a2e9b9a3 perf: optimize ticker animation and increase speed
- Added translate3d(0,0,0) for hardware acceleration
- Added font smoothing for better rendering
- Reduced default ticker speed from 60s to 30s (2x faster)
- Improved animation smoothness to reduce jitter
- Better GPU acceleration with backface-visibility and willChange
2026-02-05 07:58:33 -05:00
4a545b5f5c fix: use container class to align navigation with dashboard cards
- Changed from max-w-6xl to container mx-auto
- Restored left-4 and right-4 positioning for logo and theme toggle
- Navigation edges now align perfectly with dashboard card edges
- Matches the same container padding used throughout the app
2026-02-04 09:00:33 -05:00
b7e43c2232 style: align navigation edges with card content
- Removed container class, using max-w-6xl with px-4 directly
- Changed absolute positioning from left-4/right-4 to left-0/right-0
- Navigation edges now align perfectly with card edges
- Logo lines up with Dashboard text on left
- Theme toggle aligns with card edge on right
2026-02-04 08:50:41 -05:00
4316d0187f style: constrain navigation width to match content cards
- Added max-w-6xl to navigation container
- Navigation now aligns with KPI cards on wide screens
- Prevents navigation from stretching too wide
- Maintains consistent layout alignment
2026-02-04 08:48:09 -05:00
7b3830a388 fix: move Wulf logo to left navbar, correct spelling to Wulf
- Replaced Pulse icon with Wulf logo on left side of navbar
- Removed duplicate logo from right side
- Corrected alt text from 'Wulff' to 'Wulf'
- Logo now appears next to Pulse branding on left
2026-02-03 23:52:56 -05:00
98199f671d feat: add Wulff Consulting logo to navigation and favicon
- Added Wulff logo (W_RGB.png) to public directory
- Updated favicon to use Wulff logo
- Added logo to upper right of navigation bar (h-10)
- Logo appears next to theme toggle
- Links to home page when clicked
2026-02-03 23:49:58 -05:00
13fd13afd6 style: remove all top padding on kiosk display
- Changed to px-4 pb-4 pt-0 (zero top padding)
- KPI cards now sit right against navigation bar
- Maximizes vertical screen space for TV display
2026-02-03 23:41:47 -05:00
60b58b3f57 style: reduce top padding on kiosk display
- Changed padding from p-16 to p-4 pt-2
- Brings KPI cards closer to navigation bar
- Better use of screen space for TV display
2026-02-03 23:39:38 -05:00
root
62ec703f81 feat: increase ticket font sizes and fix company name display
- Increased ticket number font from text-lg to text-2xl
- Increased company name font from text-sm to text-lg
- Increased ticket title font from text-xs to text-base
- Increased padding on ticket cards for better spacing
- Fixed company ID to name conversion in settings page
- Ensure excluded_company_ids are parsed as numbers for proper lookup
2026-02-03 09:09:46 -05:00
root
724791121a feat: add top 3 tickets display on kiosk KPI cards
- Show company name and ticket title for top 3 tickets per category
- Critical tickets sorted by priority then create date
- Waiting tickets sorted by oldest activity
- Stale tickets sorted by oldest activity
- Overdue tickets sorted by most overdue
- Closed tickets sorted by most recent
- Adjusted card layout to accommodate ticket list
2026-02-03 08:25:27 -05:00
root
aec21d2b1e fix: replace Radix UI slider with custom implementation to avoid dependency 2026-02-02 23:39:24 -05:00
root
20a0785ec3 feat: add executive kiosk dashboard for TV display
- Created /kiosk route with full-screen display
- Added API endpoints for stats and activity feed
- Built cycling KPI display with 12 metrics
- Added scrolling ticker for ticket activity
- Implemented UI-configurable cycle interval (3-15s, default 7s)
- Focus on critical tickets and business metrics
- Added navigation link from dashboard
- Dark theme optimized for TV viewing
2026-02-02 23:36:35 -05:00
root
efff465a86 style: center navigation bar to match rest of app layout
Changed navigation layout from spread (justify-between) to centered:
- Logo positioned absolutely on the left
- Navigation menu centered with mx-auto
- Right actions positioned absolutely on the right
- Container uses justify-center for proper centering
2026-02-02 21:22:57 -05:00