Skip to content

Commit 6dbbe7d

Browse files
authored
Merge pull request #6 from hunterjam/UIupdates
U iupdates Comments to be addressed in a future PR
2 parents 578f47d + ec5e102 commit 6dbbe7d

15 files changed

Lines changed: 1988 additions & 1384 deletions

content-gen/src/backend/app.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ def get_authenticated_user():
4949
Get the authenticated user from EasyAuth headers.
5050
5151
In production (with App Service Auth), the X-Ms-Client-Principal-Id header
52-
contains the user's ID. In development mode, returns empty/None values.
52+
contains the user's ID. In development mode, returns "anonymous".
5353
"""
5454
user_principal_id = request.headers.get("X-Ms-Client-Principal-Id", "")
5555
user_name = request.headers.get("X-Ms-Client-Principal-Name", "")
5656
auth_provider = request.headers.get("X-Ms-Client-Principal-Idp", "")
5757

5858
return {
59-
"user_principal_id": user_principal_id or "",
59+
"user_principal_id": user_principal_id or "anonymous",
6060
"user_name": user_name or "",
6161
"auth_provider": auth_provider or "",
6262
"is_authenticated": bool(user_principal_id)
@@ -1051,14 +1051,13 @@ async def list_conversations():
10511051
List conversations for a user.
10521052
10531053
Uses authenticated user from EasyAuth headers. In development mode
1054-
(when not authenticated), returns conversations where user_id is empty/null.
1054+
(when not authenticated), uses "anonymous" as user_id.
10551055
10561056
Query params:
10571057
limit: Max number of results (default 20)
10581058
"""
1059-
# Get authenticated user from headers
10601059
auth_user = get_authenticated_user()
1061-
user_id = auth_user["user_principal_id"] # Empty string if not authenticated
1060+
user_id = auth_user["user_principal_id"]
10621061

10631062
limit = int(request.args.get("limit", 20))
10641063

