Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

on:
push:
branches: [main, develop]
branches: [main, dev]
pull_request:
branches: [main, develop]
branches: [main, dev]
schedule:
- cron: '0 3 * * *' # nightly full prod-stack smoke
workflow_dispatch:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/comprehensive-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ name: Comprehensive Test Suite

on:
push:
branches: [main, develop]
branches: [main, dev]
pull_request:
branches: [main, develop]
branches: [main, dev]
schedule:
- cron: '0 2 * * *' # daily 02:00 UTC
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/AdminUserManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ export function AdminUserManagement() {
{/* Create User Modal */}
{showCreateUser && (
<div className="fixed inset-0 bg-gray-600 bg-opacity-75 flex items-center justify-center z-50">
<div className="bg-gray-800 border border-gray-700 rounded-lg p-6 max-w-md w-full mx-4">
<div data-testid="admin-create-user-modal" className="bg-gray-800 border border-gray-700 rounded-lg p-6 max-w-md w-full mx-4">
<div className="flex items-center mb-4">
<Plus className="h-6 w-6 text-green-400 mr-3" />
<h3 className="text-lg font-semibold text-gray-100">Create New User</h3>
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/CustomDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function CustomDropdown({

{/* Dropdown Menu */}
{isOpen && (
<div className="absolute z-50 w-full mt-1 bg-gray-700 border border-gray-600 rounded-lg shadow-lg max-h-60 overflow-auto">
<div data-testid="custom-dropdown-menu" className="absolute z-50 w-full mt-1 bg-gray-700 border border-gray-600 rounded-lg shadow-lg max-h-60 overflow-auto">
{options.map((option) => (
<button
key={option.value}
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/components/GraphSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ export function GraphSelector({ onCreateGraph, onEditGraph, onDeleteGraph }: Gra
{/* Dropdown menu with folder structure - Portal based for proper z-index */}
{isOpen && buttonPosition && createPortal(
<div
data-testid="graph-selector-dropdown"
className="bg-gradient-to-br from-gray-800/98 to-gray-900/98 backdrop-blur-xl border-2 border-gray-600/50 rounded-2xl shadow-2xl overflow-hidden"
style={{
position: 'fixed',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4897,6 +4897,7 @@ export function InteractiveGraphVisualization({ onResetLayout, onNodeSelected, i
onTouchEnd={() => setMenuDragState({ isDragging: false, offset: { x: 0, y: 0 } })}
>
<div
data-testid="node-context-menu"
className="absolute bg-black/90 backdrop-blur-xl rounded-2xl border border-white/10 shadow-2xl overflow-hidden animate-fadeIn"
style={{
left: nodeMenu.position.x,
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/components/UserSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function UserSelector({ isCollapsed = false }: UserSelectorProps) {

{/* Dropdown menu */}
{isOpen && (
<div className={`absolute top-full mt-2 bg-gray-800 border border-gray-700 rounded-lg shadow-lg z-50 max-h-96 overflow-hidden ${
<div data-testid="user-menu-dropdown" className={`absolute top-full mt-2 bg-gray-800 border border-gray-700 rounded-lg shadow-lg z-50 max-h-96 overflow-hidden ${
isCollapsed ? 'left-0 w-64' : 'left-0 right-0'
}`}>
{/* Tabs */}
Expand Down
5 changes: 4 additions & 1 deletion packages/web/src/components/ViewManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,10 @@ const ViewManager: React.FC<ViewManagerProps> = ({ viewMode }) => {
<div className="h-full flex flex-col">
{/* Search and Filter Bar - Only for table, card, kanban views */}
{shouldShowFilters && (
<div className="bg-gray-800/90 backdrop-blur-sm border-b border-gray-700/50 p-3 sm:p-4">
// relative z-50: backdrop-blur makes this a stacking context, so the filter
// dropdowns' z-50 is trapped inside it — without an explicit z-index the
// later content area paints over the open dropdowns.
<div className="relative z-50 bg-gray-800/90 backdrop-blur-sm border-b border-gray-700/50 p-3 sm:p-4">
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 items-stretch sm:items-center">
{/* Search Input */}
<div className="relative w-full sm:w-80 md:w-96 lg:w-[28rem]">
Expand Down
6 changes: 4 additions & 2 deletions packages/web/src/components/WorkItemDetailsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ export function WorkItemDetailsModal({
{/* Enhanced Clickable Type Badge */}
<div className="relative z-[100000]">
<button
data-testid="details-type-badge"
onClick={() => setShowTypeDropdown(!showTypeDropdown)}
className={`w-36 flex items-center justify-between px-3 py-2 rounded-lg text-sm font-semibold hover:scale-105 transition-all duration-200 cursor-pointer shadow-lg backdrop-blur-sm ${getTypeColor(currentNode.type)} border border-opacity-30 hover:border-opacity-50`}
>
Expand All @@ -600,7 +601,7 @@ export function WorkItemDetailsModal({

{/* Enhanced Type Dropdown with Staggered Animation */}
{showTypeDropdown && (
<div className="absolute top-full left-0 mt-1 w-40 bg-gray-800/95 backdrop-blur-xl rounded-xl border border-gray-600/30 shadow-2xl z-[99999] max-h-48 overflow-y-auto animate-in fade-in slide-in-from-top-2 duration-200">
<div data-testid="details-type-dropdown" className="absolute top-full left-0 mt-1 w-40 bg-gray-800/95 backdrop-blur-xl rounded-xl border border-gray-600/30 shadow-2xl z-[99999] max-h-48 overflow-y-auto animate-in fade-in slide-in-from-top-2 duration-200">
<div className="p-2">
{TYPE_OPTIONS.filter(opt => opt.value !== 'all').map((type, index) => (
<button
Expand Down Expand Up @@ -641,6 +642,7 @@ export function WorkItemDetailsModal({
{/* Enhanced Clickable Status Badge */}
<div className="relative z-[100000]">
<button
data-testid="details-status-badge"
onClick={() => setShowStatusDropdown(!showStatusDropdown)}
className={`flex items-center space-x-2 px-3 py-2 rounded-lg text-sm font-semibold hover:scale-105 transition-all duration-200 cursor-pointer shadow-lg backdrop-blur-sm ${getStatusColor(currentNode.status)} border border-opacity-30 hover:border-opacity-50`}
>
Expand All @@ -653,7 +655,7 @@ export function WorkItemDetailsModal({

{/* Enhanced Status Dropdown with Staggered Animation */}
{showStatusDropdown && (
<div className="absolute top-full left-0 mt-1 w-40 bg-gray-800/95 backdrop-blur-xl rounded-xl border border-gray-600/30 shadow-2xl z-[99999] max-h-48 overflow-y-auto animate-in fade-in slide-in-from-top-2 duration-200">
<div data-testid="details-status-dropdown" className="absolute top-full left-0 mt-1 w-40 bg-gray-800/95 backdrop-blur-xl rounded-xl border border-gray-600/30 shadow-2xl z-[99999] max-h-48 overflow-y-auto animate-in fade-in slide-in-from-top-2 duration-200">
<div className="p-2">
{STATUS_OPTIONS.filter(opt => opt.value !== 'all').map((status, index) => (
<button
Expand Down
14 changes: 12 additions & 2 deletions packages/web/src/contexts/NotificationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { createContext, useContext, useState, useCallback } from 'react';
import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';
import { Check, X, AlertCircle, Info } from 'lucide-react';

type NotificationType = 'success' | 'error' | 'warning' | 'info';
Expand Down Expand Up @@ -66,6 +66,14 @@ export function NotificationProvider({ children }: { children: React.ReactNode }
showNotification({ type: 'info', title, message });
}, [showNotification]);

// Test affordance: fire a toast on demand (e.g. to verify it stacks above an
// open modal). Harmless in prod — it can only surface a local notification.
useEffect(() => {
(window as any).__notify = (type: NotificationType, title: string, message?: string) =>
showNotification({ type, title, message });
return () => { delete (window as any).__notify; };
}, [showNotification]);

return (
<NotificationContext.Provider
value={{
Expand Down Expand Up @@ -96,8 +104,10 @@ function NotificationContainer({
}) {
if (notifications.length === 0) return null;

// Toasts/alerts are the top transient layer — above modals (≤ z-[999999999])
// so an alert is never hidden behind an open dialog; below tooltips.
return (
<div className="fixed top-4 right-4 z-[9999] space-y-2 max-w-sm">
<div data-testid="toast-stack" className="fixed top-4 right-4 z-[1000000000] space-y-2 max-w-sm">
{notifications.map(notification => (
<NotificationItem
key={notification.id}
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/pages/Ontology.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export function Ontology() {
{/* Work Item Type Detail Modal */}
{showDetailModal && selectedNodeType && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-gray-800 rounded-xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-hidden">
<div data-testid="ontology-type-modal" className="bg-gray-800 rounded-xl shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-hidden">
{/* Modal Header */}
<div className="flex items-center justify-between p-6 border-b border-gray-700">
<div className="flex items-center space-x-4">
Expand Down
24 changes: 13 additions & 11 deletions packages/web/src/pages/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,19 @@ export function Settings() {
<p className="text-sm text-gray-400 mb-2">
Auto adapts to your device and network — effects scale down before responsiveness ever does. Pin a tier if auto guesses wrong.
</p>
<CustomDropdown
options={[
{ value: 'AUTO', label: 'Auto (recommended)' },
{ value: 'LOW', label: 'Low — fastest, no effects' },
{ value: 'MEDIUM', label: 'Medium — glow, light animation' },
{ value: 'HIGH', label: 'High — full living graph' },
{ value: 'ULTRA', label: 'Ultra — everything on' }
]}
value={override ?? 'AUTO'}
onChange={(value) => setOverride(value === 'AUTO' ? null : (value as QualityTier))}
/>
<div data-testid="settings-quality-dropdown">
<CustomDropdown
options={[
{ value: 'AUTO', label: 'Auto (recommended)' },
{ value: 'LOW', label: 'Low — fastest, no effects' },
{ value: 'MEDIUM', label: 'Medium — glow, light animation' },
{ value: 'HIGH', label: 'High — full living graph' },
{ value: 'ULTRA', label: 'Ultra — everything on' }
]}
value={override ?? 'AUTO'}
onChange={(value) => setOverride(value === 'AUTO' ? null : (value as QualityTier))}
/>
</div>
</div>
</div>
</div>
Expand Down
Loading
Loading