Added a different message if the account is free tier (#69)

* Added a different upsell message if the account is free tier

* Fixing prettier and unit tests
This commit is contained in:
vchske 2020-07-08 10:02:47 -07:00 committed by GitHub
parent 512f56c28a
commit 955d08e4d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 132 additions and 18 deletions

View File

@ -15,7 +15,7 @@
.infoBoxMessage {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
white-space: normal;
width: 320px;
padding-top: 2px;
color: @BaseHigh;

View File

@ -374,6 +374,8 @@ export class HttpStatusCodes {
export class Urls {
public static feedbackEmail = "https://aka.ms/cosmosdbfeedback?subject=Cosmos%20DB%20Data%20Explorer%20Feedback";
public static autoscaleMigration = "https://aka.ms/cosmos-autoscale-migration";
public static freeTierInformation = "https://aka.ms/cosmos-free-tier";
public static cosmosPricing = "https://aka.ms/azure-cosmos-db-pricing";
}
export class HashRoutePrefixes {

View File

@ -61,9 +61,8 @@
<span><img class="infoBoxIcon" src="/info_color.svg" alt="Promo"></span>
<span class="infoBoxDetails">
<span class="infoBoxMessage" data-bind="text: upsellMessage, attr: { title: upsellMessage }"></span>
<a class="underlinedLink" id="linkAddCollection" data-bind="attr: { 'aria-label': upsellMessageAriaLabel }"
target="_blank" href="https://aka.ms/azure-cosmos-db-pricing" tabindex="0">
More details</a>
<a class="underlinedLink" id="linkAddCollection" data-bind="text: upsellAnchorText, attr: { 'href': upsellAnchorUrl, 'aria-label': upsellMessageAriaLabel }"
target="_blank" href="" tabindex="0"></a>
</span>
</div>
</div>

View File

@ -13,7 +13,29 @@ describe("Add Collection Pane", () => {
kind: "DocumentDB",
location: "",
name: "mock",
properties: undefined,
properties: {
documentEndpoint: "",
cassandraEndpoint: "",
gremlinEndpoint: "",
tableEndpoint: "",
enableFreeTier: false
},
type: undefined,
tags: []
};
const mockFreeTierDatabaseAccount: ViewModels.DatabaseAccount = {
id: "mock",
kind: "DocumentDB",
location: "",
name: "mock",
properties: {
documentEndpoint: "",
cassandraEndpoint: "",
gremlinEndpoint: "",
tableEndpoint: "",
enableFreeTier: true
},
type: undefined,
tags: []
};
@ -68,5 +90,23 @@ describe("Add Collection Pane", () => {
addCollectionPane.partitionKey("/label");
expect(addCollectionPane.isValid()).toBe(true);
});
it("should display free tier text in upsell messaging", () => {
explorer.databaseAccount(mockFreeTierDatabaseAccount);
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
expect(addCollectionPane.isFreeTierAccount()).toBe(true);
expect(addCollectionPane.upsellMessage()).toContain("With free tier discount");
expect(addCollectionPane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation);
expect(addCollectionPane.upsellAnchorText()).toBe("Learn more");
});
it("should display standard texr in upsell messaging", () => {
explorer.databaseAccount(mockDatabaseAccount);
const addCollectionPane = explorer.addCollectionPane as AddCollectionPane;
expect(addCollectionPane.isFreeTierAccount()).toBe(false);
expect(addCollectionPane.upsellMessage()).toContain("Start at");
expect(addCollectionPane.upsellAnchorUrl()).toBe(Constants.Urls.cosmosPricing);
expect(addCollectionPane.upsellAnchorText()).toBe("More details");
});
});
});

View File

@ -69,6 +69,8 @@ export default class AddCollectionPane extends ContextualPaneBase implements Vie
public uniqueKeysPlaceholder: ko.Computed<string>;
public upsellMessage: ko.PureComputed<string>;
public upsellMessageAriaLabel: ko.PureComputed<string>;
public upsellAnchorUrl: ko.PureComputed<string>;
public upsellAnchorText: ko.PureComputed<string>;
public debugstring: ko.Computed<string>;
public displayCollectionThroughput: ko.Computed<boolean>;
public isAutoPilotSelected: ko.Observable<boolean>;
@ -508,11 +510,19 @@ export default class AddCollectionPane extends ContextualPaneBase implements Vie
});
this.upsellMessage = ko.pureComputed<string>(() => {
return PricingUtils.getUpsellMessage(this.container.serverId());
return PricingUtils.getUpsellMessage(this.container.serverId(), this.isFreeTierAccount());
});
this.upsellMessageAriaLabel = ko.pureComputed<string>(() => {
return `${this.upsellMessage()}. Click for more details`;
return `${this.upsellMessage()}. Click ${this.isFreeTierAccount() ? "to learn more" : "for more details"}`;
});
this.upsellAnchorUrl = ko.pureComputed<string>(() => {
return this.isFreeTierAccount() ? Constants.Urls.freeTierInformation : Constants.Urls.cosmosPricing;
});
this.upsellAnchorText = ko.pureComputed<string>(() => {
return this.isFreeTierAccount() ? "Learn more" : "More details";
});
this.displayCollectionThroughput = ko.computed<boolean>(() => {

View File

@ -53,9 +53,8 @@
<span><img class="infoBoxIcon" src="/info_color.svg" alt="Promo"></span>
<span class="infoBoxDetails">
<span class="infoBoxMessage" data-bind="text: upsellMessage, attr: { title: upsellMessage }"></span>
<a class="underlinedLink" id="linkAddDatabase" data-bind="attr: { 'aria-label': upsellMessageAriaLabel }"
target="_blank" href="https://aka.ms/azure-cosmos-db-pricing" tabindex="0">
More details</a>
<a class="underlinedLink" id="linkAddDatabase" data-bind="text: upsellAnchorText, attr: { 'href': upsellAnchorUrl, 'aria-label': upsellMessageAriaLabel }"
target="_blank" href="" tabindex="0"></a>
</span>
</div>
</div>

View File

@ -1,3 +1,4 @@
import * as Constants from "../../Common/Constants";
import * as ViewModels from "../../Contracts/ViewModels";
import Explorer from "../Explorer";
import AddDatabasePane from "./AddDatabasePane";
@ -5,6 +6,37 @@ import AddDatabasePane from "./AddDatabasePane";
describe("Add Database Pane", () => {
describe("getSharedThroughputDefault()", () => {
let explorer: ViewModels.Explorer;
const mockDatabaseAccount: ViewModels.DatabaseAccount = {
id: "mock",
kind: "DocumentDB",
location: "",
name: "mock",
properties: {
documentEndpoint: "",
cassandraEndpoint: "",
gremlinEndpoint: "",
tableEndpoint: "",
enableFreeTier: false
},
type: undefined,
tags: []
};
const mockFreeTierDatabaseAccount: ViewModels.DatabaseAccount = {
id: "mock",
kind: "DocumentDB",
location: "",
name: "mock",
properties: {
documentEndpoint: "",
cassandraEndpoint: "",
gremlinEndpoint: "",
tableEndpoint: "",
enableFreeTier: true
},
type: undefined,
tags: []
};
beforeEach(() => {
explorer = new Explorer({
@ -43,5 +75,23 @@ describe("Add Database Pane", () => {
const addDatabasePane = explorer.addDatabasePane as AddDatabasePane;
expect(addDatabasePane.getSharedThroughputDefault()).toBe(true);
});
it("should display free tier text in upsell messaging", () => {
explorer.databaseAccount(mockFreeTierDatabaseAccount);
const addDatabasePane = explorer.addDatabasePane as AddDatabasePane;
expect(addDatabasePane.isFreeTierAccount()).toBe(true);
expect(addDatabasePane.upsellMessage()).toContain("With free tier discount");
expect(addDatabasePane.upsellAnchorUrl()).toBe(Constants.Urls.freeTierInformation);
expect(addDatabasePane.upsellAnchorText()).toBe("Learn more");
});
it("should display standard texr in upsell messaging", () => {
explorer.databaseAccount(mockDatabaseAccount);
const addDatabasePane = explorer.addDatabasePane as AddDatabasePane;
expect(addDatabasePane.isFreeTierAccount()).toBe(false);
expect(addDatabasePane.upsellMessage()).toContain("Start at");
expect(addDatabasePane.upsellAnchorUrl()).toBe(Constants.Urls.cosmosPricing);
expect(addDatabasePane.upsellAnchorText()).toBe("More details");
});
});
});

View File

@ -38,6 +38,8 @@ export default class AddDatabasePane extends ContextualPaneBase implements ViewM
public costsVisible: ko.PureComputed<boolean>;
public upsellMessage: ko.PureComputed<string>;
public upsellMessageAriaLabel: ko.PureComputed<string>;
public upsellAnchorUrl: ko.PureComputed<string>;
public upsellAnchorText: ko.PureComputed<string>;
public isAutoPilotSelected: ko.Observable<boolean>;
public selectedAutoPilotTier: ko.Observable<DataModels.AutopilotTier>;
public autoPilotTiersList: ko.ObservableArray<ViewModels.DropdownOption<DataModels.AutopilotTier>>;
@ -228,11 +230,19 @@ export default class AddDatabasePane extends ContextualPaneBase implements ViewM
});
this.upsellMessage = ko.pureComputed<string>(() => {
return PricingUtils.getUpsellMessage(this.container.serverId());
return PricingUtils.getUpsellMessage(this.container.serverId(), this.isFreeTierAccount());
});
this.upsellMessageAriaLabel = ko.pureComputed<string>(() => {
return `${this.upsellMessage()}. Click for more details`;
return `${this.upsellMessage()}. Click ${this.isFreeTierAccount() ? "to learn more" : "for more details"}`;
});
this.upsellAnchorUrl = ko.pureComputed<string>(() => {
return this.isFreeTierAccount() ? Constants.Urls.freeTierInformation : Constants.Urls.cosmosPricing;
});
this.upsellAnchorText = ko.pureComputed<string>(() => {
return this.isFreeTierAccount() ? "Learn more" : "More details";
});
}

View File

@ -279,12 +279,16 @@ export function getEstimatedSpendAcknowledgeString(
)} - ${currencySign}${calculateEstimateNumber(monthlyPrice)} monthly cost for the throughput above.`;
}
export function getUpsellMessage(serverId: string = "default"): string {
let price: number = Constants.OfferPricing.MonthlyPricing.default.Standard.StartingPrice;
export function getUpsellMessage(serverId: string = "default", isFreeTier: boolean = 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.`;
} else {
let price: number = Constants.OfferPricing.MonthlyPricing.default.Standard.StartingPrice;
if (serverId === "mooncake") {
price = Constants.OfferPricing.MonthlyPricing.mooncake.Standard.StartingPrice;
if (serverId === "mooncake") {
price = Constants.OfferPricing.MonthlyPricing.mooncake.Standard.StartingPrice;
}
return `Start at ${getCurrencySign(serverId)}${price}/mo per database, multiple containers included`;
}
return `Start at ${getCurrencySign(serverId)}${price}/mo per database, multiple containers included`;
}