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

OCV first pass #10355

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open

OCV first pass #10355

wants to merge 27 commits into from

Conversation

srietkerk
Copy link
Contributor

This is the work to plug in the One Customer Voice iframe into our products. Right now, it's only getting triggered from our settings menus, but we can pop this modal up in any context.

Things of note in this PR

  • I likely should have split this into a separate PR, but I added a flag to the CLI to use https rather than always using http. This was needed because the OCV iframe only shows up for domains in an allow list, and the local development options they have for that allow list use https.
  • I added the giveFeedback option to the appTheme object as a starting point for only showing the feedback menu item for our targets.
  • FeedbackListener.ts is where the logic to get OCV to work lives. There is a lot of generic code in there and console logs that I figure we'll want to update to something more clean/helpful, but I kept it in for now for simplicity. A note about the event listener: the ones that I kept in are the ones I figured would be useful for us. There were some others, but I removed them because for our use case, they wouldn't really apply. If you would like to see the other events, I would be happy to showcase them.

To Dos

  • Programmatically changing the theme of the feedback for high contrast and so we can have different colors based on the target we're serving from
  • Use the "kind" flag that I've added to the feedback object to change the feedback config. I'm planning on following a similar pattern that the share modal uses with ShareInfo.
  • Get rating feedback to show upon finishing tutorials

Testing
Unfortunately, I cannot make an upload target that will be useful for these changes because of the allow list that I talked about before. I've pinged the OCV teams a couple of times to get the makecode domain in their allow list but I'm not sure of the progress. If I made an upload target, you would be able to see the "Give Feedback" option in the setting menu, but clicking on it will give you a modal with a broken iframe. If you want to actually try out the forms, you can test locally with https. I'm going to write up a doc on how to test OCV locally.

In the meantime, here's how it looks:
image

image

image

@srietkerk srietkerk requested a review from a team January 28, 2025 00:01
Copy link
Member

@riknoll riknoll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to have typings for these configs! they don't have to be exhaustive, but should include the fields you're referencing. we can expand them later as we add more code

react-common/components/controls/Feedback/Feedback.tsx Outdated Show resolved Hide resolved
* @param {any} [callbacks]: an object of functions that can be called when certain events happen in the feedback modal.
* Needs to be passed in because the callbacks will depend on what the parent wants to react to.
*/
export const initFeedbackEventListener = (feedbackConfig: any, frameId: string, callbacks?: any) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't use any. same for the variables declared above.

react-common/styles/controls/Feedback.less Outdated Show resolved Hide resolved
@@ -349,7 +355,7 @@ export class SettingsMenu extends data.Component<SettingsMenuProps, SettingsMenu
{
// we always need a way to clear local storage, regardless if signed in or not
}
{targetTheme.feedbackUrl ? <a className="ui item" href={targetTheme.feedbackUrl} role="menuitem" title={lf("Give Feedback")} target="_blank" rel="noopener noreferrer" >{lf("Give Feedback")}</a> : undefined}
{targetTheme.giveFeedback ? <sui.Item role="menuitem" text={lf("🙂 Give Feedback")} onClick={this.showFeedbackDialog} /> : undefined}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this icon shouldn't be included in the lf string, otherwise a translator might move it so it's not left aligned like the rest of the menu items. same for the home menu item below

@abchatra
Copy link
Collaborator

Nice work

@@ -0,0 +1,57 @@
export const appId = 50315;
export const feedbackFrameUrl = 'https://admin-ignite.microsoft.com';
Copy link
Contributor

@thsparks thsparks Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are feedbackFrameUrl and appId things we should store in targetconfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was definitely something I was considering, but these are going to be the same for each of our targets, so it feels redundant to put these in the target config of each target.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that's true. Ideally, I think we'd want to put this somewhere that wouldn't require a release to change (i.e. what happened with our CDN) but I'm not sure if we have a good option for that without going through our backend.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this url should go in pxtarget.json, even if it is the same for each target. This is what we do for privacyUrl, termsOfUseUrl, etc.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat related question: is the OCV/feedback feature only enabled for 1st party targets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should only be showing feedback in our self-hosted targets. There is more work to really verify this, which will be my next priority, but for now, it's just something that gets set in the apptheme as something to include in the target.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to move these hard-coded config values to pxtarget.json?

