Add logic in DE to show NPS Survey (#1565)

* Send messages from DE to Portal to display NPS Survey

* Address comments
This commit is contained in:
sindhuba 2023-08-04 13:24:30 -07:00 committed by GitHub
parent 5f0c7bcea2
commit 92f43c28a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 2 deletions

View File

@ -1,5 +1,8 @@
import { Link } from "@fluentui/react/lib/Link"; import { Link } from "@fluentui/react/lib/Link";
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility"; import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
import { sendMessage } from "Common/MessageHandler";
import { Platform } from "ConfigContext";
import { MessageTypes } from "Contracts/ExplorerContracts";
import { IGalleryItem } from "Juno/JunoClient"; import { IGalleryItem } from "Juno/JunoClient";
import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointValidation"; import { allowedNotebookServerUrls, validateEndpoint } from "Utils/EndpointValidation";
import * as ko from "knockout"; import * as ko from "knockout";
@ -23,7 +26,7 @@ import { PhoenixClient } from "../Phoenix/PhoenixClient";
import * as ExplorerSettings from "../Shared/ExplorerSettings"; import * as ExplorerSettings from "../Shared/ExplorerSettings";
import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../UserContext"; import { isAccountNewerThanThresholdInMs, userContext } from "../UserContext";
import { getCollectionName, getUploadName } from "../Utils/APITypeUtils"; import { getCollectionName, getUploadName } from "../Utils/APITypeUtils";
import { stringToBlob } from "../Utils/BlobUtils"; import { stringToBlob } from "../Utils/BlobUtils";
import { isCapabilityEnabled } from "../Utils/CapabilityUtils"; import { isCapabilityEnabled } from "../Utils/CapabilityUtils";
@ -258,6 +261,45 @@ export default class Explorer {
// TODO: return result // TODO: return result
} }
private getRandomInt(max: number) {
return Math.floor(Math.random() * max);
}
public openNPSSurveyDialog(): void {
if (!Platform.Portal) {
return;
}
const NINETY_DAYS_IN_MS = 7776000000;
const ONE_DAY_IN_MS = 86400000;
const isAccountNewerThanNinetyDays = isAccountNewerThanThresholdInMs(
userContext.databaseAccount?.systemData?.createdAt || "",
NINETY_DAYS_IN_MS
);
// Try Cosmos DB subscription - survey shown to random 25% of users at day 1 in Data Explorer.
if (userContext.isTryCosmosDBSubscription) {
if (
isAccountNewerThanThresholdInMs(userContext.databaseAccount?.systemData?.createdAt || "", ONE_DAY_IN_MS) &&
this.getRandomInt(100) < 25
) {
sendMessage(MessageTypes.DisplayNPSSurvey);
}
} else {
// An existing account is lesser than 90 days old. For existing account show to random 10 % of users in Data Explorer.
if (isAccountNewerThanNinetyDays) {
if (this.getRandomInt(100) < 10) {
sendMessage(MessageTypes.DisplayNPSSurvey);
}
} else {
// An existing account is greater than 90 days. For existing account show to random 25 % of users in Data Explorer.
if (this.getRandomInt(100) < 25) {
sendMessage(MessageTypes.DisplayNPSSurvey);
}
}
}
}
public async refreshDatabaseForResourceToken(): Promise<void> { public async refreshDatabaseForResourceToken(): Promise<void> {
const databaseId = userContext.parsedResourceToken?.databaseId; const databaseId = userContext.parsedResourceToken?.databaseId;
const collectionId = userContext.parsedResourceToken?.collectionId; const collectionId = userContext.parsedResourceToken?.collectionId;

View File

@ -1425,6 +1425,10 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
this.setState({ isExecuting: false }); this.setState({ isExecuting: false });
TelemetryProcessor.traceSuccess(Action.CreateCollection, telemetryData, startKey); TelemetryProcessor.traceSuccess(Action.CreateCollection, telemetryData, startKey);
useSidePanel.getState().closeSidePanel(); useSidePanel.getState().closeSidePanel();
// open NPS Survey Dialog once the collection is created
if (userContext.features.enableNPSSurvey) {
this.props.explorer.openNPSSurveyDialog();
}
} catch (error) { } catch (error) {
const errorMessage: string = getErrorMessage(error); const errorMessage: string = getErrorMessage(error);
this.setState({ isExecuting: false, errorMessage, showErrorDetails: true }); this.setState({ isExecuting: false, errorMessage, showErrorDetails: true });

View File

@ -36,6 +36,7 @@ export type Features = {
readonly enableLegacyMongoShellV2Debug: boolean; readonly enableLegacyMongoShellV2Debug: boolean;
readonly loadLegacyMongoShellFromBE: boolean; readonly loadLegacyMongoShellFromBE: boolean;
readonly enableCopilot: boolean; readonly enableCopilot: boolean;
readonly enableNPSSurvey: boolean;
// can be set via both flight and feature flag // can be set via both flight and feature flag
autoscaleDefault: boolean; autoscaleDefault: boolean;
@ -104,6 +105,7 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
enableLegacyMongoShellV2Debug: "true" === get("enablelegacymongoshellv2debug"), enableLegacyMongoShellV2Debug: "true" === get("enablelegacymongoshellv2debug"),
loadLegacyMongoShellFromBE: "true" === get("loadlegacymongoshellfrombe"), loadLegacyMongoShellFromBE: "true" === get("loadlegacymongoshellfrombe"),
enableCopilot: "true" === get("enablecopilot"), enableCopilot: "true" === get("enablecopilot"),
enableNPSSurvey: "true" === get("enableNPSSurvey"),
}; };
} }

View File

@ -91,7 +91,7 @@ const userContext: UserContext = {
collectionCreationDefaults: CollectionCreationDefaults, collectionCreationDefaults: CollectionCreationDefaults,
}; };
function isAccountNewerThanThresholdInMs(createdAt: string, threshold: number) { export function isAccountNewerThanThresholdInMs(createdAt: string, threshold: number) {
let createdAtMs: number = Date.parse(createdAt); let createdAtMs: number = Date.parse(createdAt);
if (isNaN(createdAtMs)) { if (isNaN(createdAtMs)) {
createdAtMs = 0; createdAtMs = 0;