Skip to content

Commit e23818e

Browse files
bojanclaude
authored andcommitted
feat: Add dark theme and fix JsonPathResolver
UI Changes: - Switch to dark theme using GitHub-style colors - Custom dark colors: bg, card, border, hover - Update all components with dark theme styling Backend Fix: - Fix JsonPathResolver to merge Input.Data properties - Allows $.input.deviceId path instead of $.input.data.deviceId - All 115 unit tests now pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ed362d5 commit e23818e

File tree

14 files changed

+209
-170
lines changed

14 files changed

+209
-170
lines changed

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
"Bash(git push:*)",
4747
"Bash(git commit:*)",
4848
"Bash(git checkout:*)",
49-
"Bash(npm run build:*)"
49+
"Bash(npm run build:*)",
50+
"Bash(gh pr create:*)"
5051
],
5152
"deny": [],
5253
"ask": []

src/Orchestration.Core/Workflow/Interpreter/JsonPathResolver.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,33 @@ public void SetValue(string path, object? value, WorkflowRuntimeState state)
143143
private JsonNode? ConvertStateToJsonNode(WorkflowRuntimeState state)
144144
{
145145
// Build the full input object including all WorkflowInput properties
146-
var inputObject = state.Input != null
147-
? new Dictionary<string, object?>
146+
// Merge Data dictionary into root of input for easy path access like $.input.deviceId
147+
Dictionary<string, object?>? inputObject = null;
148+
if (state.Input != null)
149+
{
150+
inputObject = new Dictionary<string, object?>
148151
{
149152
["workflowType"] = state.Input.WorkflowType,
150153
["version"] = state.Input.Version,
151154
["entityId"] = state.Input.EntityId,
152155
["idempotencyKey"] = state.Input.IdempotencyKey,
153156
["correlationId"] = state.Input.CorrelationId,
154157
["data"] = state.Input.Data
158+
};
159+
160+
// Merge Data properties into root of input for direct access
161+
if (state.Input.Data != null)
162+
{
163+
foreach (var kvp in state.Input.Data)
164+
{
165+
// Don't overwrite standard properties
166+
if (!inputObject.ContainsKey(kvp.Key))
167+
{
168+
inputObject[kvp.Key] = kvp.Value;
169+
}
170+
}
155171
}
156-
: null;
172+
}
157173

158174
var stateObject = new Dictionary<string, object?>
159175
{

ui/src/components/Dashboard.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ export function Dashboard() {
2121
return (
2222
<div className="space-y-6">
2323
<div>
24-
<h1 className="text-2xl font-bold text-gray-900">Dashboard</h1>
25-
<p className="text-gray-600">
24+
<h1 className="text-2xl font-bold text-gray-100">Dashboard</h1>
25+
<p className="text-gray-400">
2626
Welcome back{user ? `, ${user.name}` : ''}!
2727
</p>
2828
</div>
@@ -36,8 +36,8 @@ export function Dashboard() {
3636
</div>
3737

3838
{/* Quick Actions */}
39-
<div className="bg-white rounded-lg border border-gray-200 p-6">
40-
<h2 className="text-lg font-semibold text-gray-900 mb-4">
39+
<div className="bg-dark-card rounded-lg border border-dark-border p-6">
40+
<h2 className="text-lg font-semibold text-gray-100 mb-4">
4141
Quick Actions
4242
</h2>
4343
<div className="flex gap-4">
@@ -49,27 +49,27 @@ export function Dashboard() {
4949
</Link>
5050
<button
5151
disabled
52-
className="px-4 py-2 border border-gray-300 text-gray-400 rounded-lg cursor-not-allowed"
52+
className="px-4 py-2 border border-dark-border text-gray-500 rounded-lg cursor-not-allowed"
5353
title="Coming soon"
5454
>
5555
Open Designer
5656
</button>
5757
<Link
5858
to="/workflows"
59-
className="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors"
59+
className="px-4 py-2 border border-dark-border text-gray-300 rounded-lg hover:bg-dark-hover transition-colors"
6060
>
6161
View All Workflows
6262
</Link>
6363
</div>
6464
</div>
6565

6666
{/* Recent Workflows */}
67-
<div className="bg-white rounded-lg border border-gray-200 p-6">
67+
<div className="bg-dark-card rounded-lg border border-dark-border p-6">
6868
<div className="flex justify-between items-center mb-4">
69-
<h2 className="text-lg font-semibold text-gray-900">
69+
<h2 className="text-lg font-semibold text-gray-100">
7070
Recent Workflows
7171
</h2>
72-
<Link to="/workflows" className="text-sm text-blue-600 hover:underline">
72+
<Link to="/workflows" className="text-sm text-blue-400 hover:underline">
7373
View all
7474
</Link>
7575
</div>
@@ -89,11 +89,11 @@ export function Dashboard() {
8989
key={workflow.InstanceId}
9090
to="/workflows/$instanceId"
9191
params={{ instanceId: workflow.InstanceId }}
92-
className="block p-3 rounded-lg hover:bg-gray-50 transition-colors"
92+
className="block p-3 rounded-lg hover:bg-dark-hover transition-colors"
9393
>
9494
<div className="flex items-center justify-between">
9595
<div>
96-
<div className="font-mono text-sm text-gray-900">
96+
<div className="font-mono text-sm text-gray-200">
9797
{workflow.InstanceId.substring(0, 20)}...
9898
</div>
9999
<div className="text-xs text-gray-500">
@@ -119,15 +119,15 @@ interface StatCardProps {
119119

120120
function StatCard({ title, value, color }: StatCardProps) {
121121
const colorClasses = {
122-
blue: 'bg-blue-50 text-blue-600',
123-
green: 'bg-green-50 text-green-600',
124-
yellow: 'bg-yellow-50 text-yellow-600',
125-
red: 'bg-red-50 text-red-600',
122+
blue: 'bg-blue-900/30 text-blue-400',
123+
green: 'bg-green-900/30 text-green-400',
124+
yellow: 'bg-yellow-900/30 text-yellow-400',
125+
red: 'bg-red-900/30 text-red-400',
126126
};
127127

128128
return (
129-
<div className="bg-white rounded-lg border border-gray-200 p-4">
130-
<div className="text-sm text-gray-500">{title}</div>
129+
<div className="bg-dark-card rounded-lg border border-dark-border p-4">
130+
<div className="text-sm text-gray-400">{title}</div>
131131
<div className={`text-2xl font-bold mt-1 ${colorClasses[color]}`}>
132132
{value}
133133
</div>

ui/src/components/LoginPage.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ export function LoginPage() {
1414
};
1515

1616
return (
17-
<div className="min-h-screen flex items-center justify-center bg-gray-100">
18-
<div className="bg-white p-8 rounded-xl shadow-lg max-w-md w-full">
17+
<div className="min-h-screen flex items-center justify-center bg-dark-bg">
18+
<div className="bg-dark-card p-8 rounded-xl border border-dark-border max-w-md w-full">
1919
<div className="text-center mb-8">
20-
<h1 className="text-2xl font-bold text-gray-900">
20+
<h1 className="text-2xl font-bold text-gray-100">
2121
Orchestration Studio
2222
</h1>
23-
<p className="text-gray-600 mt-2">
23+
<p className="text-gray-400 mt-2">
2424
Azure Durable Functions Demo
2525
</p>
2626
</div>
@@ -34,15 +34,15 @@ export function LoginPage() {
3434
<button
3535
key={user.id}
3636
onClick={() => handleLogin(user.id)}
37-
className="w-full flex items-center gap-4 p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
37+
className="w-full flex items-center gap-4 p-4 border border-dark-border rounded-lg hover:bg-dark-hover transition-colors"
3838
>
39-
<div className="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center">
40-
<span className="text-blue-600 font-semibold">
39+
<div className="w-10 h-10 bg-blue-900/50 rounded-full flex items-center justify-center">
40+
<span className="text-blue-400 font-semibold">
4141
{user.name.charAt(0)}
4242
</span>
4343
</div>
4444
<div className="text-left">
45-
<div className="font-medium text-gray-900">{user.name}</div>
45+
<div className="font-medium text-gray-200">{user.name}</div>
4646
<div className="text-sm text-gray-500">
4747
{user.email}<span className="capitalize">{user.role}</span>
4848
</div>
@@ -51,8 +51,8 @@ export function LoginPage() {
5151
))}
5252
</div>
5353

54-
<div className="mt-8 p-4 bg-blue-50 rounded-lg">
55-
<p className="text-xs text-blue-800">
54+
<div className="mt-8 p-4 bg-blue-900/30 rounded-lg border border-blue-800">
55+
<p className="text-xs text-blue-300">
5656
<strong>Note:</strong> This is a demo authentication system.
5757
In production, this would integrate with Azure AD / Entra ID.
5858
</p>

ui/src/components/common/JsonViewer.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,23 @@ export function JsonViewer({ data, initialExpanded = true }: JsonViewerProps) {
1515
<div className="absolute top-2 right-2 flex gap-2">
1616
<button
1717
onClick={() => setExpanded(!expanded)}
18-
className="px-2 py-1 text-xs bg-gray-100 text-gray-600 rounded hover:bg-gray-200"
18+
className="px-2 py-1 text-xs bg-dark-hover text-gray-400 rounded hover:bg-dark-border hover:text-gray-200"
1919
>
2020
{expanded ? 'Collapse' : 'Expand'}
2121
</button>
2222
<button
2323
onClick={() => navigator.clipboard.writeText(jsonString)}
24-
className="px-2 py-1 text-xs bg-gray-100 text-gray-600 rounded hover:bg-gray-200"
24+
className="px-2 py-1 text-xs bg-dark-hover text-gray-400 rounded hover:bg-dark-border hover:text-gray-200"
2525
>
2626
Copy
2727
</button>
2828
</div>
2929
<pre
30-
className={`bg-gray-50 rounded-lg p-4 text-sm font-mono overflow-auto ${
30+
className={`bg-dark-bg rounded-lg p-4 text-sm font-mono overflow-auto ${
3131
expanded ? 'max-h-96' : 'max-h-24'
3232
}`}
3333
>
34-
<code className="text-gray-800">{jsonString}</code>
34+
<code className="text-gray-300">{jsonString}</code>
3535
</pre>
3636
</div>
3737
);

0 commit comments

Comments
 (0)