Skip to content

Commit 37e8a19

Browse files
feat(preview): add new sign dropdown under ff (#3190)
* feat(preview): add new sign dropdown under ff * fix: Trigger Build
1 parent f1f5c81 commit 37e8a19

File tree

7 files changed

+175
-17
lines changed

7 files changed

+175
-17
lines changed

i18n/en-US.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,12 @@ be.contentSidebar.boxSignFtuxBody = Sign documents or send signature requests, r
320320
be.contentSidebar.boxSignFtuxTitle = Box Sign - Secure, seamless e-signatures in Box
321321
# label for button that opens a Box Sign signature request experience
322322
be.contentSidebar.boxSignRequest = Request Signature
323+
# One of the dropdown options that opens a Box Sign request signature experience
324+
be.contentSidebar.boxSignRequestSignature = Request Signature
323325
# Tooltip text for when Box Sign is blocked due to a security policy
324326
be.contentSidebar.boxSignSecurityBlockedTooltip = This action is unavailable due to a security policy.
327+
# One of the dropdown options that opens a Box Sign sign myself experience
328+
be.contentSidebar.boxSignSignMyself = Sign Myself
325329
# label for button that opens a Box Sign signature fulfillment experience
326330
be.contentSidebar.boxSignSignature = Sign
327331
# Tooltip text for when Box Sign is blocked due to an item being watermarked

src/elements/content-sidebar/SidebarNav.js

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import IconDocInfo from '../../icons/general/IconDocInfo';
1313
import IconMagicWand from '../../icons/general/IconMagicWand';
1414
import IconMetadataThick from '../../icons/general/IconMetadataThick';
1515
import SidebarNavButton from './SidebarNavButton';
16-
import SidebarNavSignButton from './SidebarNavSignButton';
16+
import SidebarNavSign from './SidebarNavSign';
1717
import SidebarNavTablist from './SidebarNavTablist';
1818
import SidebarToggle from './SidebarToggle';
1919
import messages from '../common/messages';
@@ -54,13 +54,7 @@ const SidebarNav = ({
5454
isOpen,
5555
onNavigate,
5656
}: Props) => {
57-
const {
58-
blockedReason: boxSignBlockedReason,
59-
enabled: hasBoxSign,
60-
onClick: onBoxSignClick,
61-
status: boxSignStatus,
62-
targetingApi: boxSignTargetingApi,
63-
} = useFeatureConfig('boxSign');
57+
const { enabled: hasBoxSign } = useFeatureConfig('boxSign');
6458

6559
return (
6660
<div className="bcs-SidebarNav" aria-label={intl.formatMessage(messages.sidebarNavLabel)}>
@@ -108,15 +102,9 @@ const SidebarNav = ({
108102
)}
109103
</SidebarNavTablist>
110104

111-
{hasBoxSign && onBoxSignClick && (
105+
{hasBoxSign && (
112106
<div className="bcs-SidebarNav-secondary">
113-
<SidebarNavSignButton
114-
blockedReason={boxSignBlockedReason}
115-
data-resin-target={SIDEBAR_NAV_TARGETS.SIGN}
116-
onClick={() => onBoxSignClick({ fileId })}
117-
status={boxSignStatus}
118-
targetingApi={boxSignTargetingApi}
119-
/>
107+
<SidebarNavSign />
120108
</div>
121109
)}
122110

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import '../../styles/variables';
2+
3+
.bcs-SidebarNavSign-icon path {
4+
fill: $bdl-gray;
5+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react';
2+
import { FormattedMessage } from 'react-intl';
3+
4+
// @ts-ignore Module is written in Flow
5+
import { useFeatureConfig } from '../common/feature-checking';
6+
// @ts-ignore Module is written in Flow
7+
import { SIDEBAR_NAV_TARGETS } from '../common/interactionTargets';
8+
9+
// @ts-ignore Module is written in Flow
10+
import DropdownMenu from '../../components/dropdown-menu';
11+
import SidebarNavSignButton from './SidebarNavSignButton';
12+
import SignMe32 from '../../icon/fill/SignMe32';
13+
import SignMeOthers32 from '../../icon/fill/SignMeOthers32';
14+
import { Menu, MenuItem } from '../../components/menu';
15+
16+
// @ts-ignore Module is written in Flow
17+
import messages from './messages';
18+
19+
import './SidebarNavSign.scss';
20+
21+
export function SidebarNavSign() {
22+
const {
23+
blockedReason: boxSignBlockedReason,
24+
onClick: onBoxClickRequestSignature,
25+
onClickSignMyself: onBoxClickSignMyself,
26+
status: boxSignStatus,
27+
targetingApi: boxSignTargetingApi,
28+
isSignRemoveInterstitialEnabled,
29+
} = useFeatureConfig('boxSign');
30+
31+
return (
32+
<>
33+
{isSignRemoveInterstitialEnabled ? (
34+
<DropdownMenu isResponsive constrainToWindow isRightAligned>
35+
<SidebarNavSignButton
36+
blockedReason={boxSignBlockedReason}
37+
status={boxSignStatus}
38+
targetingApi={boxSignTargetingApi}
39+
data-resin-target={SIDEBAR_NAV_TARGETS.SIGN}
40+
/>
41+
<Menu>
42+
<MenuItem data-testid="sign-request-signature-button" onClick={onBoxClickRequestSignature}>
43+
<SignMeOthers32 width={16} height={16} className="bcs-SidebarNavSign-icon" />
44+
<FormattedMessage {...messages.boxSignRequestSignature} />
45+
</MenuItem>
46+
<MenuItem data-testid="sign-sign-myself-button" onClick={onBoxClickSignMyself}>
47+
<SignMe32 width={16} height={16} className="bcs-SidebarNavSign-icon" />
48+
<FormattedMessage {...messages.boxSignSignMyself} />
49+
</MenuItem>
50+
</Menu>
51+
</DropdownMenu>
52+
) : (
53+
<SidebarNavSignButton
54+
blockedReason={boxSignBlockedReason}
55+
data-resin-target={SIDEBAR_NAV_TARGETS.SIGN}
56+
onClick={onBoxClickRequestSignature}
57+
status={boxSignStatus}
58+
targetingApi={boxSignTargetingApi}
59+
/>
60+
)}
61+
</>
62+
);
63+
}
64+
65+
export default SidebarNavSign;

src/elements/content-sidebar/SidebarNavSignButton.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,13 @@ export function SidebarNavSignButton({ blockedReason, intl, status, targetingApi
5555
useTargetingApi={() => targetingApi}
5656
>
5757
<Tooltip isDisabled={isTargeted} position={TooltipPosition.MIDDLE_LEFT} text={tooltipMessage}>
58-
<PlainButton aria-label={label} className={buttonClassName} isDisabled={isSignDisabled} {...rest}>
58+
<PlainButton
59+
aria-label={label}
60+
className={buttonClassName}
61+
data-testid="sign-button"
62+
isDisabled={isSignDisabled}
63+
{...rest}
64+
>
5965
<BoxSign28 className="bcs-SidebarNavSignButton-icon" />
6066
<Sign16 width={20} height={20} className="bcs-SidebarNavSignButton-icon--grayscale" />
6167
</PlainButton>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React from 'react';
2+
import { render, fireEvent } from '@testing-library/react';
3+
import SidebarNavSign from '../SidebarNavSign';
4+
// @ts-ignore Module is written in Flow
5+
import FeatureProvider from '../../common/feature-checking/FeatureProvider';
6+
7+
describe('elements/content-sidebar/SidebarNavSign', () => {
8+
const onClickRequestSignature = jest.fn();
9+
const onClickSignMyself = jest.fn();
10+
11+
const renderComponent = (props = {}, features = {}) =>
12+
render(
13+
<FeatureProvider features={features}>
14+
<SidebarNavSign {...props} />
15+
</FeatureProvider>,
16+
);
17+
18+
test.each([true, false])('should render sign button', isRemoveInterstitialEnabled => {
19+
const features = {
20+
boxSign: {
21+
isSignRemoveInterstitialEnabled: isRemoveInterstitialEnabled,
22+
},
23+
};
24+
25+
const wrapper = renderComponent({}, features);
26+
expect(wrapper.getByTestId('sign-button')).toBeVisible();
27+
});
28+
29+
test('should call correct handler when sign button is clicked', () => {
30+
const features = {
31+
boxSign: {
32+
isSignRemoveInterstitialEnabled: false,
33+
onClick: onClickRequestSignature,
34+
},
35+
};
36+
const { getByTestId } = renderComponent({}, features);
37+
38+
fireEvent.click(getByTestId('sign-button'));
39+
40+
expect(onClickRequestSignature).toBeCalled();
41+
});
42+
43+
test('should open dropdown with 2 menu items when sign button is clicked', () => {
44+
const features = {
45+
boxSign: {
46+
isSignRemoveInterstitialEnabled: true,
47+
},
48+
};
49+
const { getByTestId } = renderComponent({}, features);
50+
fireEvent.click(getByTestId('sign-button'));
51+
expect(getByTestId('sign-request-signature-button')).toBeVisible();
52+
expect(getByTestId('sign-sign-myself-button')).toBeVisible();
53+
});
54+
55+
test('should call correct handler when request signature option is clicked', () => {
56+
const features = {
57+
boxSign: {
58+
isSignRemoveInterstitialEnabled: true,
59+
onClick: onClickRequestSignature,
60+
},
61+
};
62+
const { getByTestId } = renderComponent({}, features);
63+
fireEvent.click(getByTestId('sign-button'));
64+
fireEvent.click(getByTestId('sign-request-signature-button'));
65+
expect(onClickRequestSignature).toBeCalled();
66+
});
67+
68+
test('should call correct handler when sign myself option is clicked', () => {
69+
const features = {
70+
boxSign: {
71+
isSignRemoveInterstitialEnabled: true,
72+
onClickSignMyself,
73+
},
74+
};
75+
const { getByTestId } = renderComponent({}, features);
76+
fireEvent.click(getByTestId('sign-button'));
77+
fireEvent.click(getByTestId('sign-sign-myself-button'));
78+
expect(onClickSignMyself).toBeCalled();
79+
});
80+
});

src/elements/content-sidebar/messages.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ const messages = defineMessages({
3232
defaultMessage: 'Request Signature',
3333
description: 'label for button that opens a Box Sign signature request experience',
3434
},
35+
boxSignRequestSignature: {
36+
id: 'be.contentSidebar.boxSignRequestSignature',
37+
defaultMessage: 'Request Signature',
38+
description: 'One of the dropdown options that opens a Box Sign request signature experience',
39+
},
40+
boxSignSignMyself: {
41+
id: 'be.contentSidebar.boxSignSignMyself',
42+
defaultMessage: 'Sign Myself',
43+
description: 'One of the dropdown options that opens a Box Sign sign myself experience',
44+
},
3545
boxSignSignature: {
3646
id: 'be.contentSidebar.boxSignSignature',
3747
defaultMessage: 'Sign',

0 commit comments

Comments
 (0)