Skip to content

Commit

Permalink
Address review points
Browse files Browse the repository at this point in the history
  • Loading branch information
OEvgeny committed Jan 14, 2025
1 parent 52816a9 commit 05e408d
Show file tree
Hide file tree
Showing 21 changed files with 344 additions and 30 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- Added support for math blocks using `$$` delimiter alongside existing `\[...\]` and `\(...\)` notations, in PR [#5381](https://github.com/microsoft/BotFramework-WebChat/pull/5381), by [@OEvgeny](https://github.com/OEvgeny)
- Added support for speech recognition initial silence timeout when using Azure Speech, in PR [#5400](https://github.com/microsoft/BotFramework/WebChat/pull/5400), by [@compulim](https://github.com/compulim)
- Introduced syntax highlighting for markdown code blocks, in PR [#5389](https://github.com/microsoft/BotFramework-WebChat/pull/5389), by [@OEvgeny](https://github.com/OEvgeny)
- Added `feedbackActionsPlacement` style option to control feedback button placement, in PR [#5407](https://github.com/microsoft/BotFramework-WebChat/pull/5407), by [@OEvgeny](https://github.com/OEvgeny)
- (Experimental) Added `feedbackActionsPlacement` style option to control feedback button placement, in PR [#5407](https://github.com/microsoft/BotFramework-WebChat/pull/5407), by [@OEvgeny](https://github.com/OEvgeny)
- New style option supports two values: `'activity-actions'` and `'activity-status'` (default)
- When set to `'activity-actions'`, feedback buttons are displayed in the activity actions toolbar
- When set to `'activity-status'`, feedback buttons appear in the activity status area (default behavior)
Expand Down
143 changes: 143 additions & 0 deletions __tests__/html2/activity/feedback.activity.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
</head>
<body>
<main id="webchat"></main>
<script type="text/babel" data-presets="env,stage-3,react">
const {
React: { useMemo },
WebChat: {
hooks: { useDirection }
}
} = window;

run(async function () {
WebChat.renderWebChat(
{
directLine: await testHelpers.createDirectLineWithTranscript([
{
from:{
role: "bot"
},
id: "a-00000",
timestamp: 0,
type: "message",
text: "This is compleded feedback action example.",
entities: [
{
'@context': 'https://schema.org',
'@id': '',
'@type': 'Message',
type: 'https://schema.org/Message',
keywords: ['AIGeneratedContent', 'AllowCopy'],
potentialAction: [
{
"@type": "LikeAction",
actionStatus: "CompletedActionStatus",
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=like"
}
},
{
"@type": "DislikeAction",
actionStatus: "PotentialActionStatus",
result: {
"@type": "Review",
reviewBody: "I don't like it.",
"reviewBody-input": {
"@type": "PropertyValueSpecification",
valueMinLength: 3,
valueName: "reason"
}
},
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=dislike{&reason}"
}
}
]
}
]
},
{
from:{
role: "bot"
},
id: "a-00002",
timestamp: 0,
type: "message",
text: "Hi! I'm *Cody*, the devbot. How can I help?",
entities: [
{
'@context': 'https://schema.org',
'@id': '',
'@type': 'Message',
type: 'https://schema.org/Message',
keywords: [],
potentialAction: [
{
"@type": "LikeAction",
actionStatus: "PotentialActionStatus",
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=like"
}
},
{
"@type": "DislikeAction",
actionStatus: "PotentialActionStatus",
result: {
"@type": "Review",
reviewBody: "I don't like it.",
"reviewBody-input": {
"@type": "PropertyValueSpecification",
valueMinLength: 3,
valueName: "reason"
}
},
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=dislike{&reason}"
}
}
]
}
]
}
]),
styleOptions: {
feedbackActionsPlacement: 'activity-actions'
},
store: testHelpers.createStore(),
},
document.getElementById('webchat')
);

await pageConditions.uiConnected();

await host.snapshot('local');

pageElements.sendBoxTextBox().focus();
await host.sendShiftTab(3);

await host.sendKeys('ENTER');
await host.snapshot('local');
await host.sendKeys('ENTER');
await host.snapshot('local');
await host.sendKeys('TAB');
await host.snapshot('local');
await host.sendKeys('ENTER');
await host.snapshot('local');
});
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
158 changes: 158 additions & 0 deletions __tests__/html2/activity/feedback.status.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
</head>
<body>
<main id="webchat"></main>
<script type="text/babel" data-presets="env,stage-3,react">
const {
React: { useMemo },
WebChat: {
hooks: { useDirection }
}
} = window;

run(async function () {
WebChat.renderWebChat(
{
directLine: await testHelpers.createDirectLineWithTranscript([
{
from:{
role: "bot"
},
id: "a-00000",
timestamp: 0,
type: "message",
text: "This is compleded feedback action example.",
entities: [
{
'@context': 'https://schema.org',
'@id': '',
'@type': 'Message',
type: 'https://schema.org/Message',
keywords: ['AIGeneratedContent', 'AllowCopy'],
potentialAction: [
{
"@type": "LikeAction",
actionStatus: "CompletedActionStatus",
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=like"
}
},
{
"@type": "DislikeAction",
actionStatus: "PotentialActionStatus",
result: {
"@type": "Review",
reviewBody: "I don't like it.",
"reviewBody-input": {
"@type": "PropertyValueSpecification",
valueMinLength: 3,
valueName: "reason"
}
},
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=dislike{&reason}"
}
}
]
}
]
},
{
from: {
role: 'user'
},
id: "a-00001",
timestamp: 0,
type: "message",
text: "Test",
},
{
from:{
role: "bot"
},
id: "a-00002",
timestamp: 0,
type: "message",
text: "Hi! I'm *Cody*, the devbot. How can I help?",
entities: [
{
'@context': 'https://schema.org',
'@id': '',
'@type': 'Message',
type: 'https://schema.org/Message',
keywords: [],
potentialAction: [
{
"@type": "LikeAction",
actionStatus: "PotentialActionStatus",
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=like"
}
},
{
"@type": "DislikeAction",
actionStatus: "PotentialActionStatus",
result: {
"@type": "Review",
reviewBody: "I don't like it.",
"reviewBody-input": {
"@type": "PropertyValueSpecification",
valueMinLength: 3,
valueName: "reason"
}
},
target: {
"@type": "EntryPoint",
urlTemplate: "ms-directline://postback?interaction=dislike{&reason}"
}
}
]
}
]
}
]),
store: testHelpers.createStore(),
},
document.getElementById('webchat')
);

