Skip to content

Commit

Permalink
Alkwa/cte storybook docs (#2623)
Browse files Browse the repository at this point in the history
* cte docs

* updating CTE storybook documentation

* adding storybook preview to try out cte in call composite

* updated with PR comments

* pushing up with code comments
  • Loading branch information
alkwa-msft authored Jan 18, 2023
1 parent 75f11b3 commit 1a91053
Show file tree
Hide file tree
Showing 7 changed files with 301 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Updating cte documentation in storybook",
"packageName": "@azure/communication-react",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "Updating cte documentation in storybook",
"packageName": "@azure/communication-react",
"email": "[email protected]",
"dependentChangeType": "none"
}
3 changes: 2 additions & 1 deletion packages/storybook/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ export const parameters = {
'Best Practices',
'Troubleshooting',
'Identity',
'Rooms'
'Rooms',
'Communication as Teams user'
],
EXAMPLES_FOLDER_PREFIX,
STATEFUL_CLIENT_PREFIX,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { CallComposite } from '@azure/communication-react';
import { Stack } from '@fluentui/react';
import { Meta } from '@storybook/react/types-6-0';
import React from 'react';
import { COMPOSITE_FOLDER_PREFIX, compositeExperienceContainerStyle } from '../constants';
import { defaultCallCompositeHiddenControls, controlsToAdd, ArgsFrom } from '../controlsUtils';
import { compositeLocale } from '../localizationUtils';
import { getDocs } from './CallCompositeDocs';
import { ContosoCTECallContainer } from './snippets/CTEContainer.snippet';
import { ConfigJoinCallHintBanner } from './snippets/Utils';

const storyControls = {
userId: controlsToAdd.userId,
token: controlsToAdd.token,
callLocator: controlsToAdd.teamsMeetingLink,
compositeFormFactor: controlsToAdd.formFactor,
callInvitationURL: controlsToAdd.callInvitationURL
};

const JoinExistingCallWithCommunicationAsTeamsUserStory = (
args: ArgsFrom<typeof storyControls>,
context
): JSX.Element => {
const {
globals: { locale }
} = context;
const areAllKnobsSet = !!args.callLocator && !!args.userId && !!args.token;

return (
<Stack horizontalAlign="center" verticalAlign="center" styles={compositeExperienceContainerStyle}>
{areAllKnobsSet ? (
<ContosoCTECallContainer
fluentTheme={context.theme}
locator={args.callLocator}
userId={{ microsoftTeamsUserId: args.userId }}
token={args.token}
callInvitationURL={args.callInvitationURL}
locale={compositeLocale(locale)}
formFactor={args.compositeFormFactor}
/>
) : (
<ConfigJoinCallHintBanner />
)}
</Stack>
);
};

export const JoinExistingCallWithCommunicationAsTeamsUser = JoinExistingCallWithCommunicationAsTeamsUserStory.bind({});

export default {
id: `${COMPOSITE_FOLDER_PREFIX}-call-joinexistingcallwithCommunicationAsTeamsuser`,
title: `${COMPOSITE_FOLDER_PREFIX}/CallComposite/Join Existing Call With Communication As Teams User`,
component: CallComposite,
argTypes: {
...storyControls,
// Hiding auto-generated controls
...defaultCallCompositeHiddenControls
},
parameters: {
docs: {
page: () => getDocs()
}
}
} as Meta;
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { TeamsMeetingLinkLocator } from '@azure/communication-calling';
import { AzureCommunicationTokenCredential, MicrosoftTeamsUserIdentifier } from '@azure/communication-common';
import {
CallComposite,
CallCompositeOptions,
CompositeLocale,
TeamsCallAdapter,
useTeamsCallAdapter
} from '@azure/communication-react';
import { PartialTheme, Theme } from '@fluentui/react';
import React, { useMemo } from 'react';

export type ContainerProps = {
userId: MicrosoftTeamsUserIdentifier;
token: string;
locator: string;
formFactor?: 'desktop' | 'mobile';
fluentTheme?: PartialTheme | Theme;
callInvitationURL?: string;
locale?: CompositeLocale;
options?: CallCompositeOptions;
};

const isTeamsMeetingLink = (link: string): boolean => link.startsWith('https://teams.microsoft.com/l/meetup-join');

const createCallAdapterLocator = (locator: string): TeamsMeetingLinkLocator | undefined => {
if (isTeamsMeetingLink(locator)) {
return { meetingLink: locator };
}
return undefined;
};

export const ContosoCTECallContainer = (props: ContainerProps): JSX.Element => {
const credential = useMemo(() => {
try {
return new AzureCommunicationTokenCredential(props.token);
} catch {
console.error('Failed to construct token credential');
return undefined;
}
}, [props.token]);

const locator = useMemo(() => createCallAdapterLocator(props.locator), [props.locator]);

const adapter = useTeamsCallAdapter(
{
userId: props.userId,
credential,
locator
},
undefined,
leaveCall
);

if (!locator) {
return <>Provided call locator '{props.locator}' is not recognized.</>;
}

if (adapter) {
return (
<div style={{ height: '90vh', width: '90vw' }}>
<CallComposite
adapter={adapter}
formFactor={props.formFactor}
fluentTheme={props.fluentTheme}
callInvitationUrl={props?.callInvitationURL}
locale={props?.locale}
options={props?.options}
/>
</div>
);
}
if (credential === undefined) {
return <>Failed to construct credential. Provided token is malformed.</>;
}
return <>Initializing...</>;
};

const leaveCall = async (adapter: TeamsCallAdapter): Promise<void> => {
await adapter.leaveCall().catch((e) => {
console.error('Failed to leave call', e);
});
};
58 changes: 58 additions & 0 deletions packages/storybook/stories/CommunicationAsTeamsUser.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Meta, Source } from '@storybook/addon-docs';
import { DetailedBetaBanner } from './BetaBanners/DetailedBetaBanner';
import CommunicationAsTeamsUserSnippetText from '!!raw-loader!./snippets/CommunicationAsTeamsUser.snippet.tsx';

<Meta
id="communicationAsTeamsUser"
title="Concepts/Communication as Teams user"
parameters={{ previewTabs: { canvas: { disable: true, hidden: true } } }}
/>

# Communication as Teams user

<DetailedBetaBanner version={'1.5.1-beta.1'} />

Communication as Teams user is a workflow where you can join an Azure Communications Service powered call as a Teams user.

To learn more about the Communication as Teams user, click [here](https://learn.microsoft.com/en-us/azure/communication-services/concepts/teams-endpoint)

## Examples

Leveraging Communication as Teams user, enables developers to create customized Teams experiences:

- Browser support on mobile devices
- User interface (UI) customization
- End users can join calls as their M365 user instead of an External user.

## How does UI Library support Communication as Teams user?

The UI Library helps Contoso build custom teams client experiences via a simplified API surface, providing a set of UI components,
and offering UI composites to reduce development time to production. The UI Library is able to offer all of these capabilities by taking
in a Teams access token as input and using teams-specific calling functions for making calls as a Teams user.

Note: The UI Library is not able to create teams access tokens or interact with your existing tenant.

## Using UI Library in Communication as Teams user scenarios

The following is a code snippet of how to try out Communication as Teams user with the CallComposite

<Source code={CommunicationAsTeamsUserSnippetText} />

## FAQs

### Is Communication as Teams user ready for production loads?

UI Library support for Communication as Teams user is currently in public preview. We definitely look forward to seeing how you
like this experience so we can create an amazing experience when the feature will hit "General Availablility" in 2023.

### If I have found any issues with the CallComposite when interacting with Communication as Teams user where can I go?

Feel free to log a [Github issue](https://github.com/Azure/communication-ui-library/issues) and someone from our team can work with you on your issue.

### If I want to learn more about the Communication as Teams user workflow where can I look?

You can check out our documentation in our Azure Documentation [here](https://learn.microsoft.com/en-us/azure/communication-services/concepts/teams-endpoint)

### How do I get the Teams access token in code to try out the Communication as Teams user workflow?

You can try out this quickstart to create a Teams access token [here](https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/manage-teams-identity?pivots=programming-language-javascript)
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { AzureCommunicationTokenCredential, MicrosoftTeamsUserIdentifier } from '@azure/communication-common';
import {
CallComposite,
CallCompositeOptions,
CompositeLocale,
TeamsCallAdapter,
useTeamsCallAdapter
} from '@azure/communication-react';
import { PartialTheme, Theme } from '@fluentui/react';
import React, { useMemo } from 'react';

export type ContainerProps = {
userId: MicrosoftTeamsUserIdentifier;
token: string;
locator: string;
displayName: string;
formFactor?: 'desktop' | 'mobile';
fluentTheme?: PartialTheme | Theme;
callInvitationURL?: string;
locale?: CompositeLocale;
options?: CallCompositeOptions;
meetingUrl?: string;
};

export const ContosoCallContainer = (props: ContainerProps): JSX.Element => {
const credential = useMemo(() => {
try {
return new AzureCommunicationTokenCredential(props.token); // <-- This props.token would be your Teams access token
} catch {
console.error('Failed to construct token credential');
return undefined;
}
}, [props.token]);

const adapter = useTeamsCallAdapter(
{
userId: props.userId,
credential,
locator: props.meetingUrl
? {
meetingLink: props.meetingUrl
}
: undefined
},
undefined,
leaveCall
);

if (!props.meetingUrl) {
return <>Teams meeting link is not provided.</>;
}

if (adapter) {
return (
<div style={{ height: '90vh', width: '90vw' }}>
<CallComposite
adapter={adapter}
formFactor={props.formFactor}
fluentTheme={props.fluentTheme}
callInvitationUrl={props?.callInvitationURL}
locale={props?.locale}
options={props?.options}
/>
</div>
);
}
if (credential === undefined) {
return <>Failed to construct credential. Provided token is malformed.</>;
}
return <>Initializing...</>;
};

const leaveCall = async (adapter: TeamsCallAdapter): Promise<void> => {
await adapter.leaveCall().catch((e) => {
console.error('Failed to leave call', e);
});
};

0 comments on commit 1a91053

Please sign in to comment.