Skip to content

Commit b901205

Browse files
authored
Merge pull request #469 from it-at-m/deleted-communityassistants-in-db
Deleted communityassistants in db
2 parents 4714f6d + 0fd72f1 commit b901205

File tree

17 files changed

+326
-56
lines changed

17 files changed

+326
-56
lines changed

mucgpt-assistant-service/src/api/api_models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ class SubscriptionResponse(BaseModel):
494494
description="Unique identifier for the assistant (UUID v4)",
495495
example="123e4567-e89b-12d3-a456-426614174000",
496496
)
497-
name: str = Field(
497+
title: str = Field(
498498
...,
499499
description="The name/title of the assistant",
500500
example="Technical Support Assistant",
@@ -511,7 +511,8 @@ class SubscriptionResponse(BaseModel):
511511
json_schema_extra={
512512
"example": {
513513
"id": "123e4567-e89b-12d3-a456-426614174000",
514-
"name": "Technical Support Assistant",
514+
"title": "Technical Support Assistant",
515+
"description": "An AI assistant specialized in providing technical support for software issues",
515516
}
516517
},
517518
)

mucgpt-assistant-service/src/api/routers/users_router.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ async def get_user_subscriptions(
230230
if latest_version:
231231
response = SubscriptionResponse(
232232
id=assistant_id,
233-
name=getattr(latest_version, "name", ""),
233+
title=getattr(latest_version, "name", ""),
234234
description=getattr(latest_version, "description", ""),
235235
)
236236
response_list.append(response)

mucgpt-assistant-service/src/database/assistant_repo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations # Enable forward references in annotations
22

33
import uuid
4-
from datetime import datetime, timezone
4+
from datetime import datetime
55

66
from sqlalchemy import delete, func, insert, select, update
77
from sqlalchemy.ext.asyncio import AsyncSession
@@ -428,7 +428,7 @@ async def remove_subscription(self, assistant_id: str, user_id: str) -> bool:
428428
.values(
429429
subscriptions_count=Assistant.subscriptions_count
430430
- rows_deleted,
431-
updated_at=datetime.now(timezone.utc),
431+
updated_at=datetime.now(),
432432
)
433433
)
434434

mucgpt-assistant-service/tests/integration/test_users_router.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ def test_subscribe_to_assistant_success(test_client):
523523
# Validate using SubscriptionResponse model
524524
subscription_response = SubscriptionResponse.model_validate(subscriptions[0])
525525
assert subscription_response.id == assistant_id
526-
assert subscription_response.name == "Subscribe Test Assistant"
526+
assert subscription_response.title == "Subscribe Test Assistant"
527527

528528

529529
@pytest.mark.integration
@@ -630,7 +630,7 @@ def test_unsubscribe_from_assistant_success(test_client):
630630
# Validate using SubscriptionResponse model
631631
subscription_response = SubscriptionResponse.model_validate(subscriptions_before[0])
632632
assert subscription_response.id == assistant_id
633-
assert subscription_response.name == "Unsubscribe Test Assistant"
633+
assert subscription_response.title == "Unsubscribe Test Assistant"
634634

635635
# Unsubscribe from the assistant
636636
unsubscribe_response = test_client.delete(
@@ -721,7 +721,7 @@ def test_get_user_subscriptions_multiple(test_client):
721721
assert len(subscriptions) == 2
722722

723723
# Check that we have the correct assistants with simplified structure
724-
subscription_names = [sub["name"] for sub in subscriptions]
724+
subscription_names = [sub["title"] for sub in subscriptions]
725725
assert "Subscription Assistant 1" in subscription_names
726726
assert "Subscription Assistant 2" not in subscription_names
727727
assert (
@@ -731,14 +731,14 @@ def test_get_user_subscriptions_multiple(test_client):
731731
# Parse with SubscriptionResponse model to ensure structure is correct
732732
subscription_response = SubscriptionResponse.model_validate(subscription)
733733
assert subscription_response.id in [assistant_ids[0], assistant_ids[2]]
734-
assert subscription_response.name in [
734+
assert subscription_response.title in [
735735
"Subscription Assistant 1",
736736
"Subscription Assistant 3",
737737
]
738738

739739
# Also validate that only expected fields are present
740740
assert "id" in subscription
741-
assert "name" in subscription
741+
assert "title" in subscription
742742
# Should NOT have complex fields like latest_version
743743
assert "latest_version" not in subscription
744744
assert "created_at" not in subscription
@@ -776,7 +776,7 @@ async def test_subscription_lifecycle(test_client, test_db_session):
776776
# Validate using SubscriptionResponse model
777777
subscription_response = SubscriptionResponse.model_validate(after_subscribe[0])
778778
assert subscription_response.id == assistant_id
779-
assert subscription_response.name == "Lifecycle Test Assistant"
779+
assert subscription_response.title == "Lifecycle Test Assistant"
780780

781781
# Also validate that only expected fields are present
782782
assert "latest_version" not in after_subscribe[0]
@@ -1161,7 +1161,7 @@ async def test_hierarchical_access_subscription_vs_ownership(
11611161
# Verify subscription was created
11621162
subscriptions = test_client.get("/user/subscriptions", headers=headers).json()
11631163
assert len(subscriptions) == 1
1164-
assert subscriptions[0]["name"] == "IT Accessible Assistant"
1164+
assert subscriptions[0]["title"] == "IT Accessible Assistant"
11651165

11661166

11671167
@pytest.mark.integration

mucgpt-frontend/src/api/assistant-client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { getConfig, handleApiRequest, postConfig, deleteConfig } from "./fetch-utils";
2-
import { AssistantCreateInput, AssistantCreateResponse, AssistantResponse, AssistantUpdateInput, Assistant } from "./models";
2+
import { AssistantCreateInput, AssistantCreateResponse, AssistantResponse, AssistantUpdateInput, Assistant, CommunityAssistant } from "./models";
33

44
/**
55
* Get all assistants the user is subscribed to (ID and name only).
66
* @returns Array of SubscriptionResponse
77
*/
88

9-
export async function getUserSubscriptionsApi(): Promise<{ id: string; name: string; description: string }[]> {
9+
export async function getUserSubscriptionsApi(): Promise<CommunityAssistant[]> {
1010
return handleApiRequest(() => fetch("/api/user/subscriptions", getConfig()), "Failed to get user subscriptions");
1111
} /**
1212
* Unsubscribe the current user from an assistant.

mucgpt-frontend/src/api/models.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,9 @@ export interface User {
227227
user_roles?: string[];
228228
authorities?: string[];
229229
}
230+
231+
export type CommunityAssistant = {
232+
title: string;
233+
description: string;
234+
id: string;
235+
};

mucgpt-frontend/src/components/AssistantsettingsDrawer/AssistantsettingsDrawer.module.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,17 @@
285285
.newChatHeaderContent:hover {
286286
background-color: var(--colorNeutralBackground1Hover);
287287
}
288+
289+
.deletedWarning {
290+
padding: var(--spacingVerticalM) var(--spacingHorizontalM);
291+
background-color: var(--colorPaletteRedBackground1);
292+
border: 1px solid var(--colorPaletteRedBorder1);
293+
border-radius: var(--borderRadiusMedium);
294+
color: var(--colorPaletteRedForeground1);
295+
font-size: var(--fontSizeBase300);
296+
font-weight: var(--fontWeightSemibold);
297+
margin: var(--spacingVerticalM) var(--spacingHorizontalM);
298+
display: flex;
299+
align-items: center;
300+
gap: var(--spacingHorizontalS);
301+
}

mucgpt-frontend/src/components/AssistantsettingsDrawer/AssistantsettingsDrawer.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { AssistantStorageService } from "../../service/assistantstorage";
2929
import { ASSISTANT_STORE } from "../../constants";
3030
import { Collapse } from "@fluentui/react-motion-components-preview";
3131
import { deleteCommunityAssistantApi } from "../../api/assistant-client";
32-
import { AssistantStrategy } from "../../pages/assistant/AssistantStrategy";
32+
import { AssistantStrategy, DeletedCommunityAssistantStrategy } from "../../pages/assistant/AssistantStrategy";
3333

3434
interface Props {
3535
assistant: Assistant;
@@ -203,18 +203,23 @@ export const AssistantsettingsDrawer = ({
203203
<div className={styles.titleSection}>
204204
<h3 className={styles.assistantTitle}>{assistant.title}</h3>
205205
</div>
206+
{strategy instanceof DeletedCommunityAssistantStrategy && (
207+
<div className={styles.deletedWarning}>
208+
{t("components.assistantsettingsdrawer.deleted_warning")}
209+
</div>
210+
)}
206211
<div
207212
className={styles.actionsHeader}
208213
role="heading"
209214
aria-level={4}
210-
onClick={clearChat}
215+
onClick={clearChatDisabled ? undefined : clearChat}
211216
aria-disabled={clearChatDisabled}
212217
tabIndex={0}
213-
onKeyDown={e => e.key === "Enter" && clearChat()}
218+
onKeyDown={clearChatDisabled ? undefined : e => e.key === "Enter" && clearChat()}
214219
>
215220
<div className={styles.newChatHeaderContent}>
216221
<ChatAdd24Regular className={styles.actionsIcon} aria-hidden="true" />
217-
<span>New Chat</span>
222+
<span>{t("common.clear_chat")}</span>
218223
</div>
219224
</div>
220225

@@ -237,6 +242,7 @@ export const AssistantsettingsDrawer = ({
237242
icon={isOwner ? <Edit24Regular /> : <ChatSettings24Regular />}
238243
onClick={toggleEditDialog}
239244
className={styles.actionButton}
245+
disabled={strategy instanceof DeletedCommunityAssistantStrategy}
240246
>
241247
{isOwner ? t("components.assistantsettingsdrawer.edit") : t("components.assistantsettingsdrawer.show_configutations")}
242248
</Button>

mucgpt-frontend/src/components/CommunityAssistantDialog/CommunityAssistantDialog.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { Button, Dialog, DialogBody, DialogContent, DialogSurface, DialogTitle,
22
import { Dismiss24Regular } from "@fluentui/react-icons";
33
import { useTranslation } from "react-i18next";
44
import { useCallback, useEffect, useState } from "react";
5-
import { Assistant, AssistantResponse } from "../../api";
6-
import { AssistantStorageService } from "../../service/assistantstorage";
7-
import { ASSISTANT_STORE } from "../../constants";
5+
import { Assistant, AssistantResponse, CommunityAssistant } from "../../api";
6+
import { CommunityAssistantStorageService } from "../../service/communityassistantstorage";
7+
import { COMMUNITY_ASSISTANT_STORE } from "../../constants";
88

99
// Components
1010
import { AssistantSearchSection } from "./components/AssistantSearchSection";
@@ -72,7 +72,7 @@ export const CommunityAssistantsDialog = ({
7272
const [selectedAssistant, setSelectedAssistant] = useState<Assistant>(createMockAssistant());
7373
const [showAssistantDialog, setShowAssistantDialog] = useState<boolean>(false);
7474

75-
const communityAssistantStorageService = new AssistantStorageService(ASSISTANT_STORE);
75+
const communityAssistantStorageService = new CommunityAssistantStorageService(COMMUNITY_ASSISTANT_STORE);
7676

7777
// sort Functions
7878
const compareByTitle = (a: AssistantWithMetadata, b: AssistantWithMetadata): number => {
@@ -240,6 +240,12 @@ export const CommunityAssistantsDialog = ({
240240

241241
try {
242242
await subscribeToAssistantApi(assistant.id);
243+
const community_config: CommunityAssistant = {
244+
id: assistant.id,
245+
title: assistant.title,
246+
description: assistant.description,
247+
}
248+
await communityAssistantStorageService.createAssistantConfig(community_config);
243249
showSuccess(
244250
t("components.community_assistants.subscribe_success_title", { title: assistant.title }),
245251
t("components.community_assistants.subscribe_success_message")
@@ -274,9 +280,6 @@ export const CommunityAssistantsDialog = ({
274280
// Load full assistant details
275281
const fullAssistant = await loadAssistantDetails(assistant.id);
276282
setSelectedAssistant(fullAssistant);
277-
278-
// Update storage service
279-
communityAssistantStorageService.getAssistantConfig(assistant.id);
280283
} catch (error) {
281284
// Error is handled in the hook
282285
console.error("Failed to load assistant details:", error);

mucgpt-frontend/src/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ export const CHAT_STORE: IndexedDBStorage = {
4242
db_version: 3
4343
};
4444

45+
export const COMMUNITY_ASSISTANT_STORE: IndexedDBStorage = {
46+
db_name: "MUCGPT-COMMUNITY-ASSISTANTS",
47+
objectStore_name: "assistants",
48+
db_version: 1
49+
};
50+
4551
// Create Assistant examples
4652
export const CREATE_ASSISTANT_EXAMPLE_1 = "Englischübersetzer: Der Assistent übersetzt den eingegebenen Text ins Englische.";
4753
export const CREATE_ASSISTANT_EXAMPLE_2 =

0 commit comments

Comments
 (0)