Skip to content

Commit dd27d89

Browse files
committed
Enhance graph selection UI and fix node visibility issues
- Enhanced GraphSelectionModal with color-coded type badges and improved styling - Updated Switch Graph button with yellow background and visible count badge - Fixed graph filtering to ensure nodes display correctly across different graphs - Improved GraphSelector with gradient colors and consistent hover effects - Cleaned up debug code and removed unnecessary logging - Updated workspace header styling with gradient text and consistent badge colors
1 parent c7350ac commit dd27d89

7 files changed

Lines changed: 190 additions & 156 deletions

File tree

packages/web/src/components/GraphSelectionModal.tsx

Lines changed: 76 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,12 @@ function GraphItem({ graph, onSelect, getGraphTypeIcon }: GraphItemProps) {
2525
variables: {
2626
where: {
2727
graph: {
28-
id: graph.id,
29-
teamId: currentTeam?.id || 'default-team'
28+
id: graph.id
3029
}
3130
}
3231
},
33-
skip: !currentTeam,
34-
pollInterval: 10000 // Poll every 10 seconds to avoid too many requests
32+
pollInterval: 10000,
33+
fetchPolicy: 'cache-and-network'
3534
});
3635

3736
const { data: edgesData } = useQuery(GET_EDGES, {
@@ -44,38 +43,55 @@ function GraphItem({ graph, onSelect, getGraphTypeIcon }: GraphItemProps) {
4443
}
4544
}
4645
},
47-
pollInterval: 10000
46+
pollInterval: 10000,
47+
fetchPolicy: 'cache-and-network'
4848
});
4949

5050
const actualNodeCount = workItemsData?.workItems?.length || 0;
5151
const actualEdgeCount = edgesData?.edges?.length || 0;
5252

