diff --git a/ghost/admin/app/components/gh-benefit-item.hbs b/ghost/admin/app/components/gh-benefit-item.hbs
index 2406575f4c..21738c8a2c 100644
--- a/ghost/admin/app/components/gh-benefit-item.hbs
+++ b/ghost/admin/app/components/gh-benefit-item.hbs
@@ -1,39 +1,46 @@
-{{#unless this.benefitItem.isNew}}
-
- {{svg-jar "grab"}}
- Reorder
-
-{{/unless}}
+
+ {{#unless @benefitItem.isNew}}
+
+ {{svg-jar "grab"}}
+ Reorder
+
+ {{/unless}}
-
- {{svg-jar "check-2"}}
-
-
+
+ {{svg-jar "check-2"}}
+
+
-
-
-
+
+
+
-{{#if this.benefitItem.isNew}}
-
-{{else}}
-
-{{/if}}
+ {{#if @benefitItem.isNew}}
+
+ {{else}}
+
+ {{/if}}
+
+
\ No newline at end of file
diff --git a/ghost/admin/app/components/gh-benefit-item.js b/ghost/admin/app/components/gh-benefit-item.js
index cce8042910..ec32702510 100644
--- a/ghost/admin/app/components/gh-benefit-item.js
+++ b/ghost/admin/app/components/gh-benefit-item.js
@@ -1,58 +1,19 @@
-import Component from '@ember/component';
-import ValidationState from 'ghost-admin/mixins/validation-state';
-import boundOneWay from 'ghost-admin/utils/bound-one-way';
-import {computed} from '@ember/object';
-import {readOnly} from '@ember/object/computed';
-import {run} from '@ember/runloop';
+import Component from '@glimmer/component';
+import {action} from '@ember/object';
-export default Component.extend(ValidationState, {
- classNames: 'gh-blognav-item',
- classNameBindings: ['errorClass', 'benefitItem.isNew::gh-blognav-item--sortable'],
-
- new: false,
-
- // closure actions
- addItem() {},
- deleteItem() {},
- updateLabel() {},
- name: boundOneWay('benefitItem.name'),
-
- errors: readOnly('benefitItem.errors'),
-
- errorClass: computed('hasError', function () {
- return this.hasError ? 'gh-blognav-item--error' : '';
- }),
-
- actions: {
- addItem(item) {
- this.addItem(item);
- },
-
- deleteItem(item) {
- this.deleteItem(item);
- },
-
- updateLabel(value) {
- this.set('name', value);
- return this.updateLabel(value, this.benefitItem);
- },
-
- clearLabelErrors() {
- if (this.get('benefitItem.errors')) {
- this.get('benefitItem.errors').remove('name');
- }
- }
- },
-
- keyPress(event) {
- // enter key
- if (event.keyCode === 13) {
- event.preventDefault();
- if (this.get('benefitItem.isNew')) {
- run.scheduleOnce('actions', this, this.send, 'addItem', this.benefitItem);
- } else {
- run.scheduleOnce('actions', this, this.send, 'focusItem', this.benefitItem);
- }
- }
+export default class GhBenefitItem extends Component {
+ @action
+ handleLabelInput(event) {
+ this.updateLabel(event.target.value);
}
-});
+
+ @action
+ updateLabel(value) {
+ this.args.updateLabel(value, this.args.benefitItem);
+ }
+
+ @action
+ clearLabelErrors() {
+ this.args.benefitItem.errors?.remove('name');
+ }
+}
diff --git a/ghost/admin/app/modifiers/validation-status.js b/ghost/admin/app/modifiers/validation-status.js
index 3b71f5c2df..bb8f74e553 100644
--- a/ghost/admin/app/modifiers/validation-status.js
+++ b/ghost/admin/app/modifiers/validation-status.js
@@ -1,12 +1,18 @@
import Modifier from 'ember-modifier';
import {isEmpty} from '@ember/utils';
-const errorClass = 'error';
-const successClass = 'success';
+const ERROR_CLASS = 'error';
+const SUCCESS_CLASS = 'success';
export default class ValidationStatusModifier extends Modifier {
- modify(element, positional, {errors, property, hasValidated}) {
- const validationClass = this.errorClass(errors, property, hasValidated);
+ modify(element, positional, {errors, property, hasValidated, errorClass = ERROR_CLASS, successClass = SUCCESS_CLASS}) {
+ const hasError = this.hasError(errors, property, hasValidated);
+
+ let validationClass = '';
+
+ if (!property || hasValidated?.includes(property)) {
+ validationClass = hasError ? errorClass : successClass;
+ }
element.classList.remove(errorClass);
element.classList.remove(successClass);
@@ -16,16 +22,6 @@ export default class ValidationStatusModifier extends Modifier {
}
}
- errorClass(errors, property, hasValidated) {
- const hasError = this.hasError(errors, property, hasValidated);
-
- if (hasValidated && hasValidated.includes(property)) {
- return hasError ? errorClass : successClass;
- } else {
- return '';
- }
- }
-
hasError(errors, property, hasValidated) {
// if we aren't looking at a specific property we always want an error class
if (!property && errors && !errors.get('isEmpty')) {
diff --git a/ghost/admin/tests/integration/modifiers/validation-status-test.js b/ghost/admin/tests/integration/modifiers/validation-status-test.js
new file mode 100644
index 0000000000..fe12a2aab4
--- /dev/null
+++ b/ghost/admin/tests/integration/modifiers/validation-status-test.js
@@ -0,0 +1,129 @@
+import DS from 'ember-data'; // eslint-disable-line
+import EmberObject from '@ember/object';
+import hbs from 'htmlbars-inline-precompile';
+import {expect} from 'chai';
+import {find, render} from '@ember/test-helpers';
+import {settled} from '@ember/test-helpers';
+import {setupRenderingTest} from 'ember-mocha';
+
+const {Errors} = DS;
+
+describe('Integration: Modifier: validation-status', function () {
+ setupRenderingTest();
+
+ this.beforeEach(function () {
+ let testObject = EmberObject.create();
+ testObject.name = 'Test';
+ testObject.hasValidated = [];
+ testObject.errors = Errors.create();
+
+ this.set('testObject', testObject);
+ });
+
+ it('handles missing params', async function () {
+ await render(hbs`