content-gen/src/backend/services/cosmos_service.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -431,39 +431,24 @@ async def get_user_conversations(
431431
Get all conversations for a user with summary data.
432432
433433
Args:
434-
user_id: User ID (empty string for development mode - returns conversations with empty/null user_id)
434+
user_id: User ID ("anonymous" for unauthenticated users)
435435
limit: Maximum number of conversations
436436
437437
Returns:
438438
List of conversation summaries
439439
"""
440440
await self.initialize()
441441

442-
# Get conversations with messages to extract title and last message
443-
# In development mode (empty user_id), get conversations where user_id is empty, null, or not set
444-
if user_id:
445-
# Production mode: get conversations for the authenticated user
446-
query = """
447-
SELECT TOP @limit c.id, c.user_id, c.updated_at, c.messages, c.brief
448-
FROM c
449-
WHERE c.user_id = @user_id
450-
ORDER BY c.updated_at DESC
451-
"""
452-
params = [
453-
{"name": "@user_id", "value": user_id},
454-
{"name": "@limit", "value": limit}
455-
]
456-
else:
457-
# Development mode: get conversations where user_id is empty, null, or not defined
458-
query = """
459-
SELECT TOP @limit c.id, c.user_id, c.updated_at, c.messages, c.brief
460-
FROM c
461-
WHERE (NOT IS_DEFINED(c.user_id) OR c.user_id = null OR c.user_id = "")
462-
ORDER BY c.updated_at DESC
463-
"""
464-
params = [
465-
{"name": "@limit", "value": limit}
466-
]
442+
query = """
443+
SELECT TOP @limit c.id, c.user_id, c.updated_at, c.messages, c.brief
444+
FROM c
445+
WHERE c.user_id = @user_id
446+
ORDER BY c.updated_at DESC
447+
"""
448+
params = [
449+
{"name": "@user_id", "value": user_id},
450+
{"name": "@limit", "value": limit}
451+
]
467452

468453
conversations = []
469454
async for item in self._conversations_container.query_items(

content-gen/src/frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
5+
<link rel="icon" type="image/svg+xml" href="/microsoft.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>Content Generation Accelerator</title>
88
</head>
Lines changed: 6 additions & 0 deletions
Loading

content-gen/src/frontend/src/App.tsx

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function App() {
5050

5151
// Product selection
5252
const [selectedProducts, setSelectedProducts] = useState<Product[]>([]);
53+
const [availableProducts, setAvailableProducts] = useState<Product[]>([]);
5354

5455
// Generated content
5556
const [generatedContent, setGeneratedContent] = useState<GeneratedContent | null>(null);
@@ -86,27 +87,23 @@ function App() {
8687
const response = await fetch('/api/user');
8788
if (response.ok) {
8889
const user: UserInfo = await response.json();
89-
// Use user_principal_id if authenticated, otherwise empty string for dev mode
90-
setUserId(user.user_principal_id || '');
90+
setUserId(user.user_principal_id || 'anonymous');
9191
}
9292
} catch (err) {
9393
console.error('Error fetching user:', err);
94-
// Default to empty string for development mode
95-
setUserId('');
94+
setUserId('anonymous');
9695
}
9796
};
9897
fetchUser();
9998
}, []);
10099

101100
// Handle selecting a conversation from history
102101
const handleSelectConversation = useCallback(async (selectedConversationId: string) => {
103-
setIsLoading(true);
104102
try {
105103
const response = await fetch(`/api/conversations/${selectedConversationId}?user_id=${encodeURIComponent(userId)}`);
106104
if (response.ok) {
107105
const data = await response.json();
108106
setConversationId(selectedConversationId);
109-
// Map messages to ChatMessage format
110107
const loadedMessages: ChatMessage[] = (data.messages || []).map((msg: { role: string; content: string; timestamp?: string; agent?: string }, index: number) => ({
111108
id: `${selectedConversationId}-${index}`,
112109
role: msg.role as 'user' | 'assistant',
@@ -118,24 +115,18 @@ function App() {
118115
setPendingBrief(null);
119116
setConfirmedBrief(data.brief || null);
120117

121-
// Restore generated content if it exists
122118
if (data.generated_content) {
123119
const gc = data.generated_content;
124-
// Parse text_content if it's a string
125120
let textContent = gc.text_content;
126121
if (typeof textContent === 'string') {
127122
try {
128123
textContent = JSON.parse(textContent);
129124
} catch {
130-
// Keep as string if not valid JSON
131125
}
132126
}
133127

134-
// Build image URL: convert old blob URLs to proxy URLs, or use existing proxy URL
135128
let imageUrl: string | undefined = gc.image_url;
136129
if (imageUrl && imageUrl.includes('blob.core.windows.net')) {
137-
// Convert old blob URL to proxy URL
138-
// blob URL format: https://account.blob.core.windows.net/container/conv_id/filename.png
139130
const parts = imageUrl.split('/');
140131
const filename = parts[parts.length - 1];
141132
const convId = parts[parts.length - 2];
@@ -159,14 +150,12 @@ function App() {
159150
} : undefined,
160151
violations: gc.violations || [],
161152
requires_modification: gc.requires_modification || false,
162-
// Restore any generation errors
163153
error: gc.error,
164154
image_error: gc.image_error,
165155
text_error: gc.text_error,
166156
};
167157
setGeneratedContent(restoredContent);
168158

169-
// Restore selected products if they exist
170159
if (gc.selected_products && Array.isArray(gc.selected_products)) {
171160
setSelectedProducts(gc.selected_products);
172161
} else {
@@ -179,8 +168,6 @@ function App() {
179168
}
180169
} catch (error) {
181170
console.error('Error loading conversation:', error);
182-
} finally {
183-
setIsLoading(false);
184171
}
185172
}, [userId]);
186173

@@ -406,10 +393,16 @@ function App() {
406393
setConfirmedBrief(pendingBrief);
407394
setPendingBrief(null);
408395

396+
const productsResponse = await fetch('/api/products');
397+
if (productsResponse.ok) {
398+
const productsData = await productsResponse.json();
399+
setAvailableProducts(productsData.products || []);
400+
}
401+
409402
const assistantMessage: ChatMessage = {
410403
id: uuidv4(),
411404
role: 'assistant',
412-
content: "Great! Your creative brief has been confirmed. Now let's select products to feature in your campaign. Tell me what products you'd like to include - you can describe them by name, category, or characteristics.",
405+
content: "Great! Your creative brief has been confirmed. Here are the available products for your campaign. Select the ones you'd like to feature, or tell me what you're looking for.",
413406
agent: 'ProductAgent',
414407
timestamp: new Date().toISOString(),
415408
};
@@ -442,6 +435,17 @@ function App() {
442435
setMessages(prev => [...prev, assistantMessage]);
443436
}, []);
444437

438+
const handleProductSelect = useCallback((product: Product) => {
439+
setSelectedProducts(prev => {
440+
const isSelected = prev.some(p => (p.sku || p.product_name) === (product.sku || product.product_name));
441+
if (isSelected) {
442+
return prev.filter(p => (p.sku || p.product_name) !== (product.sku || product.product_name));
443+
} else {
444+
return [...prev, product];
445+
}
446+
});
447+
}, []);
448+
445449
const handleStopGeneration = useCallback(() => {
446450
if (abortControllerRef.current) {
447451
abortControllerRef.current.abort();
@@ -635,12 +639,15 @@ function App() {
635639
confirmedBrief={confirmedBrief}
636640
generatedContent={generatedContent}
637641
selectedProducts={selectedProducts}
642+
availableProducts={availableProducts}
638643
onBriefConfirm={handleBriefConfirm}
639644
onBriefCancel={handleBriefCancel}
640645
onGenerateContent={handleGenerateContent}
641646
onRegenerateContent={handleGenerateContent}
642647
onProductsStartOver={handleProductsStartOver}
648+
onProductSelect={handleProductSelect}
643649
imageGenerationEnabled={imageGenerationEnabled}
650+
onNewConversation={handleNewConversation}
644651
/>
645652
</div>
646653

0 commit comments

Comments
 (0)