53+
const getGraphTypeColor = (type: string) => {
54+
switch (type) {
55+
case 'PROJECT': return 'text-blue-400 bg-gradient-to-br from-blue-500/20 to-blue-600/30 border border-blue-400/20';
56+
case 'WORKSPACE': return 'text-purple-400 bg-gradient-to-br from-purple-500/20 to-purple-600/30 border border-purple-400/20';
57+
case 'SUBGRAPH': return 'text-emerald-400 bg-gradient-to-br from-emerald-500/20 to-emerald-600/30 border border-emerald-400/20';
58+
case 'TEMPLATE': return 'text-amber-400 bg-gradient-to-br from-amber-500/20 to-amber-600/30 border border-amber-400/20';
59+
default: return 'text-slate-400 bg-gradient-to-br from-slate-500/20 to-slate-600/30 border border-slate-400/20';
60+
}
61+
};
62+
63+
const getBadgeColor = (type: string) => {
64+
switch (type) {
65+
case 'PROJECT': return 'bg-blue-500/20 text-blue-300 border border-blue-400/30';
66+
case 'WORKSPACE': return 'bg-purple-500/20 text-purple-300 border border-purple-400/30';
67+
case 'SUBGRAPH': return 'bg-emerald-500/20 text-emerald-300 border border-emerald-400/30';
68+
case 'TEMPLATE': return 'bg-amber-500/20 text-amber-300 border border-amber-400/30';
69+
default: return 'bg-slate-500/20 text-slate-300 border border-slate-400/30';
70+
}
71+
};
72+
5373
return (
5474
<button
5575
onClick={() => onSelect(graph.id)}
56-
className="w-full flex items-center px-6 py-4 hover:bg-gray-700/50 transition-colors text-left group"
76+
className="w-full flex items-center px-4 py-4 hover:bg-gray-700 transition-colors text-left group rounded-lg border border-gray-600 hover:border-green-500 bg-gray-800 mb-2"
5777
>
5878
<div className="flex-shrink-0 mr-4">
59-
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${
60-
graph.type === 'PROJECT' ? 'bg-blue-600/20 text-blue-400' :
61-
graph.type === 'WORKSPACE' ? 'bg-purple-600/20 text-purple-400' :
62-
graph.type === 'SUBGRAPH' ? 'bg-green-600/20 text-green-400' :
63-
'bg-orange-600/20 text-orange-400'
64-
}`}>
79+
<div className={`w-10 h-10 rounded flex items-center justify-center ${getGraphTypeColor(graph.type)}`}>
6580
{getGraphTypeIcon(graph.type)}
6681
</div>
6782
</div>
6883

6984
<div className="flex-1 min-w-0">
7085
<div className="flex items-center justify-between mb-1">
71-
<h4 className="text-base font-medium text-green-300 group-hover:text-green-200 truncate">
86+
<h4 className="text-lg font-semibold text-white group-hover:text-green-300 truncate">
7287
{graph.name}
7388
</h4>
74-
<span className={`ml-2 px-3 py-1 text-xs font-medium rounded-full ${
75-
graph.type === 'PROJECT' ? 'bg-blue-600/20 text-blue-300' :
76-
graph.type === 'WORKSPACE' ? 'bg-purple-600/20 text-purple-300' :
77-
graph.type === 'SUBGRAPH' ? 'bg-green-600/20 text-green-300' :
78-
'bg-orange-600/20 text-orange-300'
89+
<span className={`ml-2 px-2 py-1 text-xs font-medium rounded ${
90+
graph.type === 'PROJECT' ? 'bg-blue-500/20 text-blue-300 border border-blue-400/30' :
91+
graph.type === 'WORKSPACE' ? 'bg-purple-500/20 text-purple-300 border border-purple-400/30' :
92+
graph.type === 'SUBGRAPH' ? 'bg-emerald-500/20 text-emerald-300 border border-emerald-400/30' :
93+
graph.type === 'TEMPLATE' ? 'bg-amber-500/20 text-amber-300 border border-amber-400/30' :
94+
'bg-slate-500/20 text-slate-300 border border-slate-400/30'
7995
}`}>
8096
{graph.type}
8197
</span>
@@ -85,7 +101,7 @@ function GraphItem({ graph, onSelect, getGraphTypeIcon }: GraphItemProps) {
85101
{graph.description || 'No description provided'}
86102
</p>
87103

88-
<div className="flex items-center gap-4 text-xs text-gray-500">
104+
<div className="flex items-center gap-3 text-xs text-gray-500 group-hover:text-gray-400">
89105
<span className="flex items-center gap-1">
90106
<div className="w-1.5 h-1.5 bg-green-400 rounded-full"></div>
91107
{actualNodeCount} node{actualNodeCount !== 1 ? 's' : ''}
@@ -99,7 +115,7 @@ function GraphItem({ graph, onSelect, getGraphTypeIcon }: GraphItemProps) {
99115
{graph.contributorCount} contributor{graph.contributorCount !== 1 ? 's' : ''}
100116
</span>
101117
{graph.status && (
102-
<span className={`ml-2 px-2 py-1 rounded text-xs font-medium ${
118+
<span className={`px-2 py-0.5 rounded text-xs ${
103119
graph.status === 'ACTIVE' ? 'bg-green-900/30 text-green-300' :
104120
graph.status === 'DRAFT' ? 'bg-yellow-900/30 text-yellow-300' :
105121
'bg-gray-700/30 text-gray-400'
@@ -160,25 +176,32 @@ export function GraphSelectionModal({ isOpen, onClose }: GraphSelectionModalProp
160176
/>
161177

162178
{/* Modal */}
163-
<div className="inline-block w-full max-w-2xl p-0 my-8 overflow-hidden text-left align-middle transition-all transform bg-gray-800 shadow-xl rounded-lg border border-gray-700">
179+
<div className="inline-block w-full max-w-4xl p-0 my-6 overflow-hidden text-left align-middle transition-all transform bg-gray-800 shadow-lg rounded border border-gray-700">
164180
{/* Header */}
165181
<div className="flex items-center justify-between px-6 py-4 border-b border-gray-700 bg-gray-800">
166-
<h3 className="text-xl font-semibold text-green-300">
167-
Select Graph
168-
</h3>
182+
<div>
183+
<h3 className="text-xl font-semibold text-green-300">
184+
Select Graph
185+
</h3>
186+
<p className="text-sm text-gray-400 mt-1">Choose your graph to begin</p>
187+
</div>
169188
<button
170189
onClick={onClose}
171-
className="p-2 text-gray-400 hover:text-gray-300 hover:bg-gray-700 rounded-lg transition-colors"
190+
className="p-2 text-gray-400 hover:text-gray-300 hover:bg-gray-700 rounded transition-colors"
172191
>
173-
<X className="h-5 w-5" />
192+
<X className="h-6 w-6" />
174193
</button>
175194
</div>
176195

177196
{/* Content */}
178197
{availableGraphs.length > 0 ? (
179-
<div className="p-6 space-y-4">
180-
<p className="text-gray-300">Choose a graph to start working with</p>
181-
<div className="divide-y divide-gray-700 max-h-80 overflow-y-auto">
198+
<div className="p-4">
199+
<div className="max-h-80 overflow-y-auto space-y-2" style={{scrollbarWidth: 'none', msOverflowStyle: 'none'}}>
200+
<style jsx>{`
201+
div::-webkit-scrollbar {
202+
display: none;
203+
}
204+
`}</style>
182205
{availableGraphs.map((graph) => (
183206
<GraphItem
184207
key={graph.id}
@@ -190,35 +213,33 @@ export function GraphSelectionModal({ isOpen, onClose }: GraphSelectionModalProp
190213
</div>
191214
</div>
192215
) : (
193-
<div className="p-6 space-y-6">
194-
<p className="text-gray-300">Choose a graph to start working with</p>
195-
<div className="text-center py-8">
196-
{/* Compact Icon */}
197-
<div className="mx-auto mb-6 w-16 h-16 bg-gradient-to-br from-green-600 to-blue-600 rounded-xl flex items-center justify-center shadow-lg">
198-
<Folder className="h-8 w-8 text-white" />
199-
</div>
200-
201-
{/* Content */}
202-
<div className="mb-8">
203-
<h4 className="text-lg font-medium text-green-300 mb-3">
204-
No graphs yet
205-
</h4>
206-
<p className="text-gray-400 text-sm leading-relaxed">
207-
Create your first graph to start organizing projects with powerful visualization tools.
208-
</p>
209-
</div>
216+
<div className="p-8">
217+
<div className="text-center max-w-md mx-auto">
218+
{/* Icon */}
219+
<div className="mx-auto mb-6 w-16 h-16 bg-gray-700 rounded flex items-center justify-center">
220+
<Folder className="h-8 w-8 text-gray-400" />
221+
</div>
210222

211-
{/* CTA Button */}
212-
<button
213-
onClick={handleCreateGraph}
214-
className="group relative px-6 py-3 bg-gradient-to-r from-green-600 to-blue-600 hover:from-green-500 hover:to-blue-500 text-white rounded-lg font-semibold text-sm transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105 mb-6"
215-
>
216-
<div className="relative flex items-center justify-center">
217-
<Plus className="h-4 w-4 mr-2" />
218-
Create Your First Graph
223+
{/* Content */}
224+
<div className="mb-8">
225+
<h4 className="text-lg font-semibold text-green-300 mb-3">
226+
No Graphs Available
227+
</h4>
228+
<p className="text-gray-400 leading-relaxed">
229+
Create your first graph to start organizing your projects with visual tools and collaborative features.
230+
</p>
219231
</div>
220-
</button>
221232

233+
{/* CTA Button */}
234+
<button
235+
onClick={handleCreateGraph}
236+
className="px-6 py-3 bg-green-600 hover:bg-green-700 text-white rounded font-medium transition-colors"
237+
>
238+
<div className="flex items-center justify-center">
239+
<Plus className="h-4 w-4 mr-2" />
240+
Create Your First Graph
241+
</div>
242+
</button>
222243
</div>
223244
</div>
224245
)}

packages/web/src/components/GraphSelector.tsx

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,31 @@ export function GraphSelector() {
1414

1515
// Get real-time counts for current graph
1616
const { data: workItemsData } = useQuery(GET_WORK_ITEMS, {
17-
variables: {
17+
variables: currentGraph ? {
1818
where: {
1919
graph: {
20-
id: currentGraph?.id,
21-
teamId: currentTeam?.id || 'default-team'
20+
id: currentGraph.id
2221
}
2322
}
24-
},
25-
skip: !currentGraph || !currentTeam,
26-
pollInterval: 5000
23+
} : {},
24+
skip: !currentGraph,
25+
pollInterval: 5000,
26+
fetchPolicy: 'cache-and-network'
2727
});
2828

2929
const { data: edgesData } = useQuery(GET_EDGES, {
30-
variables: {
30+
variables: currentGraph ? {
3131
where: {
3232
source: {
3333
graph: {
34-
id: currentGraph?.id
34+
id: currentGraph.id
3535
}
3636
}
3737
}
38-
},
38+
} : {},
3939
skip: !currentGraph,
40-
pollInterval: 5000
40+
pollInterval: 5000,
41+
fetchPolicy: 'cache-and-network'
4142
});
4243

4344
const actualNodeCount = workItemsData?.workItems?.length || 0;
@@ -79,11 +80,11 @@ export function GraphSelector() {
7980

8081
const getGraphTypeColor = (type: string) => {
8182
switch (type) {
82-
case 'PROJECT': return 'text-blue-300 bg-blue-900/30';
83-
case 'WORKSPACE': return 'text-purple-300 bg-purple-900/30';
84-
case 'SUBGRAPH': return 'text-green-300 bg-green-900/30';
85-
case 'TEMPLATE': return 'text-orange-300 bg-orange-900/30';
86-
default: return 'text-gray-300 bg-gray-700/30';
83+
case 'PROJECT': return 'text-blue-400 bg-gradient-to-br from-blue-500/20 to-blue-600/30 border border-blue-400/20';
84+
case 'WORKSPACE': return 'text-purple-400 bg-gradient-to-br from-purple-500/20 to-purple-600/30 border border-purple-400/20';
85+
case 'SUBGRAPH': return 'text-emerald-400 bg-gradient-to-br from-emerald-500/20 to-emerald-600/30 border border-emerald-400/20';
86+
case 'TEMPLATE': return 'text-amber-400 bg-gradient-to-br from-amber-500/20 to-amber-600/30 border border-amber-400/20';
87+
default: return 'text-slate-400 bg-gradient-to-br from-slate-500/20 to-slate-600/30 border border-slate-400/20';
8788
}
8889
};
8990

@@ -113,7 +114,7 @@ export function GraphSelector() {
113114
{/* Graph selector button (EXACT same pattern as UserSelector) */}
114115
<button
115116
onClick={() => setIsOpen(!isOpen)}
116-
className="flex items-center space-x-3 w-full p-3 text-left hover:bg-gray-700 rounded-lg transition-colors"
117+
className="flex items-center space-x-3 w-full p-3 text-left hover:bg-gray-700/80 rounded-xl transition-all duration-200 hover:scale-[1.02] border border-gray-600/30 hover:border-gray-500/50 shadow-lg hover:shadow-xl backdrop-blur-sm bg-gray-800/50"
117118
>
118119
<div className="flex-shrink-0">
119120
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${getGraphTypeColor(currentGraph.type)}`}>
@@ -150,10 +151,10 @@ export function GraphSelector() {
150151

151152
{/* Dropdown menu (EXACT same pattern as UserSelector) */}
152153
{isOpen && (
153-
<div className="absolute bottom-full left-0 right-0 mb-2 bg-gray-800 border border-gray-600 rounded-lg shadow-lg z-50 max-h-96 overflow-hidden">
154+
<div className="absolute bottom-full left-0 right-0 mb-2 bg-gray-800/95 backdrop-blur-lg border border-gray-600/60 rounded-xl shadow-2xl z-50 max-h-96 overflow-hidden">
154155
{/* Header */}
155-
<div className="flex items-center justify-between p-3 border-b border-gray-600">
156-
<span className="text-sm font-medium text-gray-300">Select Graph</span>
156+
<div className="flex items-center justify-between p-4 border-b border-gray-600/60 bg-gradient-to-r from-emerald-500/10 to-green-500/10 backdrop-blur-sm">
157+
<span className="text-sm font-semibold bg-gradient-to-r from-emerald-400 to-green-300 bg-clip-text text-transparent">Select Graph</span>
157158
<div className="flex items-center gap-2">
158159
<button
159160
onClick={() => setIsOpen(false)}
@@ -173,14 +174,16 @@ export function GraphSelector() {
173174
<button
174175
key={graph.id}
175176
onClick={() => handleGraphSelect(graph.id)}
176-
className={`w-full flex items-center space-x-3 p-2 rounded-lg text-left transition-colors ${
177+
className={`w-full flex items-center space-x-3 p-3 rounded-xl text-left transition-all duration-200 ${
177178
graph.id === currentGraph.id
178-
? 'bg-green-900/30 text-green-300 border border-green-500/30'
179-
: 'hover:bg-gray-700 text-gray-300'
179+
? 'bg-gradient-to-r from-emerald-500/20 to-green-500/20 text-emerald-300 border border-emerald-400/30 shadow-md'
180+
: 'hover:bg-gray-700/60 text-gray-300 hover:border-gray-600/40 border border-transparent hover:shadow-md hover:scale-[1.02]'
180181
}`}
181182
>
182183
<div className="flex-shrink-0">
183-
{getGraphTypeIcon(graph.type)}
184+
<div className={`w-6 h-6 rounded-lg flex items-center justify-center ${getGraphTypeColor(graph.type)}`}>
185+
{getGraphTypeIcon(graph.type)}
186+
</div>
184187
</div>
185188
<div className="flex-1 min-w-0">
186189
<div className="flex items-center gap-2">

packages/web/src/components/GraphVisualization.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ export function GraphVisualization() {
6565
// Store the current positioned nodes for access in click handlers
6666
const currentNodesRef = useRef<WorkItem[]>([]);
6767

68-
const { data: workItemsData, loading: workItemsLoading } = useQuery(GET_WORK_ITEMS, {
68+
const { data: workItemsData, loading: workItemsLoading, error: workItemsError } = useQuery(GET_WORK_ITEMS, {
6969
variables: {
7070
options: { limit: 100 }
7171
},
72-
fetchPolicy: 'cache-and-network', // Use cache first, then fetch from network for updates
73-
pollInterval: 5000, // Poll every 5 seconds for real-time updates
72+
fetchPolicy: 'cache-and-network',
73+
pollInterval: 5000,
7474
notifyOnNetworkStatusChange: true,
7575
errorPolicy: 'all'
7676
});

0 commit comments

Comments
 (0)