Skip to content

Commit 1c16476

Browse files
authored
Adding styleOptions to support file type restriction and single file upload (#5048)
* Add style option to allow for file type narrowing * Rename and add multi upload prop * Fix launch config type * Add e2e test to validate <input> * Resolve comments * Revert to true * Resolve e2e test * Added changelog entry
1 parent 3d09177 commit 1c16476

File tree

8 files changed

+74
-8
lines changed

8 files changed

+74
-8
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"version": "0.2.0",
66
"configurations": [
77
{
8-
"type": "edge",
8+
"type": "msedge",
99
"request": "launch",
1010
"name": "Launch Microsoft Edge",
1111
"url": "http://localhost:5000/samples/",

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
2222

2323
## [Unreleased]
2424

25+
### Added
26+
27+
- Resolves [#5081](https://github.com/microsoft/BotFramework-WebChat/issues/5081). Added `uploadAccept` and `uploadMultiple` style options, by [@ms-jb](https://github.com/ms-jb)
28+
2529
### Changed
2630

2731
- Moved pull request validation pipeline to GitHub Actions, by [@compulim](https://github.com/compulim), in PR [#4976](https://github.com/microsoft/BotFramework-WebChat/pull/4976)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script crossorigin="anonymous" src="/test-harness.js"></script>
6+
<script crossorigin="anonymous" src="/test-page-object.js"></script>
7+
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
8+
</head>
9+
<body>
10+
<main id="webchat"></main>
11+
<script>
12+
run(async function () {
13+
const directLine = WebChat.createDirectLine({ token: await testHelpers.token.fetchDirectLineToken() });
14+
const store = testHelpers.createStore();
15+
16+
WebChat.renderWebChat(
17+
{
18+
directLine,
19+
store: testHelpers.createStore(),
20+
styleOptions: {
21+
uploadAccept: 'image/*',
22+
uploadMultiple: false
23+
}
24+
},
25+
document.getElementById('webchat')
26+
);
27+
28+
await pageConditions.uiConnected();
29+
30+
// Validate the <input> element has the correct file types
31+
const uploadButton = pageElements.uploadButton()
32+
expect(uploadButton).toHaveProperty('accept', 'image/*');
33+
expect(uploadButton).toHaveProperty('multiple', false);
34+
35+
});
36+
</script>
37+
</body>
38+
</html>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */
2+
3+
describe('Attachment', () => {
4+
test('with allowed file types', () =>
5+
runHTML('attachment.allowedFileTypes.html'));
6+
});

packages/api/src/StyleOptions.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ type StyleOptions = {
259259
microphoneButtonColorOnDictate?: string;
260260
sendBoxBackground?: string;
261261

262+
/**
263+
* The comma-delimited file types that the upload button should accept.
264+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept
265+
* @example 'image/*,.pdf'
266+
*/
267+
uploadAccept?: string;
268+
/**
269+
* If true, the upload button will accept multiple files.
270+
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#multiple
271+
*/
272+
uploadMultiple?: boolean;
273+
262274
/** Send box button: Icon color, defaults to subtle */
263275
sendBoxButtonColor?: string;
264276

packages/api/src/defaultStyleOptions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ const DEFAULT_OPTIONS: Required<StyleOptions> = {
9595
hideUploadButton: false,
9696
microphoneButtonColorOnDictate: '#F33',
9797
sendBoxBackground: 'White',
98+
uploadAccept: undefined,
99+
uploadMultiple: true,
98100

99101
// Send box buttons
100102
sendBoxButtonColor: undefined,

packages/component/src/SendBox/UploadButton.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import classNames from 'classnames';
33
import PropTypes from 'prop-types';
44
import React, { FC, useCallback, useRef } from 'react';
55

6-
import AttachmentIcon from './Assets/AttachmentIcon';
7-
import connectToWebChat from '../connectToWebChat';
86
import downscaleImageToDataURL from '../Utils/downscaleImageToDataURL/index';
9-
import IconButton from './IconButton';
7+
import connectToWebChat from '../connectToWebChat';
8+
import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject';
109
import useSendFiles from '../hooks/useSendFiles';
1110
import useStyleSet from '../hooks/useStyleSet';
12-
import useStyleToEmotionObject from '../hooks/internal/useStyleToEmotionObject';
11+
import AttachmentIcon from './Assets/AttachmentIcon';
12+
import IconButton from './IconButton';
1313

14-
const { useDisabled, useLocalizer } = hooks;
14+
const { useDisabled, useLocalizer, useStyleOptions } = hooks;
1515

1616
const ROOT_STYLE = {
1717
'&.webchat__upload-button': {
@@ -95,6 +95,7 @@ type UploadButtonProps = {
9595

9696
const UploadButton: FC<UploadButtonProps> = ({ className }) => {
9797
const [{ uploadButton: uploadButtonStyleSet }] = useStyleSet();
98+
const [{ uploadAccept, uploadMultiple }] = useStyleOptions();
9899
const [disabled] = useDisabled();
99100
const inputRef = useRef<HTMLInputElement>();
100101
const localize = useLocalizer();
@@ -122,10 +123,11 @@ const UploadButton: FC<UploadButtonProps> = ({ className }) => {
122123
return (
123124
<div className={classNames(rootClassName, 'webchat__upload-button', uploadButtonStyleSet + '', className)}>
124125
<input
126+
accept={uploadAccept}
125127
aria-disabled={disabled}
126128
aria-hidden="true"
127129
className="webchat__upload-button--file-input"
128-
multiple={true}
130+
multiple={uploadMultiple}
129131
onChange={disabled ? undefined : handleFileChange}
130132
onClick={disabled ? PREVENT_DEFAULT_HANDLER : undefined}
131133
readOnly={disabled}

packages/test/page-object/src/globals/pageElements/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import transcript from './transcript';
1919
import transcriptLiveRegion from './transcriptLiveRegion';
2020
import transcriptScrollable from './transcriptScrollable';
2121
import transcriptTerminator from './transcriptTerminator';
22+
import uploadButton from './uploadButton';
2223

2324
export {
2425
activeActivity,
@@ -41,5 +42,6 @@ export {
4142
transcript,
4243
transcriptLiveRegion,
4344
transcriptScrollable,
44-
transcriptTerminator
45+
transcriptTerminator,
46+
uploadButton
4547
};

0 commit comments

Comments
 (0)