🐛 Fixed Hidden error in "Add tier" modal (#15361)

closes https://github.com/TryGhost/Ghost/issues/15290

- Capture error from model errors
- Add hasValidated for name property to properly mark field as error/success
- Add property to hasValidated after each failed validation
- Wrap saving on try-catch to suppress uncaught exception (validation error)
This commit is contained in:
Hakim Razalan 2022-09-13 16:23:54 +08:00 committed by GitHub
parent 2a3b4908e1
commit e376ef0242
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 15 deletions

View File

@ -14,7 +14,7 @@
<h4 class="gh-main-section-header small bn">Basic</h4>
<div class="gh-main-section-content grey gh-tier-priceform-block">
{{#unless this.isFreeTier}}
<GhFormGroup @errors={{this.errors}} @property="name" data-test-formgroup="name">
<GhFormGroup @errors={{this.tier.errors}} @hasValidated={{this.tier.hasValidated}} @property="name" data-test-formgroup="name">
<label for="name" class="fw6">Name</label>
<GhTextInput
@value={{readonly this.tier.name}}
@ -25,11 +25,11 @@
@id="name"
@class="gh-input"
data-test-input="tier-name" />
<GhErrorMessage @errors={{this.errors}} @property="name" />
<GhErrorMessage @errors={{this.tier.errors}} @property="name" />
</GhFormGroup>
{{/unless}}
<GhFormGroup @errors={{this.errors}} @property="description" data-test-formgroup="description">
<GhFormGroup @errors={{this.tier.errors}} @property="description" data-test-formgroup="description">
<label for="description" class="fw6">Description</label>
{{#if this.isFreeTier}}
<GhTextInput
@ -50,7 +50,7 @@
@class="gh-input"
data-test-input="tier-description" />
{{/if}}
<GhErrorMessage @errors={{this.errors}} @property="description" />
<GhErrorMessage @errors={{this.tier.errors}} @property="description" />
</GhFormGroup>
{{#unless this.isFreeTier}}
@ -107,7 +107,7 @@
{{/if}}
</GhFormGroup>
<GhFormGroup @errors={{this.errors}} @property="trialDays" data-test-formgroup="trialDays">
<GhFormGroup @errors={{this.tier.errors}} @property="trialDays" data-test-formgroup="trialDays">
<div class="flex justify-between items-center mb2">
<div>
<h4 class="gh-tier-setting-title">Add a free trial</h4>

View File

@ -1,11 +1,10 @@
import EmberObject, {action} from '@ember/object';
import ModalBase from 'ghost-admin/components/modal-base';
import TierBenefitItem from '../models/tier-benefit-item';
import classic from 'ember-classic-decorator';
import {action} from '@ember/object';
import {currencies, getCurrencyOptions, getSymbol} from 'ghost-admin/utils/currency';
import {A as emberA} from '@ember/array';
import {htmlSafe} from '@ember/template';
import {isEmpty} from '@ember/utils';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';
@ -30,7 +29,6 @@ export default class ModalTierPrice extends ModalBase {
@tracked stripeMonthlyAmount = 5;
@tracked stripeYearlyAmount = 50;
@tracked currency = 'usd';
@tracked errors = EmberObject.create();
@tracked stripePlanError = '';
@tracked benefits = emberA([]);
@tracked newBenefit = null;
@ -159,9 +157,7 @@ export default class ModalTierPrice extends ModalBase {
@task({drop: true})
*saveTier() {
this.validatePrices();
if (!isEmpty(this.errors) && Object.keys(this.errors).length > 0) {
return;
}
if (this.stripePlanError || this.hasTrialDaysError) {
return;
}
@ -183,10 +179,20 @@ export default class ModalTierPrice extends ModalBase {
}
this.tier.set('benefits', this.benefits.filter(benefit => !benefit.get('isBlank')));
try {
yield this.tier.save();
this.hasSaved = true;
yield this.confirm();
this.send('closeModal');
} catch (error) {
if (error === undefined) {
// Validation error
return;
}
throw error;
}
}
validatePrices() {

View File

@ -7,10 +7,12 @@ export default BaseValidator.create({
name(model) {
if (!model.name) {
model.errors.add('name', 'Please enter Name.');
model.hasValidated.addObject('name');
this.invalidate();
}
if (!validator.isLength(model.name || '', 0, 191)) {
model.errors.add('name', 'Name cannot be longer than 191 characters.');
model.hasValidated.addObject('name');
this.invalidate();
}
}