From 46b311b5611bb905829fd313f1e87a1fc5f0a4a9 Mon Sep 17 00:00:00 2001 From: Rishabh Garg Date: Mon, 28 Jun 2021 15:19:54 +0530 Subject: [PATCH] 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) --- .../admin/app/components/gh-benefit-item.hbs | 8 +++---- ghost/admin/app/components/gh-benefit-item.js | 16 +++++++++----- .../gh-membership-products-alpha.hbs | 7 ++---- ghost/admin/app/components/modal-product.js | 22 +++++++++---------- .../app/controllers/settings/membership.js | 2 +- .../admin/app/models/product-benefit-item.js | 14 ++++++------ ghost/admin/app/styles/layouts/products.css | 6 ++--- .../admin/app/transforms/product-benefits.js | 12 ++++------ .../app/validators/product-benefit-item.js | 12 +++++----- 9 files changed, 49 insertions(+), 50 deletions(-) diff --git a/ghost/admin/app/components/gh-benefit-item.hbs b/ghost/admin/app/components/gh-benefit-item.hbs index 5b531b5e5e..2ef37b80e2 100644 --- a/ghost/admin/app/components/gh-benefit-item.hbs +++ b/ghost/admin/app/components/gh-benefit-item.hbs @@ -10,19 +10,19 @@ @tagName="span" @class="gh-blognav-label" @errors={{this.benefitItem.errors}} - @property="label" + @property="name" @hasValidated={{this.benefitItem.hasValidated}} > + @focus-out={{action "updateLabel" this.name}} data-test-input="name" /> + @property="name" data-test-error="name" /> diff --git a/ghost/admin/app/components/gh-benefit-item.js b/ghost/admin/app/components/gh-benefit-item.js index 48c602e1c4..04ad955b2d 100644 --- a/ghost/admin/app/components/gh-benefit-item.js +++ b/ghost/admin/app/components/gh-benefit-item.js @@ -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'); + } } } }, diff --git a/ghost/admin/app/components/gh-membership-products-alpha.hbs b/ghost/admin/app/components/gh-membership-products-alpha.hbs index 83f54473db..a06d73e480 100644 --- a/ghost/admin/app/components/gh-membership-products-alpha.hbs +++ b/ghost/admin/app/components/gh-membership-products-alpha.hbs @@ -17,14 +17,11 @@ {{/if}}
-

Benefits (3)

+

Benefits ({{product.benefits.length}})

    {{#each product.benefits as |benefit|}} -
  • {{svg-jar "check"}} {{benefit.label}}
  • +
  • {{svg-jar "check"}} {{benefit.name}}
  • {{/each}} -
  • {{svg-jar "check"}} Access to all J&A Watch J&A episodes, past and future!
  • -
  • {{svg-jar "check"}} An exclusive AD-FREE extra video episode of J&A AMA every other week!
  • -
  • {{svg-jar "check"}} Includes Discord benefits
diff --git a/ghost/admin/app/components/modal-product.js b/ghost/admin/app/components/modal-product.js index f0292a7c65..907e92096f 100644 --- a/ghost/admin/app/components/modal-product.js +++ b/ghost/admin/app/components/modal-product.js @@ -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() { diff --git a/ghost/admin/app/controllers/settings/membership.js b/ghost/admin/app/controllers/settings/membership.js index 911950cded..158c65424b 100644 --- a/ghost/admin/app/controllers/settings/membership.js +++ b/ghost/admin/app/controllers/settings/membership.js @@ -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); } diff --git a/ghost/admin/app/models/product-benefit-item.js b/ghost/admin/app/models/product-benefit-item.js index 65b39c24b2..e73b327133 100644 --- a/ghost/admin/app/models/product-benefit-item.js +++ b/ghost/admin/app/models/product-benefit-item.js @@ -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); }) }); diff --git a/ghost/admin/app/styles/layouts/products.css b/ghost/admin/app/styles/layouts/products.css index cff79277b6..70b19d2de0 100644 --- a/ghost/admin/app/styles/layouts/products.css +++ b/ghost/admin/app/styles/layouts/products.css @@ -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; -} \ No newline at end of file +} diff --git a/ghost/admin/app/transforms/product-benefits.js b/ghost/admin/app/transforms/product-benefits.js index 8b072285d4..09f1c27b47 100644 --- a/ghost/admin/app/transforms/product-benefits.js +++ b/ghost/admin/app/transforms/product-benefits.js @@ -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; } }); diff --git a/ghost/admin/app/validators/product-benefit-item.js b/ghost/admin/app/validators/product-benefit-item.js index 4832025b60..a26f3596ee 100644 --- a/ghost/admin/app/validators/product-benefit-item.js +++ b/ghost/admin/app/validators/product-benefit-item.js @@ -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'); } });