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

Merged
merged 34 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d31eca8
plumbing for showing the feedback iframe
srietkerk Dec 12, 2024
f55fca2
add https flag to the cli to use https when debugging ocv iframe
srietkerk Dec 19, 2024
c705f96
Merge branch 'master' of https://github.com/microsoft/pxt into srietk…
srietkerk Dec 20, 2024
87236db
more config, removed functions, changed height and width of iframe
srietkerk Dec 20, 2024
0593552
using different modal for the feedback
srietkerk Jan 14, 2025
5259143
added feedback menu item to editor menu
srietkerk Jan 14, 2025
9354dc2
got rid of iframe border
srietkerk Jan 14, 2025
a764d25
some small changes and styling
srietkerk Jan 25, 2025
6446b2a
added comments
srietkerk Jan 27, 2025
2120588
move app id to configs
srietkerk Jan 27, 2025
4da2fdc
fix onclose reference
srietkerk Jan 27, 2025
05d4be7
moved frame url to configs
srietkerk Jan 27, 2025
816c662
remove tutorial completion feedback for now
srietkerk Jan 27, 2025
8336f42
use emoji instead of sui icon
srietkerk Jan 27, 2025
bab52a2
merged master
srietkerk Jan 27, 2025
f905236
update iframeelement variable in event listener
srietkerk Jan 28, 2025
4a4eb79
add space to less file
srietkerk Jan 28, 2025
6c86476
another iframe element var change
srietkerk Jan 28, 2025
cd43ef9
moved height, width to less file, fixed some styling
srietkerk Jan 28, 2025
be206b5
remove redundant jsdoc types
srietkerk Jan 28, 2025
2bb7a05
use pxt log functions, fix spacing in the event listener
srietkerk Jan 28, 2025
b209592
move emoji out of lf
srietkerk Jan 28, 2025
9438c18
use lf for the displayed strings for the rating
srietkerk Jan 28, 2025
158939c
types added
srietkerk Jan 30, 2025
c714b42
move types to localtypings and wrap them in a namespace
srietkerk Jan 30, 2025
728ebd8
change to using the comment bubble icon
srietkerk Jan 30, 2025
69ec94d
added types
srietkerk Jan 31, 2025
9dc5367
actually using feedback kind
srietkerk Feb 4, 2025
3e8c6ba
rename feedback app theme field
srietkerk Feb 4, 2025
83b45f8
move iframe init and posting code to helper function
srietkerk Feb 4, 2025
980020a
use optional chaining for ondismiss call
srietkerk Feb 4, 2025
3b6a3ff
move current theme into send update theme function, update theme options
srietkerk Feb 4, 2025
943c493
move questions for rating config to a function
srietkerk Feb 4, 2025
36c823c
move appid, frame url to apptheme
srietkerk Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2805,7 +2805,6 @@ function renderDocs(builtPackaged: string, localDir: string) {
}
pxt.log(`All docs written.`);
}

export function serveAsync(parsed: commandParser.ParsedCommand) {
// always use a cloud build
// in most cases, the user machine is not properly setup to
Expand Down Expand Up @@ -2864,6 +2863,7 @@ export function serveAsync(parsed: commandParser.ParsedCommand) {
serial: !parsed.flags["noSerial"] && !globalConfig.noSerial,
noauth: parsed.flags["noauth"] as boolean || false,
backport: parsed.flags["backport"] as number || 0,
https: parsed.flags["https"] as boolean || false,
}))
}

Expand Down Expand Up @@ -7129,7 +7129,8 @@ ${pxt.crowdin.KEY_VARIABLE} - crowdin key
description: "port where the locally running backend is listening.",
argument: "backport",
type: "number",
}
},
https: { description: "use https protocol instead of http"}
}
}, serveAsync);

Expand Down
19 changes: 14 additions & 5 deletions cli/server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import * as http from 'http';
import * as https from 'https';
import * as url from 'url';
import * as querystring from 'querystring';
import * as nodeutil from './nodeutil';
Expand All @@ -13,6 +14,7 @@ import { promisify } from "util";

import U = pxt.Util;
import Cloud = pxt.Cloud;
import { SecureContextOptions } from 'tls';

const userProjectsDirName = "projects";

Expand Down Expand Up @@ -804,6 +806,7 @@ export interface ServeOptions {
serial?: boolean;
noauth?: boolean;
backport?: number;
https?: boolean;
}

// can use http://localhost:3232/streams/nnngzlzxslfu for testing
Expand Down Expand Up @@ -949,8 +952,7 @@ export function serveAsync(options: ServeOptions) {
const wsServerPromise = initSocketServer(serveOptions.wsPort, serveOptions.hostname);
if (serveOptions.serial)
initSerialMonitor();

const server = http.createServer(async (req, res) => {
const reqListener: http.RequestListener = async (req, res) => {
const error = (code: number, msg: string = null) => {
res.writeHead(code, { "Content-Type": "text/plain" })
res.end(msg || "Error " + code)
Expand Down Expand Up @@ -1351,7 +1353,10 @@ export function serveAsync(options: ServeOptions) {
});
}
return
});
};
const canUseHttps = serveOptions.https && process.env["HTTPS_KEY"] && process.env["HTTPS_CERT"];
const httpsServerOptions: SecureContextOptions = {cert: process.env["HTTPS_CERT"], key: process.env["HTTPS_KEY"]};
const server = canUseHttps ? https.createServer(httpsServerOptions, reqListener) : http.createServer(reqListener);

