-
Notifications
You must be signed in to change notification settings - Fork 593
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
base: master
Are you sure you want to change the base?
OCV first pass #10355
Conversation
…erk/ocv-iframe
There was a problem hiding this 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
* @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) => { |
There was a problem hiding this comment.
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/components/controls/Feedback/FeedbackEventListener.ts
Outdated
Show resolved
Hide resolved
react-common/components/controls/Feedback/FeedbackEventListener.ts
Outdated
Show resolved
Hide resolved
react-common/components/controls/Feedback/FeedbackEventListener.ts
Outdated
Show resolved
Hide resolved
react-common/components/controls/Feedback/FeedbackEventListener.ts
Outdated
Show resolved
Hide resolved
react-common/components/controls/Feedback/FeedbackEventListener.ts
Outdated
Show resolved
Hide resolved
webapp/src/container.tsx
Outdated
@@ -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} |
There was a problem hiding this comment.
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
Nice work |
Co-authored-by: Richard Knoll <[email protected]>
Co-authored-by: Richard Knoll <[email protected]>
Co-authored-by: Richard Knoll <[email protected]>
@@ -0,0 +1,57 @@ | |||
export const appId = 50315; | |||
export const feedbackFrameUrl = 'https://admin-ignite.microsoft.com'; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
webapp/src/container.tsx
Outdated
@@ -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} |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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'; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 = () => { |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (feedbackCallbacks.onDismiss) { | |
if (feedbackCallbacks?.onDismiss) { |
There was a problem hiding this comment.
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)) |
There was a problem hiding this comment.
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?
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
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
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: