Skip to content

Commit

Permalink
[POR-1973] intercom pop up on provisioning pre-flight check and v2 up…
Browse files Browse the repository at this point in the history
…date errors (#3830)
  • Loading branch information
Feroze Mohideen authored Oct 18, 2023
1 parent 4887989 commit 6539bcc
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 19 deletions.
30 changes: 18 additions & 12 deletions dashboard/src/components/AzureProvisionerSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Spacer from "./porter/Spacer";
import Step from "./porter/Step";
import Link from "./porter/Link";
import Text from "./porter/Text";
import { useIntercom } from "lib/hooks/useIntercom";

const locationOptions = [
{ value: "eastus", label: "East US" },
Expand Down Expand Up @@ -89,9 +90,11 @@ const AzureProvisionerSettings: React.FC<Props> = (props) => {
const [errorDetails, setErrorDetails] = useState<string>("");
const [isClicked, setIsClicked] = useState(false);

const markStepStarted = async (step: string, region: string) => {
const { showIntercomWithMessage } = useIntercom();

const markStepStarted = async (step: string, {region, error_message}: {region?: string; error_message?: string}) => {
try {
await api.updateOnboardingStep("<token>", { step, region, provider: "azure" }, {
await api.updateOnboardingStep("<token>", { step, region, error_message, provider: "azure" }, {
project_id: currentProject.id,
});
} catch (err) {
Expand Down Expand Up @@ -224,7 +227,7 @@ const AzureProvisionerSettings: React.FC<Props> = (props) => {
setErrorDetails("")

if (!props.clusterId) {
markStepStarted("provisioning-started", azureLocation);
markStepStarted("provisioning-started", { region: azureLocation });
}

const res = await api.createContract("<token>", data, {
Expand Down Expand Up @@ -255,19 +258,22 @@ const AzureProvisionerSettings: React.FC<Props> = (props) => {
setErrorMessage("");
setErrorDetails("")
} catch (err) {
const errMessage = err.response.data.error.replace("unknown: ", "");
showIntercomWithMessage({ message: "I am running into an issue provisioning a cluster." });
let errorMessage = DEFAULT_ERROR_MESSAGE;
let errorDetails = err.response?.data?.error?.replace("unknown: ", "") ?? "";
// hacky, need to standardize error contract with backend
setIsClicked(false);
if (errMessage.includes("resource provider")) {
setErrorMessage(AZURE_MISSING_RESOURCE_PROVIDER_MESSAGE);
setErrorDetails(errMessage)
} else if (errMessage.includes("quota")) {
setErrorMessage(AZURE_CORE_QUOTA_ERROR_MESSAGE)
setErrorDetails(errMessage)
if (errorDetails.includes("resource provider")) {
setErrorDetails(errorDetails);
errorMessage = AZURE_MISSING_RESOURCE_PROVIDER_MESSAGE;
} else if (errorDetails.includes("quota")) {
setErrorDetails(errorDetails);
errorMessage = AZURE_CORE_QUOTA_ERROR_MESSAGE;
} else {
setErrorMessage(DEFAULT_ERROR_MESSAGE);
setErrorDetails("")
setErrorDetails("");
}
setErrorMessage(errorMessage);
markStepStarted("provisioning-failed", { error_message: `Error message: ${errorMessage}; Error details: ${errorDetails}` });
} finally {
setIsReadOnly(false);
setIsClicked(false);
Expand Down
6 changes: 5 additions & 1 deletion dashboard/src/components/GCPProvisionerSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import Fieldset from "./porter/Fieldset";
import ExpandableSection from "./porter/ExpandableSection";
import PreflightChecks from "./PreflightChecks";
import VerticalSteps from "./porter/VerticalSteps";
import { useIntercom } from "lib/hooks/useIntercom";


const locationOptions = [
Expand Down Expand Up @@ -92,6 +93,8 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
const [isExpanded, setIsExpanded] = useState(false);
const [preflightError, setPreflightError] = useState<string>("")

const { showIntercomWithMessage } = useIntercom();

const markStepStarted = async (step: string, region?: string) => {
try {
await api.updateOnboardingStep("<token>", { step, provider: "gcp", region }, {
Expand Down Expand Up @@ -429,10 +432,11 @@ const GCPProvisionerSettings: React.FC<Props> = (props) => {
errors = errors + check + ", "
}
}
// If none of the checks have a message, set setPreflightFailed to false
if (hasMessage) {
showIntercomWithMessage({ message: "I am running into an issue provisioning a cluster." });
markStepStarted("provisioning-failed", errors);
}
// If none of the checks have a message, set setPreflightFailed to false
if (!hasMessage) {
setPreflightFailed(false);
setStep(2);
Expand Down
4 changes: 4 additions & 0 deletions dashboard/src/components/ProvisionerSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import Loading from "./Loading";
import PreflightChecks from "./PreflightChecks";
import Placeholder from "./Placeholder";
import VerticalSteps from "./porter/VerticalSteps";
import { useIntercom } from "lib/hooks/useIntercom";
const regionOptions = [
{ value: "us-east-1", label: "US East (N. Virginia) us-east-1" },
{ value: "us-east-2", label: "US East (Ohio) us-east-2" },
Expand Down Expand Up @@ -146,6 +147,8 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
const [preflightData, setPreflightData] = useState(null)
const [preflightFailed, setPreflightFailed] = useState<boolean>(true)
const [preflightError, setPreflightError] = useState<string>("")

const { showIntercomWithMessage } = useIntercom();

const markStepStarted = async (step: string, errMessage?: string) => {
try {
Expand Down Expand Up @@ -537,6 +540,7 @@ const ProvisionerSettings: React.FC<Props> = (props) => {
}
// If none of the checks have a message, set setPreflightFailed to false
if (hasMessage) {
showIntercomWithMessage({ message: "I am running into an issue provisioning a cluster." });
markStepStarted("provisioning-failed", errors);
}
if (!hasMessage) {
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/hosted.index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
window.intercomSettings = {
app_id: "<%= htmlWebpackPlugin.options.intercomAppId %>",
custom_launcher_selector: "#intercom_help",
alignment: 'right',
};
</script>

Expand Down
3 changes: 2 additions & 1 deletion dashboard/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
<script>
window.intercomSettings = {
api_base: "https://api-iam.intercom.io",
app_id: "gq56g49i"
app_id: "gq56g49i",
alignment: 'right',
};
</script>

Expand Down
1 change: 1 addition & 0 deletions dashboard/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { EnableErrorHandling } from "shared/error_handling/window_error_handling
declare global {
interface Window {
analytics: any;
Intercom: any;
}
}

Expand Down
19 changes: 19 additions & 0 deletions dashboard/src/lib/hooks/useIntercom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// useIntercom contains all the utility methods related to the Intercom chat widget
export const useIntercom = () => {
const showIntercomWithMessageAfterDelay = (message: string, delaySeconds: number) => {
const func = () => {
if (typeof window.Intercom === 'function') {
window.Intercom('showNewMessage', message);
}
}
setTimeout(func, delaySeconds * 1000);
}

const showIntercomWithMessage = ({ message, delaySeconds = 3 }: { message: string, delaySeconds?: number }) => {
showIntercomWithMessageAfterDelay(message, delaySeconds);
}

return {
showIntercomWithMessage,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import axios from "axios";
import HelmEditorTab from "./tabs/HelmEditorTab";
import HelmLatestValuesTab from "./tabs/HelmLatestValuesTab";
import { Context } from "shared/Context";
import { useIntercom } from "lib/hooks/useIntercom";

// commented out tabs are not yet implemented
// will be included as support is available based on data from app revisions rather than helm releases
Expand Down Expand Up @@ -83,6 +84,7 @@ const AppDataContainer: React.FC<AppDataContainerProps> = ({ tabParam }) => {
const { currentProject, user } = useContext(Context);

const { updateAppStep } = useAppAnalytics();
const { showIntercomWithMessage } = useIntercom();

const {
porterApp: porterAppRecord,
Expand Down Expand Up @@ -305,6 +307,8 @@ const AppDataContainer: React.FC<AppDataContainerProps> = ({ tabParam }) => {
// redirect to the default tab after save
history.push(`/apps/${porterAppRecord.name}/${DEFAULT_TAB}`);
} catch (err) {
showIntercomWithMessage({ message: "I am running into an issue updating my application." });

let message =
"App update failed: please try again or contact [email protected] if the error persists.";
let stack = "Unable to get error stack";
Expand Down Expand Up @@ -382,7 +386,6 @@ const AppDataContainer: React.FC<AppDataContainerProps> = ({ tabParam }) => {
const errorKeys = Object.keys(errors);
if (errorKeys.length > 0) {
const stringifiedJson = JSON.stringify(errors);

let errorMessage =
"App update failed. Please try again. If the error persists, please contact [email protected].";
if (errorKeys.includes("app")) {
Expand Down Expand Up @@ -411,6 +414,7 @@ const AppDataContainer: React.FC<AppDataContainerProps> = ({ tabParam }) => {
}
}

showIntercomWithMessage({ message: "I am running into an issue updating my application." });
updateAppStep({
step: "porter-app-update-failure",
errorMessage: `Form validation error (visible to user): ${errorMessage}. Stringified JSON errors (invisible to user): ${stringifiedJson}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import EnvSettings from "../validate-apply/app-settings/EnvSettings";
import ImageSettings from "../image-settings/ImageSettings";
import { useClusterResources } from "shared/ClusterResourcesContext";
import PorterYamlModal from "./PorterYamlModal";
import { useIntercom } from "lib/hooks/useIntercom";

type CreateAppProps = {} & RouteComponentProps;

Expand All @@ -70,6 +71,8 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {
};
const [isNameHighlight, setIsNameHighlight] = React.useState(false);

const { showIntercomWithMessage } = useIntercom();

const [
validatedAppProto,
setValidatedAppProto,
Expand Down Expand Up @@ -336,6 +339,8 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {

return true;
} catch (err) {
showIntercomWithMessage({ message: "I am running into an issue launching an application." });

if (axios.isAxiosError(err) && err.response?.data?.error) {
updateAppStep({
step: "stack-launch-failure",
Expand Down Expand Up @@ -430,6 +435,8 @@ const CreateApp: React.FC<CreateAppProps> = ({ history }) => {
}
}

showIntercomWithMessage({ message: "I am running into an issue launching an application." });

updateAppStep({
step: "stack-launch-failure",
errorMessage: `Form validation error: ${errorMessage}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,18 @@ const Networking: React.FC<NetworkingProps> = ({ index, service, internalNetwork
}, [service.name.value, namespace, port]);

const getApplicationURLText = () => {
if (service.config.domains.length !== 0) {
const numNonEmptyDomains = service.config.domains.filter(
(d) => d.name.value !== ""
);
if (numNonEmptyDomains.length !== 0) {
return (
<Text>
{`External URL${service.config.domains.length === 1 ? "" : "s"}: `}
{service.config.domains.map((d, i) => {
{`External URL${numNonEmptyDomains.length === 1 ? "" : "s"}: `}
{numNonEmptyDomains.map((d, i) => {
return (
<a href={prefixSubdomain(d.name.value)} target="_blank">
{d.name.value}
{i !== service.config.domains.length - 1 && ", "}
{i !== numNonEmptyDomains.length - 1 && ", "}
</a>
);
})}
Expand Down

0 comments on commit 6539bcc

Please sign in to comment.