await pageConditions.uiConnected();

await host.snapshot('local');

const [,, activityStatus] = pageElements.activityStatuses();
const buttons = activityStatus.querySelectorAll('button');

pageElements.sendBoxTextBox().focus();

await host.sendShiftTab(3);
await host.sendKeys('ENTER');
await expect(document.activeElement).toBe(buttons[0]);
await host.snapshot('local');

await host.sendTab();
await expect(document.activeElement).toBe(buttons[1]);
await host.snapshot('local');

await host.sendTab();
await expect(document.activeElement).toBe(buttons[0]);
await host.snapshot('local');

await host.sendKeys('ENTER');
await host.snapshot('local');
});
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion packages/api/src/StyleOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -930,13 +930,15 @@ type StyleOptions = {
codeBlockTheme?: 'github-light-default' | 'github-dark-default';

/**
* Feedback buttons placement
* (EXPERIMENTAL) Feedback buttons placement
*
* - `'activity-actions'` - place feedback buttons inside activity actions
* - `'activity-status'` - place feedback buttons inside activity status
*
* @default 'activity-status'
*
* @deprecated This is an experimental style options and should not be used without understanding its risk.
*
* New in 4.19.0.
*/
feedbackActionsPlacement?: 'activity-actions' | 'activity-status';
Expand Down
10 changes: 5 additions & 5 deletions packages/component/src/Activity/ActivityFeedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@ const { useStyleOptions } = hooks;

type ActivityFeedbackProps = Readonly<{
activity: WebChatActivity;
placement: 'activity-status' | 'activity-actions';
}>;

function ActivityFeedback({ activity, placement }: ActivityFeedbackProps) {
function ActivityFeedback({ activity }: ActivityFeedbackProps) {
const [{ feedbackActionsPlacement }] = useStyleOptions();

const graph = useMemo(() => dereferenceBlankNodes(activity.entities || []), [activity.entities]);

const messageThing = useMemo(() => getOrgSchemaMessage(graph), [graph]);

const feedbackActions = useMemo<ReadonlySet<OrgSchemaAction> | undefined>(() => {
const feedbackActions = useMemo<ReadonlySet<OrgSchemaAction>>(() => {
try {
const reactActions = (messageThing?.potentialAction || []).filter(
({ '@type': type }) => type === 'LikeAction' || type === 'DislikeAction'
Expand All @@ -38,16 +37,17 @@ function ActivityFeedback({ activity, placement }: ActivityFeedbackProps) {
} catch {
// Intentionally left blank.
}
return Object.freeze(new Set([] as OrgSchemaAction[]));
}, [graph, messageThing?.potentialAction]);

return feedbackActions?.size && placement === feedbackActionsPlacement ? (
return (
<Feedback
actions={feedbackActions}
className={cx({
'webchat__thumb-button--large': feedbackActionsPlacement === 'activity-actions'
})}
/>
) : null;
);
}

export default memo(ActivityFeedback);
2 changes: 1 addition & 1 deletion packages/component/src/Activity/private/Feedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const Feedback = memo(({ actions, className }: Props) => {

return (
<Fragment>
{Array.from(actions).map((action, index) => (
{[...actions].map((action, index) => (
<FeedbackVoteButton
action={action}
className={className}
Expand Down
Loading

0 comments on commit 05e408d

Please sign in to comment.