@@ -349,7 +355,7 @@ export class SettingsMenu extends data.Component<SettingsMenuProps, SettingsMenu
{
// we always need a way to clear local storage, regardless if signed in or not
}
{targetTheme.feedbackUrl ? <a className="ui item" href={targetTheme.feedbackUrl} role="menuitem" title={lf("Give Feedback")} target="_blank" rel="noopener noreferrer" >{lf("Give Feedback")}</a> : undefined}
{targetTheme.giveFeedback ? <sui.Item role="menuitem" text={lf("🙂 Give Feedback")} onClick={this.showFeedbackDialog} /> : undefined}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, you mentioned in stand-up that the smiley face icon is jarring. I'm guessing that's why it's in the string here instead of the icon property on the Item. Per Richard's comment, we probably want to use the icon property. Did you consider using a speech bubble icon or bullhorn icon instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, I hadn't considered that! I was trying to align as close as possible to Microsoft's icon patterns, but I like the idea of the comment bubble. I'll see how that looks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, here's the different options, let me know what you think.

With emoji
image

With comment bubble
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, personally I would vote for the comment icon (bonus points if there's a filled-in version to match the other icons). I feel like the color in the emoji contrasts strangely with what's already there.

@@ -524,6 +524,7 @@ declare namespace pxt {
timeMachineDiffInterval?: number; // An interval in milliseconds at which to take diffs to store in project history. Defaults to 5 minutes
timeMachineSnapshotInterval?: number; // An interval in milliseconds at which to take full project snapshots in project history. Defaults to 15 minutes
adjustBlockContrast?: boolean; // If set to true, all block colors will automatically be adjusted to have a contrast ratio of 4.5 with text
giveFeedback?: boolean; // Show the give feedback button in the settings menu
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: naming here could be clearer/more self-documenting. Some alternatives that come to mind: showFeedbackButton, feedbackButtonEnabled.

@@ -805,6 +805,7 @@ declare namespace pxt.editor {
extensionsVisible?: boolean;
isMultiplayerGame?: boolean; // Arcade: Does the current project contain multiplayer blocks?
onboarding?: pxt.tour.BubbleStep[];
feedback?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this field mean? Can it be better named? Or add a comment after it?

@@ -0,0 +1,57 @@
export const appId = 50315;
export const feedbackFrameUrl = 'https://admin-ignite.microsoft.com';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to move these hard-coded config values to pxtarget.json?

baseTheme: currentTheme,
},
}
const iFrameElement = document.getElementById(FEEDBACK_FRAME_ID) as HTMLIFrameElement
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code duplication here. Move these two lines to a helper function. In that function, check for missing iFrameElement, as document.getElementById can return undefined.

// TODO
// haven't implemented yet with events, but this will be needed in order to update to high contrast
// general changes need to be made as well use the correct theme. the windows ones were just the defaults.
const sendUpdateTheme = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to update themeOptions somewhere in this method, to keep it in sync?

break
case 'InAppFeedbackDismissWithResult': //Invoked when feedback is dismissed - the big important one for us to be able to close the feedback modal
pxt.debug('InAppFeedbackDismissWithResult: ', payload.EventArgs);
if (feedbackCallbacks.onDismiss) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (feedbackCallbacks.onDismiss) {
if (feedbackCallbacks?.onDismiss) {

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even better: feedbackCallbacks?.onDismiss?.()

event: 'InAppFeedbackInitOptions',
data: initfeedbackOptions,
}
response = JSON.parse(JSON.stringify(response))
Copy link
Collaborator

@eanders-ms eanders-ms Feb 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a strong reason for deep copy here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants