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

Add Site Optios base screen #512

Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
32 changes: 32 additions & 0 deletions login-workflow/docs/screens/site-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# SiteOptionsScreen

A component to use for DERMS Auth workflow. It renders a message, an icon, and two buttons named `Create a New Organization` and `Join Existing Organization`.

<!-- TODO: This needs to be updatd in Full screen story -->
<!-- ![SiteOption](../../media/screens/success.png)

## Usage

```tsx
import { SiteOptionsScreenBase } from '@brightlayer-ui/react-auth-workflow';

...

<SiteOptionsScreen /> -->
```

## API

| Prop Name | Type | Description | Default |
|---|---|---|---|
| icon | `React.ReactNode` | The icon to be displayed on the screen. | |
| message | `ReactNode` | The success message to be displayed on the screen. | |
| canJoinExistingOrg | `boolean \| (() => boolean)` | Boolean or function that indicates whether the join existing organization button should be enabled. | `true` |
| canCreateNewOrg | `boolean \| (() => boolean)` | Boolean or function that indicates whether the create new organization button should be enabled. | `true` |
| joinExistingOrgLabel | `string` | The label for the custom button. Which redirects to the existing organization flow. | |
| createNewOrgLabel | `string` | label for the custom button which redirects to create a new organization flow. | |
| onJoinExistingOrg | `() => void` | A function to be called when the next button is clicked. | |
| onCreateNewOrg | `() => void` | A function to be called when the previous button is clicked. | |

This screen also extends the `WorkflowCardProps` type for updating the title, instructions, buttons, etc. See [Workflow Card](../components/workflow-card.md) for more details.

2 changes: 2 additions & 0 deletions login-workflow/example/src/navigation/AppRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ExampleHome } from '../screens/ExampleHome';
import i18nAppInstance from '../translations/i18n';
import { ChangePassword } from '../components/ChangePassword';
import { CreateNewOrgScreenBaseDemo } from '../screens/demo-components/CreateNewOrgScreenBaseDemo';
import { SiteOptionsScreenBaseDemo } from '../screens/demo-components/SiteOptionsScreenBaseDemo';

export const AppRouter: React.FC = () => {
const navigate = useNavigate();
Expand All @@ -44,6 +45,7 @@ export const AppRouter: React.FC = () => {
}
>
<Route path={'/create-new-org-base-screen-demo'} element={<CreateNewOrgScreenBaseDemo />} />
<Route path={'/site-options-base-screen-demo'} element={<SiteOptionsScreenBaseDemo />} />
<Route
path={'/login'}
element={
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import { SiteOptionsScreenBase } from '@brightlayer-ui/react-auth-workflow';
import DomainIcon from '@mui/icons-material/Domain';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';

export const SiteOptionsScreenBaseDemo: React.FC = () => (
<SiteOptionsScreenBase
icon={
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '100px',
height: '100px',
backgroundColor: '#e0eff8',
borderRadius: '50%',
}}
>
<DomainIcon color={'primary'} sx={{ fontSize: 54 }} />
</Box>
}
message={
<>
<Typography variant="subtitle2" sx={{ mb: 1 }}>
{`Now that you've specified your account details, you need to add your Organization details.`}
</Typography>
<Typography variant="subtitle2" sx={{ mb: 1 }}>
{`If you want to create a new Organization, choose Create a New Organization below.`}
</Typography>
<Typography variant="subtitle2">
{`If your Organization already exists, ask your administrator to provide you with the Registration
Code and choose Join Existing Organization below.`}
</Typography>
</>
}
createNewOrgLabel="Create a New Organization"
joinExistingOrgLabel="Join Existing Organization"
WorkflowCardHeaderProps={{
title: 'Join an Organization',
}}
onCreateNewOrg={(): void => {}}
onJoinExistingOrg={(): void => {}}
/>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import '@testing-library/jest-dom';
import { cleanup, render, screen } from '@testing-library/react';
import { SiteOptionsScreenBase } from './SiteOptionsScreenBase';
import ChatBubbleOutline from '@mui/icons-material/ChatBubbleOutline';

afterEach(cleanup);

describe('Forgot Password Screen Base', () => {
it('renders without crashing', () => {
render(
<SiteOptionsScreenBase
icon={<ChatBubbleOutline color={'primary'} sx={{ fontSize: 70 }} />}
message={`Now that you've specified your account details, you need to add your Organization details.`}
WorkflowCardHeaderProps={{ title: 'Join an Organization' }}
joinExistingOrgLabel="Join Existing Organization"
createNewOrgLabel="Create a New Organization"
/>
);
expect(screen.getByText('Join an Organization')).toBeInTheDocument();
expect(screen.getByText('Join Existing Organization')).toBeInTheDocument();
expect(screen.getByText(/Join Existing Organization/i)).toBeEnabled();
expect(screen.getByText('Create a New Organization')).toBeInTheDocument();
expect(screen.getByText(/Create a New Organization/i)).toBeEnabled();
});

it('enable Join Existing Organization button', () => {
render(
<SiteOptionsScreenBase
icon={<ChatBubbleOutline color={'primary'} sx={{ fontSize: 70 }} />}
message={`Now that you've specified your account details, you need to add your Organization details.`}
WorkflowCardHeaderProps={{ title: 'Join an Organization' }}
joinExistingOrgLabel="Join Existing Organization"
createNewOrgLabel="Create a New Organization"
canJoinExistingOrg={false}
/>
);
expect(screen.getByText('Join an Organization')).toBeInTheDocument();
expect(screen.getByText('Join Existing Organization')).toBeInTheDocument();
expect(screen.getByText(/Join Existing Organization/i)).toBeDisabled();
expect(screen.getByText('Create a New Organization')).toBeInTheDocument();
expect(screen.getByText(/Create a New Organization/i)).toBeEnabled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import React from 'react';
import { SiteOptionsScreenProps } from './types';
import { WorkflowCard, WorkflowCardHeader, WorkflowCardBody, WorkflowCardInstructions } from '../../components';
import Box from '@mui/material/Box';
import CardActions from '@mui/material/CardActions';
import Button from '@mui/material/Button';
import Divider from '@mui/material/Divider';
/**
* Component that renders a success screen
*
* @param icon the icon to be displayed on the screen
* @param message success message to be displayed on the screen
* @param joinExistingOrgLabel to display label for the custom button which redirects to existing organization flow
* @param createNewOrgLabel display label for the custom button which redirects to create a new organization flow
* @param onJoinExistingOrg function to call when user wants to join existing organization
* @param onCreateNewOrg function to call when user wants to create a new organization
* @param WorkflowCardBaseProps props that will be passed to the WorkflowCard component
* @param WorkflowCardHeaderProps props that will be passed to the WorkflowCardHeader component
* @param WorkflowCardInstructionProps props that will be passed to the WorkflowCardInstructions component
*
ektaghag-eaton marked this conversation as resolved.
Show resolved Hide resolved
* @category Component
*/

export const SiteOptionsScreenBase: React.FC<React.PropsWithChildren<SiteOptionsScreenProps>> = (props) => {
const {
icon,
message = '',
joinExistingOrgLabel = '',
createNewOrgLabel = '',
canCreateNewOrg,
canJoinExistingOrg,
onJoinExistingOrg,
onCreateNewOrg,
} = props;
const cardBaseProps = props.WorkflowCardBaseProps || {};
const headerProps = props.WorkflowCardHeaderProps || {};
const instructionsProps = props.WorkflowCardInstructionProps || {};
return (
<WorkflowCard {...cardBaseProps}>
<WorkflowCardHeader {...headerProps} />
{Object.keys(instructionsProps).length !== 0 && <WorkflowCardInstructions {...instructionsProps} />}
<WorkflowCardBody>
ektaghag-eaton marked this conversation as resolved.
Show resolved Hide resolved
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
}}
>
{icon && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
mb: 6,
}}
>
{icon}
</Box>
)}
{message && (
<Box
sx={{
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}}
>
{message}
</Box>
)}
</Box>
</WorkflowCardBody>
<Divider />
<Box
sx={{
p: { xs: 2, md: 3 },
}}
>
<CardActions
sx={[
{
flexDirection: 'column',
justifyContent: 'flex-end',
p: 0,
'>:not(:first-of-type)': {
ml: 0,
},
},
]}
>
<Button
variant="outlined"
color="primary"
fullWidth
sx={{
mb: { xs: 2, md: 3 },
}}
disabled={
canCreateNewOrg === false || (typeof canCreateNewOrg === 'function' && !canCreateNewOrg())
}
onClick={onCreateNewOrg}
>
{createNewOrgLabel}
</Button>
<Button
variant="contained"
color="primary"
fullWidth
disabled={
canJoinExistingOrg === false ||
(typeof canJoinExistingOrg === 'function' && !canJoinExistingOrg())
}
onClick={onJoinExistingOrg}
sx={{
ml: 0,
}}
>
{joinExistingOrgLabel}
</Button>
</CardActions>
</Box>
</WorkflowCard>
);
};
2 changes: 2 additions & 0 deletions login-workflow/src/screens/SiteOptionsScreen/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './SiteOptionsScreenBase';
export * from './types';
51 changes: 51 additions & 0 deletions login-workflow/src/screens/SiteOptionsScreen/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { WorkflowCardProps } from '../../components/WorkflowCard/WorkflowCard.types';
import { ErrorManagerProps } from '../../components/Error';
import { ReactNode } from 'react';

export type SiteOptionsScreenProps = WorkflowCardProps & {
/**
* The icon to display in the header
*/
icon?: JSX.Element;

/**
ektaghag-eaton marked this conversation as resolved.
Show resolved Hide resolved
* The success message to be displayed on the screen
*/
message?: ReactNode;
/**
* Boolean or function that indicates whether the join existing organization button should be enabled
*/
canJoinExistingOrg?: boolean | (() => boolean);

/**
* Boolean or function that indicates whether the create new organization button should be enabled
*/
canCreateNewOrg?: boolean | (() => boolean);

/**
* To display label for the custom button which redirects to existing organization flow
*/
joinExistingOrgLabel?: string;

/**
* To display label for the custom button which redirects create new organization flow
*/
createNewOrgLabel?: string;

/**
* The function to call when user wants to join existing organization
* @returns void
*/
onJoinExistingOrg?: () => void;

/**
* The function to call when user wants to create a new organization
* @returns void
*/
onCreateNewOrg?: () => void;

/**
* The configuration for customizing how errors are displayed
*/
errorDisplayConfig?: ErrorManagerProps;
};
1 change: 1 addition & 0 deletions login-workflow/src/screens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export * from './ForgotPasswordScreen';
export * from './ContactScreen';
export * from './RegistrationSuccessScreen';
export * from './ExistingAccountSuccessScreen';
export * from './SiteOptionsScreen';
export * from './CreateNewOrgScreen';
Loading
Loading