// if user has a server.js file, require it
const serverjs = path.resolve(path.join(root, 'built', 'server.js'))
Expand All @@ -1362,12 +1367,16 @@ export function serveAsync(options: ServeOptions) {

const serverPromise = new Promise<void>((resolve, reject) => {
server.on("error", reject);
server.listen(serveOptions.port, serveOptions.hostname, () => resolve());
server.listen(serveOptions.port, serveOptions.hostname, () => {
console.log(`Server listening on port ${serveOptions.port}`);
return resolve()
});
});

return Promise.all([wsServerPromise, serverPromise])
.then(() => {
const start = `http://${serveOptions.hostname}:${serveOptions.port}/#local_token=${options.localToken}&wsport=${serveOptions.wsPort}`;
const protocol = canUseHttps ? "https" : "http";
const start = `${protocol}://${serveOptions.hostname}:${serveOptions.port}/#local_token=${options.localToken}&wsport=${serveOptions.wsPort}`;
console.log(`---------------------------------------------`);
console.log(``);
console.log(`To launch the editor, open this URL:`);
Expand Down
274 changes: 274 additions & 0 deletions localtypings/ocv.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
declare namespace ocv {

type FeedbackKind = "generic" | "rating";

const enum FeedbackAgeGroup {
Undefined = "Undefined",
MinorWithoutParentalConsent = "MinorWithoutParentalConsent",
MinorWithParentalConsent = "MinorWithParentalConsent",
NotAdult = "NotAdult",
Adult = "Adult",
MinorNoParentalConsentRequired = "MinorNoParentalConsentRequired"
}

interface IFeedbackCallbackFunctions {
attachDiagnosticsLogs?: (diagnosticsUploadId: string, diagnosticsEndpoint: string) => void;
onDismiss?: (isFeedbackSent?: boolean) => void;
onSuccess?: (clientFeedbackId: string) => void;
onError?: (errorMessage?: string) => void;
supportCallback?: () => void;
initializationComplete?: (initializationCompleteResult: InitializationResult) => void;
setSubmitButtonState?: (isEnabled: boolean) => void;
}

const enum FeedbackAuthenticationType {
MSA = "MSA",
AAD = "AAD",
Unauthenticated = "Unauthenticated"
}

const enum FeedbackType {
Smile = "Smile",
Frown = "Frown",
Idea = "Idea",
Unclassified = "Unclassified",
Survey = "Survey"
}

const enum FeedbackPolicyValue {
Enabled = "Enabled",
Disabled = "Disabled",
NotConfigured = "Not Configured",
NotApplicable = "Not Applicable"
}

interface IThemeOptions {
isFluentV9?: boolean;
/**
* v9Theme must be Theme object from @fluentui/react-components@9.*
*/
v9Theme?: any;
/**
* brandVariants must be BrandVariants object from @fluentui/react-components@9.*
*/
brandVariants?: any;
baseTheme?: any;
colorScheme?: any;
}

interface IFeedbackInitOptions {
ageGroup?: FeedbackAgeGroup;
appId?: number;
authenticationType?: FeedbackAuthenticationType;
callbackFunctions?: IFeedbackCallbackFunctions;
clientName?: string;
feedbackConfig?: IFeedbackConfig;
isProduction?: boolean;
telemetry?: IFeedbackTelemetry;
themeOptions?: IThemeOptions;
}

const enum FeedbackUiType {
SidePane = "SidePane",// Default: Used for side pane/detail view
Modal = "Modal",// Used for modal view
CallOut = "CallOut",// Used for inscreen pop up dialogue
IFrameWithinSidePane = "IFrameWithinSidePane",// Same as side pane but used inside an iframe
IFrameWithinModal = "IFrameWithinModal",// Same as modal but used inside an iframe
IFrameWithinCallOut = "IFrameWithinCallOut",// Same as callout but used inside an iframe
NoSurface = "NoSurface",// Used when the surface is provided by the host app
NoSurfaceWithoutTitle = "NoSurfaceWithoutTitle"
}

const enum FeedbackHostPlatformType {
Windows = "Windows",
IOS = "iOS",
Android = "Android",
WacTaskPane = "WacTaskPane",
MacOS = "MacOS",
Web = "Web",
IFrame = "IFrame"
}

const enum FeedbackHostEventName {
SubmitClicked = "InAppFeedback_HostEvent_SubmitClicked",
BackClicked = "InAppFeedback_HostEvent_BackClicked"
}

const enum InitializationStatus {
Success = "Success",
Error = "Error",
Warning = "Warning"
}

const enum InAppFeedbackQuestionUiType {
DropDown = "DropDown",
MultiSelect = "MultiSelect",
Rating = "Rating",
SingleSelect = "SingleSelect",
SingleSelectHorizontal = "SingleSelectHorizontal"
}

const enum InAppFeedbackScenarioType {
FeatureArea = "FeatureArea",
ResponsibleAI = "ResponsibleAI",
Experience = "Experience",
ProductSatisfaction = "ProductSatisfaction",
CrashImpact = "CrashImpact",// CrashImpact is of type Survey
Custom = "Custom",
AIThumbsDown = "AIThumbsDown",
AIThumbsUp = "AIThumbsUp",
AIError = "AIError",
PromptSuggestion = "PromptSuggestion"
}

const enum InAppFeedbackQuestionUiBehaviour {
QuestionNotRequired = "QuestionNotRequired",
CommentNotRequired = "CommentNotRequired",
CommentRequiredWithLastOption = "CommentRequiredWithLastOption"
}

const enum FeedbackAttachmentOrigin {
Application = "Application",
User = "User"
}

const enum FeedbackEntryPoint {
Header = "Header",
Footer = "Footer",
Backstage = "Backstage",
HelpMenu = "Help Menu",
Canvas = "Canvas",
Chat = "Chat"
}

interface InitializationResult {
status: InitializationStatus;
/**
* in UTC timestamp milliseconds
*/
timestamp?: number;
/**
* Duration to load package and validations (centro performance) in milliseconds
*/
loadTime?: number;
errorMessages?: string[];
warningMessages?: string[];
}

interface IFeedbackConfig {
appData?: string;
canDisplayFeedbackCalled?: boolean;
feedbackUiType?: FeedbackUiType;
hideFooterActionButtons?: boolean;
initialFeedbackType?: FeedbackType;
hostPlatform?: FeedbackHostPlatformType;
/**
* Invokes onDismiss callback on Esc button press
* Useful for host apps like Win32 Pane or iFrames
*/
invokeOnDismissOnEsc?: boolean;
isDisplayed?: boolean;
isEmailCollectionEnabled?: boolean;
isFeedbackForumEnabled?: boolean;
isFileUploadEnabled?: boolean;
isMyFeedbackEnabled?: boolean;
isScreenRecordingEnabled?: boolean;
isScreenshotEnabled?: boolean;
isShareContextDataEnabled?: boolean;
isThankYouPageDisabled?: boolean;
isSupportEnabled?: boolean;
maxHeight?: number;
maxWidth?: number;
minHeight?: number;
minWidth?: number;
myFeedbackUrl?: string;
privacyUrl?: string;
retentionDurationDays?: number;
scenarioConfig?: InAppFeedbackScenarioConfig;
supportUrl?: string;
/**
* Enable submit offline feedback
* This will only work if submitOffline callback is provided
*/
isOfflineSubmitEnabled?: boolean;
/**
* For platforms that host other products or sites, this parameter is used to disambiguate the recipient of the data.
* Its effect is to alter the form title for internal users only, replacing 'Microsoft' with the string provided.
* The string length is capped at 30 characters.
* Please keep the name as short as possible to optimize the user experience, preferably including only the product name.
* */
msInternalTitleTarget?: string;
}

type IFeedbackTelemetry = {
accountCountryCode?: string;
affectedProcessSessionId?: string;
appVersion?: string;
audience?: string;
audienceGroup?: string;
browser?: string;
browserVersion?: string;
channel?: string;
clientCountryCode?: string;
cpuModel?: string;
dataCenter?: string;
deviceId?: string;
deviceType?: string;
entryPoint?: FeedbackEntryPoint;
errorClassification?: string;
errorCode?: string;
errorName?: string;
featureArea?: string;
featureName?: string;
feedbackOrigin?: string;
flights?: string;
flightSource?: string;
fundamentalArea?: string;
installationType?: string;
isLogIncluded?: boolean;
isUserSubscriber?: boolean;
officeArchitecture?: string;
officeBuild?: string;
officeEditingLang?: number;
officeUILang?: number;
osBitness?: number;
osBuild?: string;
osUserLang?: number;
platform?: string;
processorArchitecture?: string;
processorPhysicalCores?: number;
processSessionId?: string;
ringId?: number;
sku?: string;
sourceContext?: string;
sqmMachineId?: string;
subFeatureName?: string;
sourcePageName?: string;
sourcePageURI?: string;
systemManufacturer?: string;
systemProductName?: string;
uiHost?: string;
};

interface InAppFeedbackScenarioConfig {
isScenarioEnabled?: boolean;
scenarioType?: InAppFeedbackScenarioType;
questionDetails?: InAppFeedbackQuestion;
}

interface InAppFeedbackQuestion {
questionUiType?: InAppFeedbackQuestionUiType;
questionInstruction?: InAppFeedbackCompositeString;
questionOptions?: InAppFeedbackCompositeString[];
questionUiBehaviour?: InAppFeedbackQuestionUiBehaviour[];
}

interface InAppFeedbackCompositeString {
displayedString: string;
displayedStringInEnglish: string;
}
}




3 changes: 3 additions & 0 deletions localtypings/pxtarget.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,9 @@ 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
feedbackEnabled?: boolean; // allow feedback to be shown on a target
ocvAppId?: number; // the app id needed to attach to the OCV service
ocvFrameUrl?: string; // the base url for the OCV service
}

interface DownloadDialogTheme {
Expand Down
Loading