Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a useIsSignedIn custom hook for react #3093

Merged
merged 24 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9fae7b0
Add signed in state core functionality
musale Feb 28, 2024
60518b7
Add a hook to check and set the signed in state
musale Feb 28, 2024
28d3a3b
Add documentation of custom hooks on read me
musale Feb 28, 2024
2c2eca0
Prettier fixes
musale Feb 28, 2024
d277ca3
Add tests for signedInState
musale Feb 28, 2024
fdd48f8
Update the react-contoso sample to use the mgt-react hook
musale Feb 28, 2024
382f15b
Update the tests
musale Feb 28, 2024
f4ba3b1
Remove the useSignedIn hook from samples
musale Feb 28, 2024
bff89fc
Move the hook into a hooks folder in mgt-reactr
musale Feb 28, 2024
cdc41b6
Merge branch 'main' of github.com:microsoftgraph/microsoft-graph-tool…
musale Feb 28, 2024
a333da9
Remove unused imports
musale Feb 28, 2024
e539418
Update packages/mgt-element/src/utils/signedInState.tests.ts
musale Feb 29, 2024
3102df3
Rename utility function to isSignedIn
musale Feb 29, 2024
929c24a
Merge remote-tracking branch 'origin' into feat/signed-in-hook
musale Mar 5, 2024
a6d7153
Rename file to isSignedIn to match function name
musale Mar 5, 2024
d4f577a
Fix tests for provider settings
musale Mar 5, 2024
37adb6e
Add sample stories for HTML and React usages
musale Mar 5, 2024
852e821
Update the tests with a check for change when setState is called
musale Mar 6, 2024
4cfaa1a
Merge branch 'main' into feat/signed-in-hook
musale Mar 7, 2024
badead2
Merge branch 'main' into feat/signed-in-hook
musale Mar 12, 2024
329b294
Add a block line suppression for un-used expressions in tests
musale Mar 12, 2024
b8cbf84
Merge branch 'main' into feat/signed-in-hook
gavinbarron Mar 18, 2024
696bb6a
Refactor as ternary to avoid returning undefined
musale Mar 21, 2024
84b1c3d
Merge branch 'main' into feat/signed-in-hook
gavinbarron Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/mgt-element/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export * from './utils/LocalizationHelper';
export * from './utils/mgtHtml';
export * from './utils/CustomElement';
export * from './utils/registerComponent';
export * from './utils/isSignedIn';

export { PACKAGE_VERSION } from './utils/version';

Expand Down
22 changes: 22 additions & 0 deletions packages/mgt-element/src/utils/isSignedIn.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

import { expect } from '@open-wc/testing';
import { MockProvider } from '../mock/MockProvider';
import { ProviderState } from '../providers/IProvider';
import { Providers } from '../providers/Providers';
import { isSignedIn } from './isSignedIn';

describe('signedInState', () => {
it('should change', () => {
/* eslint-disable @typescript-eslint/no-unused-expressions */
Providers.globalProvider = new MockProvider(false);
expect(isSignedIn()).to.be.false;
Providers.globalProvider.setState(ProviderState.SignedIn);
expect(isSignedIn()).to.be.true;
});
musale marked this conversation as resolved.
Show resolved Hide resolved
});
19 changes: 19 additions & 0 deletions packages/mgt-element/src/utils/isSignedIn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

import { ProviderState } from '../providers/IProvider';
import { Providers } from '../providers/Providers';

