Wired benefits section to API (#2023)

refs https://github.com/TryGhost/Team/issues/792

- updates product benefit to use `name` instead of `label` attribute for benefit text
- updates model/serializer/validator to correctly handle benefit attributes
- added `+` button for adding new labels as the enter behavior is closing the popup(needs fix)
This commit is contained in:
Rishabh Garg 2021-06-28 15:19:54 +05:30 committed by GitHub
parent 386d59d709
commit 46b311b561
9 changed files with 49 additions and 50 deletions

View File

@ -10,19 +10,19 @@
@tagName="span"
@class="gh-blognav-label"
@errors={{this.benefitItem.errors}}
@property="label"
@property="name"
@hasValidated={{this.benefitItem.hasValidated}}
>
<GhTrimFocusInput
@shouldFocus={{this.benefitItem.last}}
@placeholder="Add benefit"
@value={{readonly this.label}}
@value={{readonly this.name}}
@input={{action "updateLabel" value="target.value"}}
@keyPress={{action "clearLabelErrors"}}
@focus-out={{action "updateLabel" this.label}} data-test-input="label" />
@focus-out={{action "updateLabel" this.name}} data-test-input="name" />
<GhErrorMessage
@errors={{this.benefitItem.errors}}
@property="label" data-test-error="label" />
@property="name" data-test-error="name" />
</GhValidationStatusContainer>
</div>

View File

@ -15,7 +15,7 @@ export default Component.extend(ValidationState, {
addItem() {},
deleteItem() {},
updateLabel() {},
label: boundOneWay('benefitItem.label'),
name: boundOneWay('benefitItem.name'),
errors: readOnly('benefitItem.errors'),
@ -33,13 +33,19 @@ export default Component.extend(ValidationState, {
},
updateLabel(value) {
this.set('label', value);
this.set('name', value);
return this.updateLabel(value, this.benefitItem);
},
clearLabelErrors() {
if (this.get('benefitItem.errors')) {
this.get('benefitItem.errors').remove('label');
clearLabelErrors(event) {
// enter key
if (event.keyCode === 13 && this.get('benefitItem.isNew')) {
event.preventDefault();
run.scheduleOnce('actions', this, this.send, 'addItem', this.benefitItem);
} else {
if (this.get('benefitItem.errors')) {
this.get('benefitItem.errors').remove('name');
}
}
}
},

View File

@ -17,14 +17,11 @@
{{/if}}
</div>
<div class="gh-product-card-block">
<h4>Benefits <span class="counter">(3)</span></h4>
<h4>Benefits <span class="counter">({{product.benefits.length}})</span></h4>
<ul class="benefits">
{{#each product.benefits as |benefit|}}
<li>{{svg-jar "check"}} {{benefit.label}} </li>
<li>{{svg-jar "check"}} {{benefit.name}} </li>
{{/each}}
<li>{{svg-jar "check"}} Access to all J&amp;A Watch J&amp;A episodes, past and future!</li>
<li>{{svg-jar "check"}} An exclusive AD-FREE extra video episode of J&amp;A AMA every other week!</li>
<li>{{svg-jar "check"}} Includes Discord benefits</li>
</ul>
</div>
<div class="gh-product-card-block">

View File

@ -19,25 +19,25 @@ const CURRENCIES = currencies.map((currency) => {
let BENEFITSDATA = emberA([
ProductBenefitItem.create({
label: 'Benefit 1'
name: 'Benefit 1'
}),
ProductBenefitItem.create({
label: 'Benefit 2'
name: 'Benefit 2'
}),
ProductBenefitItem.create({
label: 'Benefit 3'
name: 'Benefit 3'
}),
ProductBenefitItem.create({
label: 'Benefit 4'
name: 'Benefit 4'
}),
ProductBenefitItem.create({
label: 'Benefit 5'
name: 'Benefit 5'
}),
ProductBenefitItem.create({
label: 'Benefit 6'
name: 'Benefit 6'
}),
ProductBenefitItem.create({
label: 'Benefit 7'
name: 'Benefit 7'
})
]);
@ -81,7 +81,7 @@ export default class ModalProductPrice extends ModalBase {
this.benefits = this.product.get('benefits') || BENEFITSDATA;
this.newBenefit = ProductBenefitItem.create({
isNew: true,
label: ''
name: ''
});
}
@ -166,7 +166,7 @@ export default class ModalProductPrice extends ModalBase {
item.set('isNew', false);
this.benefits.pushObject(item);
this.newBenefit = ProductBenefitItem.create({isNew: true, label: ''});
this.newBenefit = ProductBenefitItem.create({isNew: true, name: ''});
}
actions = {
@ -186,8 +186,8 @@ export default class ModalProductPrice extends ModalBase {
return;
}
if (benefitItem.get('label') !== label) {
benefitItem.set('label', label);
if (benefitItem.get('name') !== label) {
benefitItem.set('name', label);
}
},
confirm() {

View File

@ -309,7 +309,7 @@ export default class MembersAccessController extends Controller {
@task({drop: true})
*fetchProducts() {
this.products = yield this.store.query('product', {include: 'monthly_price,yearly_price'});
this.products = yield this.store.query('product', {include: 'monthly_price,yearly_price,benefits'});
this.product = this.products.firstObject;
this.setupPortalProduct(this.product);
}

View File

@ -4,20 +4,20 @@ import {computed} from '@ember/object';
import {isBlank} from '@ember/utils';
export default EmberObject.extend(ValidationEngine, {
label: '',
name: '',
isNew: false,
validationType: 'productBenefitItem',
isComplete: computed('label', function () {
let {label} = this;
isComplete: computed('name', function () {
let {name} = this;
return !isBlank(label);
return !isBlank(name);
}),
isBlank: computed('label', function () {
let {label} = this;
isBlank: computed('name', function () {
let {name} = this;
return isBlank(label);
return isBlank(name);
})
});

View File

@ -424,9 +424,9 @@
opacity: 0;
}
.gh-product-benefits .gh-blognav-add {
/* .gh-product-benefits .gh-blognav-add {
display: none;
}
} */
.gh-product-benefits .gh-blognav-grab {
text-indent: 0px;
@ -440,4 +440,4 @@
.gh-product-benefits .gh-blognav-item:not(.gh-blognav-item--sortable) {
margin-bottom: 16px;
}
}

View File

@ -6,11 +6,7 @@ export default Transform.extend({
deserialize(serialized, options) {
let benefitsItems, benefitsArray;
try {
benefitsArray = JSON.parse(serialized) || [];
} catch (e) {
benefitsArray = [];
}
benefitsArray = serialized || [];
benefitsItems = benefitsArray.map((itemDetails) => {
itemDetails.isSecondary = options && options.isSecondary || false;
@ -25,13 +21,13 @@ export default Transform.extend({
if (isEmberArray(deserialized)) {
benefitsArray = deserialized.map((item) => {
let label = item.get('label').trim();
return {label};
let name = item.get('name').trim();
return {name};
}).compact();
} else {
benefitsArray = [];
}
return JSON.stringify(benefitsArray);
return benefitsArray;
}
});

View File

@ -2,17 +2,17 @@ import BaseValidator from './base';
import {isBlank} from '@ember/utils';
export default BaseValidator.create({
properties: ['label'],
properties: ['name'],
label(model) {
let label = model.get('label');
name(model) {
let name = model.get('name');
let hasValidated = model.get('hasValidated');
if (isBlank(label)) {
model.get('errors').add('label', 'You must specify a label');
if (isBlank(name)) {
model.get('errors').add('name', 'You must specify a name');
this.invalidate();
}
hasValidated.addObject('label');
hasValidated.addObject('name');
}
});