From a853a966a4f69c30772a3b45725d3054cf11a3c5 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Wed, 11 Mar 2020 16:02:38 -0700 Subject: [PATCH 1/2] 4.8 blockers Copy to clipboard fixed Making sure restart conversation does not show up in Transcript or Debug mode Signed-off-by: Srinaath Ravichandran --- .../botCreationDialog.spec.tsx | 21 ++----- .../botCreationDialog/botCreationDialog.tsx | 17 +++--- .../emulator/parts/chat/activityWrapper.tsx | 6 +- .../ui/editor/emulator/parts/chat/chat.tsx | 4 ++ .../parts/chat/outerActivityWrapper.tsx | 6 +- .../client/src/utils/copyToClipBord.spec.ts | 59 +++++++++++++++++++ .../app/client/src/utils/copyToClipboard.ts | 41 +++++++++++++ packages/app/client/src/utils/index.ts | 1 + 8 files changed, 126 insertions(+), 29 deletions(-) create mode 100644 packages/app/client/src/utils/copyToClipBord.spec.ts create mode 100644 packages/app/client/src/utils/copyToClipboard.ts diff --git a/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.spec.tsx b/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.spec.tsx index 0c054784b..3a5a15401 100644 --- a/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.spec.tsx +++ b/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.spec.tsx @@ -42,12 +42,14 @@ import { ariaAlertService } from '../../a11y'; import { BotCreationDialog, BotCreationDialogState } from './botCreationDialog'; import { BotCreationDialogContainer } from './botCreationDialogContainer'; +const mockCopyToClipboard = jest.fn(args => true); jest.mock('../index', () => null); jest.mock('../../../utils', () => ({ debounce: (func: () => any) => func, generateBotSecret: () => { return Math.random() + ''; }, + copyTextToClipboard: args => mockCopyToClipboard(args), })); jest.mock('electron', () => ({ @@ -140,26 +142,13 @@ describe('BotCreationDialog tests', () => { it('should execute a window copy command when copy is clicked', () => { testWrapper.instance().setState({ encryptKey: true }); - // mock window functions - const backupExec = window.document.execCommand; - const mockExec = jest.fn((_command: string) => null); - const backupGetElementById = window.document.getElementById; - const mockGetElementById = _selector => ({ - removeAttribute: () => null, - select: () => null, - setAttribute: () => null, - }); - (window.document.getElementById as any) = mockGetElementById; - window.document.execCommand = mockExec; const alertServiceSpy = jest.spyOn(ariaAlertService, 'alert').mockReturnValueOnce(undefined); (testWrapper.instance() as any).onCopyClick(); - expect(mockExec).toHaveBeenCalledWith('copy'); expect(alertServiceSpy).toHaveBeenCalledWith('Secret copied to clipboard.'); - - // restore window functions - window.document.execCommand = backupExec; - window.document.getElementById = backupGetElementById; + mockCopyToClipboard.mockReturnValueOnce(false); + (testWrapper.instance() as any).onCopyClick(); + expect(alertServiceSpy).toHaveBeenCalledWith('Failed to copy secret to clipboard.'); }); it('should set state via input change handlers', () => { diff --git a/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.tsx b/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.tsx index fea54507a..dc1c4ba68 100644 --- a/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.tsx +++ b/packages/app/client/src/ui/dialogs/botCreationDialog/botCreationDialog.tsx @@ -52,7 +52,7 @@ import * as React from 'react'; import { CommandServiceImpl, CommandServiceInstance } from '@bfemulator/sdk-shared'; import { store } from '../../../state/store'; -import { generateBotSecret, debounce } from '../../../utils'; +import { generateBotSecret, debounce, copyTextToClipboard } from '../../../utils'; import { ActiveBotHelper } from '../../helpers/activeBotHelper'; import { DialogService } from '../service'; import { ariaAlertService } from '../../a11y'; @@ -295,13 +295,14 @@ export class BotCreationDialog extends React.Component { activity: Activity; children: ReactNode; isSelected: boolean; - isUserActivity: boolean; onRestartConversationFromActivityClick: () => void; + showRestartBubble: boolean; } // Returns false if the event target is normally an interactive element. @@ -65,10 +65,10 @@ function shouldSelectActivity(e: React.SyntheticEvent): boolean { export class ActivityWrapper extends Component { render() { - const { activity: _, children, isSelected, isUserActivity, ...divProps } = this.props; + const { activity: _, children, isSelected, showRestartBubble, ...divProps } = this.props; let classes = styles.chatActivity; const restartConversationBubble = ( -
+
Restart conversation from here diff --git a/packages/app/client/src/ui/editor/emulator/parts/chat/chat.tsx b/packages/app/client/src/ui/editor/emulator/parts/chat/chat.tsx index c9a91f086..5f2053db1 100644 --- a/packages/app/client/src/ui/editor/emulator/parts/chat/chat.tsx +++ b/packages/app/client/src/ui/editor/emulator/parts/chat/chat.tsx @@ -139,6 +139,9 @@ export class Chat extends PureComponent { } private activityWrapper(next, card, children): ReactNode { + const { mode, restartStatus } = this.props; + const isWebChatDisabled = + mode === 'transcript' || mode === 'debug' || restartStatus === RestartConversationStatus.Started; return ( { onItemRendererClick={this.onItemRendererClick} onItemRendererKeyDown={this.onItemRendererKeyDown} restartStatusForActivity={this.props.restartStatus} + isWebChatDisabled={isWebChatDisabled} > {next(card)(children)} diff --git a/packages/app/client/src/ui/editor/emulator/parts/chat/outerActivityWrapper.tsx b/packages/app/client/src/ui/editor/emulator/parts/chat/outerActivityWrapper.tsx index 6cf1c14bf..188d54556 100644 --- a/packages/app/client/src/ui/editor/emulator/parts/chat/outerActivityWrapper.tsx +++ b/packages/app/client/src/ui/editor/emulator/parts/chat/outerActivityWrapper.tsx @@ -54,14 +54,16 @@ export interface OuterActivityWrapperProps { restartOption: RestartConversationOptions ) => void; currentRestartConversationOption: RestartConversationOptions; + isWebChatDisabled: boolean; } export class OuterActivityWrapper extends React.Component { public render() { - const { card, children, onContextMenu, onItemRendererClick, onItemRendererKeyDown } = this.props; + const { card, children, onContextMenu, onItemRendererClick, onItemRendererKeyDown, isWebChatDisabled } = this.props; const isSelected = this.shouldBeSelected(card.activity); const isUserActivity = this.isUserActivity(card.activity); + const showRestartBubble = isUserActivity && isSelected && !isWebChatDisabled; return ( {children} diff --git a/packages/app/client/src/utils/copyToClipBord.spec.ts b/packages/app/client/src/utils/copyToClipBord.spec.ts new file mode 100644 index 000000000..7d58408e5 --- /dev/null +++ b/packages/app/client/src/utils/copyToClipBord.spec.ts @@ -0,0 +1,59 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// +// Microsoft Bot Framework: http://botframework.com +// +// Bot Framework Emulator Github: +// https://github.com/Microsoft/BotFramwork-Emulator +// +// Copyright (c) Microsoft Corporation +// All rights reserved. +// +// MIT License: +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +import { copyTextToClipboard } from './copyToClipboard'; + +const mockWrite = jest.fn(args => true); + +jest.mock('electron', () => ({ + clipboard: { + writeText: args => { + mockWrite(args); + }, + }, +})); + +describe('Copy To Clipboard', () => { + beforeEach(() => { + mockWrite.mockReset(); + }); + + it('should copy text to clipboard', async () => { + let expected = 'Hello'; + copyTextToClipboard(expected); + expect(mockWrite).toHaveBeenCalledWith(expected); + expected = 'Hello Check Again'; + copyTextToClipboard(expected); + expect(mockWrite).toHaveBeenCalledWith(expected); + }); +}); diff --git a/packages/app/client/src/utils/copyToClipboard.ts b/packages/app/client/src/utils/copyToClipboard.ts new file mode 100644 index 000000000..4da8795bc --- /dev/null +++ b/packages/app/client/src/utils/copyToClipboard.ts @@ -0,0 +1,41 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. +// +// Microsoft Bot Framework: http://botframework.com +// +// Bot Framework Emulator Github: +// https://github.com/Microsoft/BotFramwork-Emulator +// +// Copyright (c) Microsoft Corporation +// All rights reserved. +// +// MIT License: +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +import { clipboard } from 'electron'; + +export const copyTextToClipboard = (textValue: string): boolean => { + try { + clipboard.writeText(textValue, 'selection'); + return true; + } catch (ex) { + return false; + } +}; diff --git a/packages/app/client/src/utils/index.ts b/packages/app/client/src/utils/index.ts index 77eb555cd..a559b62f9 100644 --- a/packages/app/client/src/utils/index.ts +++ b/packages/app/client/src/utils/index.ts @@ -37,3 +37,4 @@ export * from './getGlobal'; export * from './getSettingsDelta'; export * from './generateBotSecret'; export * from './chatUtils'; +export * from './copyToClipboard'; From e904676c5c650fab02b4ffc1557c0aad76bd69f3 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Wed, 11 Mar 2020 16:48:47 -0700 Subject: [PATCH 2/2] Changelog updated Signed-off-by: Srinaath Ravichandran --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 458dca07a..5199592ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [client] Upload and download attachments bubble texts and background in webchat were hidden. The adjustments have been made to override FileContent class in PR [2088](https://github.com/microsoft/BotFramework-Emulator/pull/2088) - [client] Fixed an issue that was causing adaptive card focus to be blurred when clicking on an activity in PR [2090](https://github.com/microsoft/BotFramework-Emulator/pull/2090) - [client] Fixed an accessibility issue with the recent bots list remove button in PR [2091](https://github.com/microsoft/BotFramework-Emulator/pull/2091) - +- [client] Copy secret key button now copies the secret key to the clipboar when creating a new bot file in PR [2098](https://github.com/microsoft/BotFramework-Emulator/pull/2098) ## Removed - [client/main] Removed legacy payments code in PR [2058](https://github.com/microsoft/BotFramework-Emulator/pull/2058)