/**
* Checks the provider state if it's in signed in.
*
* @returns true if signed in, otherwise false.
*/
export const isSignedIn = (): boolean => {
const provider = Providers.globalProvider;
return provider && provider.state === ProviderState.SignedIn;
};
18 changes: 18 additions & 0 deletions packages/mgt-react/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ const App = (props) => {

The `template` prop allows you to specify which template to overwrite. In this case, the `MyEvent` component will be repeated for every event, and the `event` object will be passed as part of the `dataContext` prop.

## Custom hooks

`mgt-react` exposes some custom hooks that you can use in your app:

### `useIsSignedIn`

You can use this hook to check the signed in state:

```tsx
import { Agenda, useIsSignedIn } from '@microsoft/mgt-react';

const App = (props) => {
const [isSignedIn] = useIsSignedIn();

return {isSignedIn && <Agenda></Agenda>}
}
```

## Why

If you've used web components in React, you know that proper interop between web components and React components requires a bit of extra work.
Expand Down
8 changes: 8 additions & 0 deletions packages/mgt-react/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

export * from './useIsSignedIn';
31 changes: 31 additions & 0 deletions packages/mgt-react/src/hooks/useIsSignedIn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

import { isSignedIn, Providers } from '@microsoft/mgt-element';
import { useState, useEffect } from 'react';

/**
* Hook to check if a user is signed in.
*
* @returns true if a user is signed on, otherwise false.
*/
export const useIsSignedIn = (): [boolean] => {
const [signedIn, setIsSignedIn] = useState(false);
useEffect(() => {
const updateState = () => {
setIsSignedIn(isSignedIn());
};

Providers.onProviderUpdated(updateState);
updateState();

return () => {
Providers.removeProviderUpdatedListener(updateState);
};
}, [setIsSignedIn]);
return [signedIn];
};
1 change: 1 addition & 0 deletions packages/mgt-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
export * from './Mgt';
export * from './MgtTemplateProps';
export * from './generated/react';
export * from './hooks';
export * from '@microsoft/mgt-components/dist/es6/exports';
export * from '@microsoft/mgt-element';
2 changes: 1 addition & 1 deletion samples/react-contoso/src/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { Suspense, lazy } from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Header } from './components/Header';
import { SideNavigation } from './components/SideNavigation';
import { useIsSignedIn } from './hooks/useIsSignedIn';
import { useIsSignedIn } from '@microsoft/mgt-react';
import { NavigationItem } from './models/NavigationItem';
import { getNavigation } from './services/Navigation';
import { FluentProvider, makeStyles, mergeClasses, shorthands } from '@fluentui/react-components';
Expand Down
12 changes: 3 additions & 9 deletions samples/react-contoso/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import * as React from 'react';
import { Login, SearchBox } from '@microsoft/mgt-react';
import { Login, SearchBox, useIsSignedIn } from '@microsoft/mgt-react';
import { PACKAGE_VERSION } from '@microsoft/mgt-element';
import { InfoButton } from '@fluentui/react-components/unstable';
import { SimpleLogin } from './SimpleLogin';
import { useIsSignedIn } from '../hooks/useIsSignedIn';
import { useNavigate } from 'react-router-dom';
import { ThemeSwitcher } from './ThemeSwitcher';
import { useAppContext } from '../AppContext';
import { Label, makeStyles, mergeClasses, shorthands, tokens } from '@fluentui/react-components';
import { Label, makeStyles, mergeClasses, shorthands, tokens, InfoLabel } from '@fluentui/react-components';
import { GridDotsRegular } from '@fluentui/react-icons';
import { useLocation } from 'react-router-dom';

Expand Down Expand Up @@ -149,11 +147,7 @@ const HeaderComponent: React.FunctionComponent = () => {

<div className={styles.waffleTitle}>
<Label className={styles.name}>{import.meta.env.VITE_SITE_NAME} </Label>
<InfoButton
className={styles.infoIcon}
size="medium"
info={<>Using the Graph Toolkit v{PACKAGE_VERSION}</>}
/>
<InfoLabel className={styles.infoIcon} size="medium" info={<>Using the Graph Toolkit v{PACKAGE_VERSION}</>} />
</div>
</div>
<div className={styles.search}>
Expand Down
23 changes: 0 additions & 23 deletions samples/react-contoso/src/hooks/useIsSignedIn.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { html } from 'lit';
import { withCodeEditor } from '../../.storybook/addons/codeEditorAddon/codeAddon';

export default {
title: 'Samples / General',
title: 'Samples / General / HTML',
decorators: [withCodeEditor],
parameters: {
viewMode: 'story'
Expand Down Expand Up @@ -89,7 +89,7 @@ export const Localization = () => html`
</script>
`;

export const cache = () => html`
export const Cache = () => html`
<fluent-button id="ClearCacheButton" appearance="accent">Clear Cache</fluent-button>
<div id="status" class="notes"></div>
<span class="notes"
Expand Down Expand Up @@ -169,7 +169,7 @@ clearCacheButton.addEventListener('click', onClearCacheButtonClick);
</script>
`;

export const theme = () => html`
export const Theme = () => html`
<div>
<p>This demonstrates how to set the theme globally without using a theme toggle and customize styling within specific scopes</p>
<p>Please refer to the JS and CSS tabs in the editor for implentation details</p>
Expand Down Expand Up @@ -223,3 +223,17 @@ body {
}
</style>
`;

export const IsSignedIn = () => html`
<p>This demonstrates how to use the <code>isSignedIn</code> utility function in JavaScript. If you're signed in, <code>mgt-person</code> is rendered below.</p>
<div id="person"></div>
<script>
import { isSignedIn } from '@microsoft/mgt-element';
const person = document.getElementById("person");
if(isSignedIn() && person){
const mgtPerson = document.createElement("mgt-person");
mgtPerson.setAttribute("person-query", "me");
person.appendChild(mgtPerson);
}
</script>
`;
28 changes: 28 additions & 0 deletions stories/samples/general.react.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

import { html } from 'lit';
import { withCodeEditor } from '../../.storybook/addons/codeEditorAddon/codeAddon';

export default {
title: 'Samples / General / React',
component: 'person-card',
decorators: [withCodeEditor]
};

export const Hooks = () => html`
<p>This demonstrates how to use the <code>useIsSignedIn</code> hook in React.</p>
<mgt-person-card person-query="me"></mgt-person-card>
<react>
import { PersonCard, useIsSignedIn } from '@microsoft/mgt-react';
const [isSignedIn] = useIsSignedIn();

export default () => (
isSignedIn && <PersonCard personQuery="me"></PersonCard>
musale marked this conversation as resolved.
Show resolved Hide resolved
);
</react>
`;
Loading