Updated inlined feedback form (#16794)

refs TryGhost/Team#3214

---

<!-- Leave the line below if you'd like GitHub Copilot to generate a
summary from your commit -->
<!--
copilot:summary
-->
### <samp>🤖 Generated by Copilot at 92b2412</samp>

This pull request refactors and simplifies the feedback system for the
lexical editor feature. It replaces the nested modal with a new
`FeedbackLexical` component that can be used in different contexts. It
also removes unused code and files related to the old feedback modal.
This commit is contained in:
Elena Baidakova 2023-05-16 16:16:57 +04:00 committed by GitHub
parent dc480b107a
commit 57d5f544d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 134 additions and 157 deletions

View File

@ -96,30 +96,8 @@
</button>
</p>
{{else}}
{{!-- Inlined beta feedback form --}}
{{#if (feature 'lexicalEditor')}}
{{!-- <div class="gh-feedback-grey">
<h4 class="gh-feedback-grey-title">Hey, noticed anything different?</h4>
<p>This post was successfully published using our new editor. Have any issues? Feedback? Let us know!</p>
<form>
<GhFormGroup>
<label for="feedback-lexical">Feedback</label>
<GhTextarea
@id="feedback-lexical"
@name="feedback-lexical"
@value={{this.feedbackMessage}}
@placeholder="I've noticed that..."
data-test-lexical-feedback-textarea
/>
</GhFormGroup>
</form>
<GhTaskButton
@buttonText="Send feedback"
@task={{this.submitFeedback}}
@class="gh-btn gh-btn-black gh-btn-icon"
data-test-button="submit-lexical-feedback"
/>
</div> --}}
<FeedbackLexical::PostCompleteForm @post={{@publishOptions.post}} />
{{/if}}
<p class="gh-publish-confirmation gh-publish-confirmation-with-feedback">
<button
@ -130,18 +108,7 @@
>
<span>Back to editor</span>
</button>
{{!-- Trigger beta feedback modal --}}
{{#if (feature 'lexicalEditor')}}
<button
type="button"
class="gh-publish-confirmation-feedback"
{{on "click" this.openFeedbackLexical}}
data-test-button="lexical-feedback"
>
<span>Beta feedback?</span>
</button>
{{/if}}
</p>
{{/if}}
{{/if}}
{{/let}}
{{/let}}

View File

@ -1,16 +0,0 @@
import Component from '@glimmer/component';
import FeedbackLexicalModal from '../../../modal-feedback-lexical';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking';
export default class PublishFlowComplete extends Component {
@service modals;
@tracked showFeedbackLexicalModal = false;
@action
async openFeedbackLexical() {
await this.modals.open(FeedbackLexicalModal, {post: this.args.publishOptions.post});
}
}

View File

@ -0,0 +1,24 @@
<div class="gh-editor-feedback-dropdown" data-test-modal="lexical-feedback">
<header class="gh-editor-feedback-dropdown-header">
<h3>Editor beta feedback</h3>
</header>
{{!-- <button class="close" type="button" title="Close" {{on "click" this.closeModal}}>{{svg-jar "close"}}<span
class="hidden">Close</span></button> --}}
<div class="">
<p>Have any issues? Feedback? Let us know!</p>
<FeedbackLexical::Textarea
@feedbackMessage={{this.feedbackMessage}}
@updateFeedbackMessage={{this.updateFeedbackMessage}}
/>
</div>
<div class="gh-editor-feedback-dropdown-footer">
<FeedbackLexical::SendButton
@onSuccess={{this.closeModal}}
@feedbackMessage={{this.feedbackMessage}}
@post={{@post}}
/>
<button class="gh-btn" type="button" {{on "click" this.closeModal}}><span>Cancel</span></button>
</div>
</div>

View File

@ -0,0 +1,17 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
import {tracked} from '@glimmer/tracking';
export default class FeedbackLexicalEditorFormComponent extends Component {
@tracked feedbackMessage = '';
@action
closeModal() {
this.args.close();
}
@action
updateFeedbackMessage(event) {
this.feedbackMessage = event.target.value;
}
}

View File

@ -0,0 +1,10 @@
<FeedbackLexical::Textarea
@feedbackMessage={{this.feedbackMessage}}
@updateFeedbackMessage={{this.updateFeedbackMessage}}
@label="Have any issues? Feedback? Let us know below!"
/>
<FeedbackLexical::SendButton
@onSuccess={{this.closeModal}}
@feedbackMessage={{this.feedbackMessage}}
/>

View File

@ -0,0 +1,12 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
import {tracked} from '@glimmer/tracking';
export default class FeedbackLexicalLabsFormComponent extends Component {
@tracked feedbackMessage = '';
@action
updateFeedbackMessage(event) {
this.feedbackMessage = event.target.value;
}
}

View File

@ -0,0 +1,13 @@
<div class="gh-feedback-grey">
<h4 class="gh-feedback-grey-title">Hey, noticed anything different?</h4>
<p>This post was successfully published using our new editor. Have any issues? Feedback? Let us know!</p>
<FeedbackLexical::Textarea
@feedbackMessage={{this.feedbackMessage}}
@updateFeedbackMessage={{this.updateFeedbackMessage}}
@label="Feedback"
/>
<FeedbackLexical::SendButton
@feedbackMessage={{this.feedbackMessage}}
@post={{@post}}
/>
</div>

View File

@ -0,0 +1,12 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
import {tracked} from '@glimmer/tracking';
export default class FeedbackLexicalPostCompleteFormComponent extends Component {
@tracked feedbackMessage = '';
@action
updateFeedbackMessage(event) {
this.feedbackMessage = event.target.value;
}
}

View File

@ -0,0 +1,6 @@
<GhTaskButton
@buttonText="Send feedback"
@task={{this.submitFeedback}}
@class="gh-btn gh-btn-black gh-btn-icon"
data-test-button="submit-lexical-feedback"
/>

View File

@ -1,10 +1,9 @@
import Component from '@glimmer/component';
import {action} from '@ember/object';
import {inject} from 'ghost-admin/decorators/inject';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
export default class FeedbackLexicalModalComponent extends Component {
export default class FeedbackLexicalSendButtonComponent extends Component {
@service ajax;
@service ghostPaths;
@service session;
@ -12,25 +11,15 @@ export default class FeedbackLexicalModalComponent extends Component {
@inject config;
constructor(...args) {
super(...args);
this.feedbackMessage = this.args.feedbackMessage;
}
@action
closeModal() {
this.args.close();
}
@task({drop: true})
*submitFeedback() {
let url = `https://submit-form.com/us6uBWv8`;
let postData;
if (this.args.data?.post) {
if (this.args?.post) {
postData = {
PostId: this.args.data.post?.id,
PostTitle: this.args.data.post?.title
PostId: this.args.post?.id,
PostTitle: this.args.post?.title
};
}
@ -41,7 +30,7 @@ export default class FeedbackLexicalModalComponent extends Component {
StaffAccessLevel: this.session.user.role?.description,
UserAgent: navigator.userAgent,
Version: this.config.version,
Feedback: this.feedbackMessage
Feedback: this.args.feedbackMessage
};
let data = {
@ -55,7 +44,7 @@ export default class FeedbackLexicalModalComponent extends Component {
throw new Error('api failed ' + response.status + ' ' + response.statusText);
}
this.args.close();
this.args.onSuccess?.();
this.notifications.showNotification('Feedback sent',
{
@ -66,4 +55,4 @@ export default class FeedbackLexicalModalComponent extends Component {
return response;
}
}
}

View File

@ -0,0 +1,20 @@
<form>
<GhFormGroup>
{{#if @label}}
<label for="feedback-lexical">{{@label}}</label>
{{/if}}
<GhTextarea
@id="feedback-lexical"
@name="feedback-lexical"
@value={{@feedbackMessage}}
@placeholder="I've noticed that..."
@shouldFocus={{true}}
data-test-lexical-feedback-textarea
{{on "input" @updateFeedbackMessage}}
/>
{{!--
<GhErrorMessage @errors={{this.member.errors}} @property="note" /> --}}
{{!-- <p> Maximum: <b>500</b> characters. Youve used
{{gh-count-down-characters this.feedbackMessage 500}}</p> --}}
</GhFormGroup>
</form>

View File

@ -1,38 +0,0 @@
<div class="{{@class}}" data-test-modal="lexical-feedback">
<header class="gh-editor-feedback-dropdown-header">
<h3>Editor beta feedback</h3>
</header>
{{!-- <button class="close" type="button" title="Close" {{on "click" this.closeModal}}>{{svg-jar "close"}}<span
class="hidden">Close</span></button> --}}
<div class="">
<p>Have any issues? Feedback? Let us know!</p>
<form>
<GhFormGroup>
{{!-- <label for="feedback-lexical">Have any issues? Feedback? Let us know below!</label> --}}
<GhTextarea
@id="feedback-lexical"
@name="feedback-lexical"
@value={{this.feedbackMessage}}
@placeholder="I've noticed that..."
@shouldFocus={{true}}
data-test-lexical-feedback-textarea
/>
{{!--
<GhErrorMessage @errors={{this.member.errors}} @property="note" /> --}}
{{!-- <p> Maximum: <b>500</b> characters. Youve used
{{gh-count-down-characters this.feedbackMessage 500}}</p> --}}
</GhFormGroup>
</form>
</div>
<div class="gh-editor-feedback-dropdown-footer">
<GhTaskButton
@buttonText="Send feedback"
@task={{this.submitFeedback}}
@class="gh-btn gh-btn-black gh-btn-icon"
data-test-button="submit-lexical-feedback"
/>
<button class="gh-btn" type="button" {{on "click" this.closeModal}}><span>Cancel</span></button>
</div>
</div>

View File

@ -3,7 +3,6 @@ import {inject as service} from '@ember/service';
/* eslint-disable ghost/ember/alias-model-in-controller */
import Controller from '@ember/controller';
import DeleteAllModal from '../../components/settings/labs/delete-all-content-modal';
import FeedbackLexicalModal from '../../components/modal-feedback-lexical';
import ImportContentModal from '../../components/modal-import-content';
import RSVP from 'rsvp';
import config from 'ghost-admin/config/environment';
@ -18,7 +17,6 @@ import {isBlank} from '@ember/utils';
import {isArray as isEmberArray} from '@ember/array';
import {run} from '@ember/runloop';
import {task, timeout} from 'ember-concurrency';
import {tracked} from '@glimmer/tracking';
const {Promise} = RSVP;
@ -52,8 +50,6 @@ export default class LabsController extends Controller {
@inject config;
@tracked showFeedbackLexicalModal = false;
importErrors = null;
importSuccessful = false;
showEarlyAccessModal = false;
@ -164,11 +160,6 @@ export default class LabsController extends Controller {
this.toggleProperty('showEarlyAccessModal');
}
@action
async openFeedbackLexical() {
await this.modals.open(FeedbackLexicalModal);
}
/**
* Opens a file selection dialog - Triggered by "Upload x" buttons,
* searches for the hidden file input within the .gh-setting element

View File

@ -109,7 +109,10 @@
<dd.Content class="gh-editor-feedback-dropdown-container">
<div {{css-transition "anim-fade-in-scale"}}>
<ModalFeedbackLexical @class="gh-editor-feedback-dropdown" @close={{dd.actions.close}} />
<FeedbackLexical::EditorForm
@post={{this.post}}
@close={{dd.actions.close}}
/>
</div>
</dd.Content>
</GhBasicDropdown>

View File

@ -213,28 +213,7 @@
<GhFeatureFlag @flag="lexicalEditor" />
</div>
</div>
{{!-- Inlined feedback form --}}
{{!-- <div>
<form>
<GhFormGroup>
<label for="feedback-lexical">Have any issues? Feedback? Let us know below!</label>
<GhTextarea
@id="feedback-lexical"
@name="feedback-lexical"
@value={{this.feedbackMessage}}
@placeholder="I've noticed that..."
@shouldFocus={{true}}
data-test-lexical-feedback-textarea
/>
</GhFormGroup>
</form>
<GhTaskButton
@buttonText="Send feedback"
@task={{this.submitFeedback}}
@class="gh-btn gh-btn-black gh-btn-icon"
data-test-button="submit-lexical-feedback"
/>
</div> --}}
<FeedbackLexical::LabsForm />
</div>
<div class="gh-expandable-block">
<div class="gh-expandable-header">

View File

@ -314,27 +314,18 @@ describe('Acceptance: Settings - Labs', function () {
expect(iframe.getAttribute('src')).to.have.string('/settings/routes/yaml/');
});
it('displays lexical feedback button when the labs setting is enabled', async function () {
it('displays lexical feedback textarea when the labs setting is enabled', async function () {
enableLabsFlag(this.server, 'lexicalEditor');
await visit('/settings/labs');
expect(find('[data-test-button="lexical-feedback"]')).to.exist;
expect(find('[data-test-lexical-feedback-textarea]')).to.exist;
});
it('does not display lexical feedback button when the labs setting is disabled', async function () {
it('does not display lexical feedback textarea when the labs setting is disabled', async function () {
await visit('/settings/labs');
expect(find('[data-test-button="lexical-feedback"]')).to.not.exist;
});
it('allows the user to launch the feedback modal', async function () {
enableLabsFlag(this.server, 'lexicalEditor');
await visit('/settings/labs');
await click('[data-test-button="lexical-feedback"]');
expect(find('[data-test-modal="lexical-feedback"]')).to.exist;
expect(find('[data-test-lexical-feedback-textarea]')).to.not.exist;
});
it('allows the user to send lexical feedback', async function () {
@ -344,14 +335,11 @@ describe('Acceptance: Settings - Labs', function () {
this.server.post('https://submit-form.com/us6uBWv8', {}, 200);
await visit('/settings/labs');
await click('[data-test-button="lexical-feedback"]');
expect(find('[data-test-modal="lexical-feedback"]')).to.exist;
await fillIn('[data-test-lexical-feedback-textarea]', 'This is test feedback');
await click('[data-test-button="submit-lexical-feedback"]');
// successful request will close the modal and show a notification toast
expect(find('[data-test-modal="lexical-feedback"]')).to.not.exist;
// successful request will show a notification toast
expect(find('[data-test-text="notification-content"]')).to.exist;
});
});