Updating error message on mongo collection create (#118)
* 1) Updated mongo collection create pane to display a better error when a shard key is ill formed. 2) Updated an error message to use double quotes since no string interpolation is used. I thought it was included in a previoue PR but I guess the change didn't get staged.
This commit is contained in:
parent
a64109ebaa
commit
d45af21996
|
@ -301,7 +301,6 @@ src/Utils/NotebookConfigurationUtils.ts
|
|||
src/Utils/OfferUtils.test.ts
|
||||
src/Utils/OfferUtils.ts
|
||||
src/Utils/PricingUtils.test.ts
|
||||
src/Utils/PricingUtils.ts
|
||||
src/Utils/QueryUtils.test.ts
|
||||
src/Utils/QueryUtils.ts
|
||||
src/Utils/StringUtils.test.ts
|
||||
|
|
|
@ -1,67 +1,69 @@
|
|||
import * as DataModels from "../Contracts/DataModels";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
|
||||
export function replaceKnownError(err: string): string {
|
||||
if (
|
||||
window.dataExplorer.subscriptionType() === ViewModels.SubscriptionType.Internal &&
|
||||
err.indexOf("SharedOffer is Disabled for your account") >= 0
|
||||
) {
|
||||
return "Database throughput is not supported for internal subscriptions.";
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
export function parse(err: any): DataModels.ErrorDataModel[] {
|
||||
try {
|
||||
return _parse(err);
|
||||
} catch (e) {
|
||||
return [<DataModels.ErrorDataModel>{ message: JSON.stringify(err) }];
|
||||
}
|
||||
}
|
||||
|
||||
function _parse(err: any): DataModels.ErrorDataModel[] {
|
||||
var normalizedErrors: DataModels.ErrorDataModel[] = [];
|
||||
if (err.message && !err.code) {
|
||||
normalizedErrors.push(err);
|
||||
} else {
|
||||
const innerErrors: any[] = _getInnerErrors(err.message);
|
||||
normalizedErrors = innerErrors.map(innerError =>
|
||||
typeof innerError === "string" ? { message: innerError } : innerError
|
||||
);
|
||||
}
|
||||
|
||||
return normalizedErrors;
|
||||
}
|
||||
|
||||
function _getInnerErrors(message: string): any[] {
|
||||
/*
|
||||
The backend error message has an inner-message which is a stringified object.
|
||||
|
||||
For SQL errors, the "errors" property is an array of SqlErrorDataModel.
|
||||
Example:
|
||||
"Message: {"Errors":["Resource with specified id or name already exists"]}\r\nActivityId: 80005000008d40b6a, Request URI: /apps/19000c000c0a0005/services/mctestdocdbprod-MasterService-0-00066ab9937/partitions/900005f9000e676fb8/replicas/13000000000955p"
|
||||
For non-SQL errors the "Errors" propery is an array of string.
|
||||
Example:
|
||||
"Message: {"errors":[{"severity":"Error","location":{"start":7,"end":8},"code":"SC1001","message":"Syntax error, incorrect syntax near '.'."}]}\r\nActivityId: d3300016d4084e310a, Request URI: /apps/12401f9e1df77/services/dc100232b1f44545/partitions/f86f3bc0001a2f78/replicas/13085003638s"
|
||||
*/
|
||||
|
||||
let innerMessage: any = null;
|
||||
|
||||
const singleLineMessage = message.replace(/[\r\n]|\r|\n/g, "");
|
||||
try {
|
||||
// Multi-Partition error flavor
|
||||
const regExp = /^(.*)ActivityId: (.*)/g;
|
||||
const regString = regExp.exec(singleLineMessage);
|
||||
const innerMessageString = regString[1];
|
||||
innerMessage = JSON.parse(innerMessageString);
|
||||
} catch (e) {
|
||||
// Single-partition error flavor
|
||||
const regExp = /^Message: (.*)ActivityId: (.*), Request URI: (.*)/g;
|
||||
const regString = regExp.exec(singleLineMessage);
|
||||
const innerMessageString = regString[1];
|
||||
innerMessage = JSON.parse(innerMessageString);
|
||||
}
|
||||
|
||||
return innerMessage.errors ? innerMessage.errors : innerMessage.Errors;
|
||||
}
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
|
||||
export function replaceKnownError(err: string): string {
|
||||
if (
|
||||
window.dataExplorer.subscriptionType() === ViewModels.SubscriptionType.Internal &&
|
||||
err.indexOf("SharedOffer is Disabled for your account") >= 0
|
||||
) {
|
||||
return "Database throughput is not supported for internal subscriptions.";
|
||||
} else if (err.indexOf("Partition key paths must contain only valid") >= 0) {
|
||||
return "Partition key paths must contain only valid characters and not contain a trailing slash or wildcard character.";
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
export function parse(err: any): DataModels.ErrorDataModel[] {
|
||||
try {
|
||||
return _parse(err);
|
||||
} catch (e) {
|
||||
return [<DataModels.ErrorDataModel>{ message: JSON.stringify(err) }];
|
||||
}
|
||||
}
|
||||
|
||||
function _parse(err: any): DataModels.ErrorDataModel[] {
|
||||
var normalizedErrors: DataModels.ErrorDataModel[] = [];
|
||||
if (err.message && !err.code) {
|
||||
normalizedErrors.push(err);
|
||||
} else {
|
||||
const innerErrors: any[] = _getInnerErrors(err.message);
|
||||
normalizedErrors = innerErrors.map(innerError =>
|
||||
typeof innerError === "string" ? { message: innerError } : innerError
|
||||
);
|
||||
}
|
||||
|
||||
return normalizedErrors;
|
||||
}
|
||||
|
||||
function _getInnerErrors(message: string): any[] {
|
||||
/*
|
||||
The backend error message has an inner-message which is a stringified object.
|
||||
|
||||
For SQL errors, the "errors" property is an array of SqlErrorDataModel.
|
||||
Example:
|
||||
"Message: {"Errors":["Resource with specified id or name already exists"]}\r\nActivityId: 80005000008d40b6a, Request URI: /apps/19000c000c0a0005/services/mctestdocdbprod-MasterService-0-00066ab9937/partitions/900005f9000e676fb8/replicas/13000000000955p"
|
||||
For non-SQL errors the "Errors" propery is an array of string.
|
||||
Example:
|
||||
"Message: {"errors":[{"severity":"Error","location":{"start":7,"end":8},"code":"SC1001","message":"Syntax error, incorrect syntax near '.'."}]}\r\nActivityId: d3300016d4084e310a, Request URI: /apps/12401f9e1df77/services/dc100232b1f44545/partitions/f86f3bc0001a2f78/replicas/13085003638s"
|
||||
*/
|
||||
|
||||
let innerMessage: any = null;
|
||||
|
||||
const singleLineMessage = message.replace(/[\r\n]|\r|\n/g, "");
|
||||
try {
|
||||
// Multi-Partition error flavor
|
||||
const regExp = /^(.*)ActivityId: (.*)/g;
|
||||
const regString = regExp.exec(singleLineMessage);
|
||||
const innerMessageString = regString[1];
|
||||
innerMessage = JSON.parse(innerMessageString);
|
||||
} catch (e) {
|
||||
// Single-partition error flavor
|
||||
const regExp = /^Message: (.*)ActivityId: (.*), Request URI: (.*)/g;
|
||||
const regString = regExp.exec(singleLineMessage);
|
||||
const innerMessageString = regString[1];
|
||||
innerMessage = JSON.parse(innerMessageString);
|
||||
}
|
||||
|
||||
return innerMessage.errors ? innerMessage.errors : innerMessage.Errors;
|
||||
}
|
||||
|
|
|
@ -373,12 +373,12 @@ describe("PricingUtils Tests", () => {
|
|||
expect(value).toBe(1);
|
||||
});
|
||||
|
||||
it("should return 1 for -1", () => {
|
||||
it("should return -1 for -1", () => {
|
||||
const value = PricingUtils.normalizeNumber(-1);
|
||||
expect(value).toBe(-1);
|
||||
});
|
||||
|
||||
it("should return 1 for 0.1", () => {
|
||||
it("should return 0 for 0.1", () => {
|
||||
const value = PricingUtils.normalizeNumber(0.1);
|
||||
expect(value).toBe(0);
|
||||
});
|
||||
|
|
|
@ -7,10 +7,11 @@ import { AutopilotTier } from "../Contracts/DataModels";
|
|||
* Otherwise, return numberOfRegions
|
||||
* @param number
|
||||
*/
|
||||
export function normalizeNumber(number: any): number {
|
||||
const normalizedNumber: number = number === null ? 0 : isNaN(number) ? 0 : parseInt(number);
|
||||
|
||||
return normalizedNumber;
|
||||
export function normalizeNumber(number: null | undefined | string | number): number {
|
||||
if (!number) {
|
||||
return 0;
|
||||
}
|
||||
return Math.floor(Number(number));
|
||||
}
|
||||
|
||||
export function getRuToolTipText(isV2AutoPilot: boolean): string {
|
||||
|
@ -79,16 +80,16 @@ export function getPriceCurrency(serverId: string): string {
|
|||
|
||||
export function computeStorageUsagePrice(serverId: string, storageUsedRoundUpToGB: number): string {
|
||||
if (serverId === "mooncake") {
|
||||
let storageCharge = storageUsedRoundUpToGB * Constants.OfferPricing.HourlyPricing.mooncake.Standard.PricePerGB;
|
||||
const storageCharge = storageUsedRoundUpToGB * Constants.OfferPricing.HourlyPricing.mooncake.Standard.PricePerGB;
|
||||
return calculateEstimateNumber(storageCharge) + " " + Constants.OfferPricing.HourlyPricing.mooncake.Currency;
|
||||
}
|
||||
|
||||
let storageCharge = storageUsedRoundUpToGB * Constants.OfferPricing.HourlyPricing.default.Standard.PricePerGB;
|
||||
const storageCharge = storageUsedRoundUpToGB * Constants.OfferPricing.HourlyPricing.default.Standard.PricePerGB;
|
||||
return calculateEstimateNumber(storageCharge) + " " + Constants.OfferPricing.HourlyPricing.default.Currency;
|
||||
}
|
||||
|
||||
export function computeDisplayUsageString(usageInKB: number): string {
|
||||
let usageInMB = usageInKB / 1024,
|
||||
const usageInMB = usageInKB / 1024,
|
||||
usageInGB = usageInMB / 1024,
|
||||
displayUsageString =
|
||||
usageInGB > 0.1
|
||||
|
@ -100,7 +101,7 @@ export function computeDisplayUsageString(usageInKB: number): string {
|
|||
}
|
||||
|
||||
export function usageInGB(usageInKB: number): number {
|
||||
let usageInMB = usageInKB / 1024,
|
||||
const usageInMB = usageInKB / 1024,
|
||||
usageInGB = usageInMB / 1024;
|
||||
return Math.ceil(usageInGB);
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ export function calculateEstimateNumber(n: number): string {
|
|||
return n >= 1 ? n.toFixed(2) : n.toPrecision(2);
|
||||
}
|
||||
|
||||
export function numberWithCommasFormatter(n: number) {
|
||||
export function numberWithCommasFormatter(n: number): string {
|
||||
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
|
@ -279,9 +280,9 @@ export function getEstimatedSpendAcknowledgeString(
|
|||
)} - ${currencySign}${calculateEstimateNumber(monthlyPrice)} monthly cost for the throughput above.`;
|
||||
}
|
||||
|
||||
export function getUpsellMessage(serverId: string = "default", isFreeTier: boolean = false): string {
|
||||
export function getUpsellMessage(serverId = "default", isFreeTier = false): string {
|
||||
if (isFreeTier) {
|
||||
return `With free tier discount, you'll get the first 400 RU/s and 5 GB of storage in this account for free. Charges will apply if your resource throughput exceeds 400 RU/s.`;
|
||||
return "With free tier discount, you'll get the first 400 RU/s and 5 GB of storage in this account for free. Charges will apply if your resource throughput exceeds 400 RU/s.";
|
||||
} else {
|
||||
let price: number = Constants.OfferPricing.MonthlyPricing.default.Standard.StartingPrice;
|
||||
|
||||
|
|
Loading…
Reference in New Issue