diff --git a/packages/mgt-chat/src/components/Chat/Chat.tsx b/packages/mgt-chat/src/components/Chat/Chat.tsx index 0fc57cc71a..7d4d78fef2 100644 --- a/packages/mgt-chat/src/components/Chat/Chat.tsx +++ b/packages/mgt-chat/src/components/Chat/Chat.tsx @@ -9,6 +9,7 @@ import { onRenderMessage } from '../../utils/chat'; import { renderMGTMention } from '../../utils/mentions'; import { registerAppIcons } from '../styles/registerIcons'; import { ChatHeader } from '../ChatHeader/ChatHeader'; +import { GraphConfig } from '../../statefulClient/GraphConfig'; import { Error } from '../Error/Error'; import { LoadingMessagesErrorIcon } from '../Error/LoadingMessageErrorIcon'; import { OpenTeamsLinkError } from '../Error/OpenTeams'; @@ -19,6 +20,7 @@ registerAppIcons(); interface IMgtChatProps { chatId: string; + usePremiumApis?: boolean; } const useStyles = makeStyles({ @@ -105,7 +107,7 @@ const messageThreadStyles: MessageThreadStyles = { } }; -export const Chat = ({ chatId }: IMgtChatProps) => { +export const Chat = ({ chatId, usePremiumApis }: IMgtChatProps) => { const styles = useStyles(); const chatClient: StatefulGraphChatClient = useGraphChatClient(chatId); const [chatState, setChatState] = useState(chatClient.getState()); @@ -116,6 +118,10 @@ export const Chat = ({ chatId }: IMgtChatProps) => { }; }, [chatClient]); + useEffect(() => { + GraphConfig.usePremiumApis = usePremiumApis ?? false; + }, [usePremiumApis]); + const isLoading = ['creating server connections', 'subscribing to notifications', 'loading messages'].includes( chatState.status ); diff --git a/packages/mgt-chat/src/statefulClient/GraphConfig.ts b/packages/mgt-chat/src/statefulClient/GraphConfig.ts index b96dc3633e..e7ee4eca5f 100644 --- a/packages/mgt-chat/src/statefulClient/GraphConfig.ts +++ b/packages/mgt-chat/src/statefulClient/GraphConfig.ts @@ -18,6 +18,7 @@ export class GraphConfig { public static canarySubscriptionVersion = 'testprodv1.0e2ewebsockets'; public static webSocketsPrefix = 'websockets:'; + static usePremiumApis = false; public static get graphEndpoint(): GraphEndpoint { return GraphConfig.useCanary ? 'https://canary.graph.microsoft.com' : 'https://graph.microsoft.com'; diff --git a/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts b/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts index 953c790e66..df22e0d5be 100644 --- a/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts +++ b/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts @@ -18,6 +18,7 @@ import type { import { GraphConfig } from './GraphConfig'; import { SubscriptionsCache } from './Caching/SubscriptionCache'; import { Timer } from '../utils/Timer'; +import { addPremiumApiSegment } from '../utils/addPremiumApiSegment'; import { getOrGenerateGroupId } from './getOrGenerateGroupId'; export const appSettings = { @@ -396,7 +397,9 @@ export class GraphNotificationClient { await this.subscriptionCache.deleteCachedSubscriptions(chatId); } const promises: Promise[] = []; - promises.push(this.subscribeToResource(`/chats/${chatId}/messages`, ['created', 'updated', 'deleted'])); + promises.push( + this.subscribeToResource(addPremiumApiSegment(`/chats/${chatId}/messages`), ['created', 'updated', 'deleted']) + ); promises.push(this.subscribeToResource(`/chats/${chatId}/members`, ['created', 'deleted'])); promises.push(this.subscribeToResource(`/chats/${chatId}`, ['updated', 'deleted'])); await Promise.all(promises).catch((e: Error) => { diff --git a/packages/mgt-chat/src/statefulClient/graph.chat.ts b/packages/mgt-chat/src/statefulClient/graph.chat.ts index 1bc71f1e4a..f9657a6ec2 100644 --- a/packages/mgt-chat/src/statefulClient/graph.chat.ts +++ b/packages/mgt-chat/src/statefulClient/graph.chat.ts @@ -16,6 +16,7 @@ import { CacheService, IGraph, prepScopes } from '@microsoft/mgt-element'; import { ResponseType } from '@microsoft/microsoft-graph-client'; import { AadUserConversationMember, Chat, ChatMessage } from '@microsoft/microsoft-graph-types'; import { chatOperationScopes } from './chatOperationScopes'; +import { addPremiumApiSegment } from '../utils/addPremiumApiSegment'; /** * Generic collection response from graph @@ -59,7 +60,7 @@ export const loadChatThread = async ( messageCount: number ): Promise => { const response = (await graph - .api(`/chats/${chatId}/messages`) + .api(addPremiumApiSegment(`/chats/${chatId}/messages`)) .orderby('createdDateTime DESC') .top(messageCount) .middlewareOptions(prepScopes(chatOperationScopes.loadChatMessages)) @@ -86,7 +87,7 @@ export const loadChatThreadDelta = async ( messageCount: number ): Promise => { const response = (await graph - .api(`/chats/${chatId}/messages`) + .api(addPremiumApiSegment(`/chats/${chatId}/messages`)) .filter(`lastModifiedDateTime gt ${lastModified}`) .orderby('lastModifiedDateTime DESC') .top(messageCount) diff --git a/packages/mgt-chat/src/utils/addPremiumApiSegment.tests.ts b/packages/mgt-chat/src/utils/addPremiumApiSegment.tests.ts new file mode 100644 index 0000000000..f7ac92b91e --- /dev/null +++ b/packages/mgt-chat/src/utils/addPremiumApiSegment.tests.ts @@ -0,0 +1,25 @@ +import { GraphConfig } from '../statefulClient/GraphConfig'; +import { addPremiumApiSegment } from './addPremiumApiSegment'; +import { expect } from '@open-wc/testing'; + +describe('addPremiumApiSegment tests', () => { + it('should return the original url if premium apis are not enabled', async () => { + const url = 'https://graph.microsoft.com/v1.0/me'; + const result = addPremiumApiSegment(url); + await expect(result).to.eql(url); + }); + + it('should add the premium api segment to the url', async () => { + const url = 'https://graph.microsoft.com/v1.0/me'; + GraphConfig.usePremiumApis = true; + const result = addPremiumApiSegment(url); + await expect(result).to.eql(`${url}?model=B`); + }); + + it('should add the premium api segment to the url when it already has query params', async () => { + const url = 'https://graph.microsoft.com/v1.0/me?select=id'; + GraphConfig.usePremiumApis = true; + const result = addPremiumApiSegment(url); + await expect(result).to.eql(`${url}&model=B`); + }); +}); diff --git a/packages/mgt-chat/src/utils/addPremiumApiSegment.ts b/packages/mgt-chat/src/utils/addPremiumApiSegment.ts new file mode 100644 index 0000000000..1c456468c1 --- /dev/null +++ b/packages/mgt-chat/src/utils/addPremiumApiSegment.ts @@ -0,0 +1,10 @@ +import { GraphConfig } from '../statefulClient/GraphConfig'; + +export const addPremiumApiSegment = (url: string) => { + // early exit if premium apis are not enabled + if (!GraphConfig.usePremiumApis) { + return url; + } + const urlHasExistingQueryParams = url.includes('?'); + return `${url}${urlHasExistingQueryParams ? '&' : '?'}model=B`; +}; diff --git a/packages/mgt-chat/src/utils/mentions.tsx b/packages/mgt-chat/src/utils/mentions.tsx index c3448d932f..f9a741428d 100644 --- a/packages/mgt-chat/src/utils/mentions.tsx +++ b/packages/mgt-chat/src/utils/mentions.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { MgtTemplateProps, Person } from '@microsoft/mgt-react'; import { ChatMessageMention, User } from '@microsoft/microsoft-graph-types'; -import { GraphChatClient } from 'src/statefulClient/StatefulGraphChatClient'; +import { GraphChatClient } from '../statefulClient/StatefulGraphChatClient'; import { Mention } from '@azure/communication-react'; export const renderMGTMention = (chatState: GraphChatClient) => { diff --git a/packages/mgt-chat/src/utils/types.ts b/packages/mgt-chat/src/utils/types.ts index 7852917747..bc62211de3 100644 --- a/packages/mgt-chat/src/utils/types.ts +++ b/packages/mgt-chat/src/utils/types.ts @@ -6,7 +6,7 @@ */ import { ChatMessage, Message } from '@azure/communication-react'; -import { GraphChatMessage } from 'src/statefulClient/StatefulGraphChatClient'; +import type { GraphChatMessage } from '../statefulClient/StatefulGraphChatClient'; /** * A typeguard to get the ChatMessage type diff --git a/packages/mgt-spfx/.gitignore b/packages/mgt-spfx/.gitignore new file mode 100644 index 0000000000..09a3b1be63 --- /dev/null +++ b/packages/mgt-spfx/.gitignore @@ -0,0 +1,2 @@ +release +temp \ No newline at end of file diff --git a/samples/react-chat/package.json b/samples/react-chat/package.json index 5b84554933..f5576b04f5 100644 --- a/samples/react-chat/package.json +++ b/samples/react-chat/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@fluentui/react-components": "^9.19.1", "@microsoft/mgt-chat": "*", "@microsoft/mgt-msal2-provider": "*", "@microsoft/mgt-react": "*", diff --git a/samples/react-chat/src/App.tsx b/samples/react-chat/src/App.tsx index dc2111332f..650d11d021 100644 --- a/samples/react-chat/src/App.tsx +++ b/samples/react-chat/src/App.tsx @@ -1,9 +1,10 @@ -import React, { memo, useCallback, useState } from 'react'; +import React, { ChangeEvent, memo, useCallback, useState } from 'react'; import './App.css'; import { Get, Login } from '@microsoft/mgt-react'; import { Chat, NewChat } from '@microsoft/mgt-chat'; import { Chat as GraphChat } from '@microsoft/microsoft-graph-types'; import ChatListTemplate from './components/ChatListTemplate/ChatListTemplate'; +import { FluentProvider, Switch, SwitchOnChangeData, teamsLightTheme } from '@fluentui/react-components'; const ChatList = memo(({ chatSelected }: { chatSelected: (e: GraphChat) => void }) => { return ( @@ -25,31 +26,39 @@ function App() { setShowNewChat(false); }, []); + const [usePremiumApis, setUsePremiumApis] = useState(false); + const onToggleChanged = useCallback((ev: ChangeEvent, data: SwitchOnChangeData) => { + setUsePremiumApis(data.checked ?? false); + }, []); + return (
-
- Mgt Chat test harness -
- -
-
-
- - Selected chat: {chatId} -
- + +
+ Mgt Chat test harness
- - {showNewChat && ( -
- setShowNewChat(false)} mode="auto" /> -
- )} -
+ + +
+
+ + + Selected chat: {chatId} +
+ +
+ + {showNewChat && ( +
+ setShowNewChat(false)} mode="auto" /> +
+ )} +
- {/* NOTE: removed the chatId guard as this case has an error state. */} -
{}
-
+ {/* NOTE: removed the chatId guard as this case has an error state. */} +
{}
+
+
); } diff --git a/yarn.lock b/yarn.lock index a39e145034..6597b5024d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26715,6 +26715,7 @@ __metadata: version: 0.0.0-use.local resolution: "react-chat@workspace:samples/react-chat" dependencies: + "@fluentui/react-components": ^9.19.1 "@microsoft/mgt-chat": "*" "@microsoft/mgt-msal2-provider": "*" "@microsoft/mgt-react": "*"