diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef889f6d2..a56bcd1c0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,9 +10,14 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### Added
- Added costs for configurable string feature options in `manifold-plan-selector`.
-- Added `read-only` attribute to `manifold-plan-details` to optionally disable inputs for configurable features.
+- Added `read-only` attribute to `manifold-plan-details` to optionally disable inputs for
+ configurable features.
- Added the ability to create and resize plans with configurable features.
+### Fixed
+
+- Properly handle errors from aborted network requests in `manifold-plan-cost`.
+
## [0.9.3] - 2019-01-13
### Added
diff --git a/package.json b/package.json
index 52c0a3501..486cabc99 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@manifoldco/ui",
"description": "Manifold UI",
- "version": "0.9.3",
+ "version": "0.9.4-rc.0",
"repository": {
"type": "git",
"url": "git+https://github.com/manifoldco/ui.git"
diff --git a/src/components/manifold-plan-cost/manifold-plan-cost.tsx b/src/components/manifold-plan-cost/manifold-plan-cost.tsx
index 8ff2df392..f7f0526e2 100644
--- a/src/components/manifold-plan-cost/manifold-plan-cost.tsx
+++ b/src/components/manifold-plan-cost/manifold-plan-cost.tsx
@@ -20,6 +20,7 @@ export class ManifoldPlanCost {
@Prop() selectedFeatures?: Gateway.FeatureMap;
@State() calculatedCost?: number;
@State() controller?: AbortController;
+ @State() error?: string;
@Watch('plan') planChange() {
this.fetchCustomCost();
}
@@ -45,6 +46,7 @@ export class ManifoldPlanCost {
// Hide display while calculating
this.calculatedCost = undefined;
+ this.error = undefined;
if (this.controller) {
this.controller.abort();
} // If a request is in flight, cancel it
@@ -58,27 +60,42 @@ export class ManifoldPlanCost {
planID: this.plan.id,
features,
init: { signal: this.controller.signal },
- }).then(({ cost }: Gateway.Price) => {
- this.calculatedCost = cost || 0;
- this.controller = undefined; // Request finished, so signal no longer needed
- });
+ })
+ .then(({ cost }: Gateway.Price) => {
+ this.calculatedCost = cost || 0;
+ this.controller = undefined; // Request finished, so signal no longer needed
+ })
+ .catch(e => {
+ if (e.name !== 'AbortError') {
+ this.error = 'Error getting plan cost.';
+ }
+ });
}
@logger()
render() {
+ if (this.error) {
+ return {this.error};
+ }
+
+ if (this.calculatedCost === undefined) {
+ return Calculating cost...;
+ }
+
+ const meteredFeatures =
+ (this.plan && this.plan.meteredFeatures && this.plan.meteredFeatures.edges) || undefined;
+ const isConfigurable =
+ (this.plan &&
+ this.plan.configurableFeatures &&
+ this.plan.configurableFeatures.edges.length > 0) ||
+ false;
+
return (
0) ||
- false
- }
+ meteredFeatures={meteredFeatures}
+ configurable={isConfigurable}
/>
);
}