mirror of
https://github.com/discourse/discourse.git
synced 2026-08-01 17:18:15 -05:00
FEATURE: add composer form template field type (#31584)
Adds a "composer" form template field type.
This commit is contained in:
@@ -69,4 +69,14 @@
|
||||
font-size: var(--font-down-1);
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
|
||||
&__composer {
|
||||
// same default effective height (150px) than a text control
|
||||
height: 189px;
|
||||
width: 100%;
|
||||
|
||||
.d-editor-preview-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7930,6 +7930,7 @@ en:
|
||||
upload: "Upload a file"
|
||||
multiselect: "Multiple choice"
|
||||
tagchooser: "Tag Group selector"
|
||||
composer: "Markdown answer"
|
||||
validations_modal:
|
||||
button_title: "Validations"
|
||||
modal_title: "Validation Options"
|
||||
|
||||
@@ -54,6 +54,10 @@ export default class FormTemplateForm extends Component {
|
||||
type: "tagchooser",
|
||||
icon: "bullseye",
|
||||
},
|
||||
{
|
||||
type: "composer",
|
||||
icon: "fab-markdown",
|
||||
},
|
||||
];
|
||||
|
||||
get disablePreviewButton() {
|
||||
|
||||
@@ -85,4 +85,11 @@ export const templateFormFields = [
|
||||
validations:
|
||||
# ${i18n("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
{
|
||||
type: "composer",
|
||||
structure: `- type: composer
|
||||
id: ${i18n("admin.form_templates.field_placeholders.id")}
|
||||
attributes:
|
||||
label: "${i18n("admin.form_templates.field_placeholders.label")}"`,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -158,10 +158,10 @@ export default class ComposerEditor extends Component {
|
||||
placeholder = `composer.${key}`;
|
||||
}
|
||||
|
||||
return applyValueTransformer(
|
||||
"composer-editor-reply-placeholder",
|
||||
placeholder,
|
||||
{ model: this.composer }
|
||||
return i18n(
|
||||
applyValueTransformer("composer-editor-reply-placeholder", placeholder, {
|
||||
model: this.composer,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -154,14 +154,6 @@ export default class DEditor extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
@discourseComputed("placeholder")
|
||||
placeholderTranslated(placeholder) {
|
||||
if (placeholder) {
|
||||
return i18n(placeholder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@discourseComputed("siteSettings.rich_editor", "forceEditorMode")
|
||||
showEditorModeToggle() {
|
||||
return this.siteSettings.rich_editor && isNone(this.forceEditorMode);
|
||||
@@ -833,7 +825,7 @@ export default class DEditor extends Component {
|
||||
@markdownOptions={{this.markdownOptions}}
|
||||
@keymap={{this.keymap}}
|
||||
@value={{this.value}}
|
||||
@placeholder={{this.placeholderTranslated}}
|
||||
@placeholder={{@placeholder}}
|
||||
@disabled={{this.disabled}}
|
||||
@change={{this.onChange}}
|
||||
@focusIn={{this.handleFocusIn}}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
import { next } from "@ember/runloop";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import DEditor from "discourse/components/d-editor";
|
||||
import icon from "discourse/helpers/d-icon";
|
||||
|
||||
export default class FormTemplateFieldComposer extends Component {
|
||||
@tracked composerValue = this.args.value || "";
|
||||
|
||||
@action
|
||||
handleInput(event) {
|
||||
this.composerValue = event.target.value;
|
||||
next(this, () => {
|
||||
this.args.onChange?.(event);
|
||||
});
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="control-group form-template-field" data-field-type="composer">
|
||||
{{#if @attributes.label}}
|
||||
<label class="form-template-field__label">
|
||||
{{@attributes.label}}
|
||||
{{#if @validations.required}}
|
||||
{{icon "asterisk" class="form-template-field__required-indicator"}}
|
||||
{{/if}}
|
||||
</label>
|
||||
{{/if}}
|
||||
|
||||
{{#if @attributes.description}}
|
||||
<span class="form-template-field__description">
|
||||
{{htmlSafe @attributes.description}}
|
||||
</span>
|
||||
{{/if}}
|
||||
<input type="hidden" name={{@id}} value={{this.composerValue}} />
|
||||
<DEditor
|
||||
class="form-template-field__composer"
|
||||
@value={{this.composerValue}}
|
||||
@change={{this.handleInput}}
|
||||
@placeholder={{@attributes.placeholder}}
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { service } from "@ember/service";
|
||||
import Yaml from "js-yaml";
|
||||
import FormTemplate from "discourse/models/form-template";
|
||||
import CheckboxField from "./checkbox";
|
||||
import ComposerField from "./composer";
|
||||
import DropdownField from "./dropdown";
|
||||
import InputField from "./input";
|
||||
import MultiSelectField from "./multi-select";
|
||||
@@ -42,6 +43,7 @@ export default class FormTemplateFieldWrapper extends Component {
|
||||
textarea: TextareaField,
|
||||
"tag-chooser": TagChooserField,
|
||||
upload: UploadField,
|
||||
composer: ComposerField,
|
||||
};
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -161,7 +161,7 @@ export default class PostTranslationEditor extends Component {
|
||||
class="translation-editor"
|
||||
@value={{readonly this.composer.model.reply}}
|
||||
@change={{this.handleInput}}
|
||||
@placeholder="composer.translations.placeholder"
|
||||
@placeholder={{i18n "composer.translations.placeholder"}}
|
||||
@extraButtons={{@extraButtons}}
|
||||
@forcePreview={{true}}
|
||||
@processPreview={{false}}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
class FormTemplateYamlValidator < ActiveModel::Validator
|
||||
RESERVED_KEYWORDS = %w[title body category category_id tags]
|
||||
ALLOWED_TYPES = %w[checkbox dropdown input multi-select textarea upload tag-chooser]
|
||||
ALLOWED_TYPES = %w[checkbox dropdown input multi-select textarea upload tag-chooser composer]
|
||||
HTML_SANITIZATION_OPTIONS = {
|
||||
elements: ["a"],
|
||||
attributes: {
|
||||
|
||||
@@ -126,6 +126,11 @@ describe "Composer Form Templates", type: :system do
|
||||
attributes:
|
||||
none_label: "Select an item"
|
||||
label: "multi-select"
|
||||
- type: composer
|
||||
id: 7
|
||||
attributes:
|
||||
label: "composer"
|
||||
placeholder: "Enter rich text here"
|
||||
),
|
||||
)
|
||||
end
|
||||
@@ -538,12 +543,17 @@ describe "Composer Form Templates", type: :system do
|
||||
expect(page).to have_css(".d-editor-preview", text: "Option 4")
|
||||
|
||||
message = "This is a test message!"
|
||||
find("textarea").fill_in(with: message)
|
||||
composer.fill_form_template_field("textarea", message)
|
||||
|
||||
expect(page).to have_css(".d-editor-preview", text: message)
|
||||
|
||||
attach_file("5-uploader", "#{Rails.root}/spec/fixtures/images/logo.png", make_visible: true)
|
||||
expect(page).to have_css(".d-editor-preview img")
|
||||
|
||||
composer_message = "This is **bold** composer content"
|
||||
composer.fill_form_template_field("composer", composer_message)
|
||||
|
||||
expect(page).to have_css(".d-editor-preview", text: "This is bold composer content")
|
||||
end
|
||||
|
||||
context "when using tagchooser" do
|
||||
|
||||
Reference in New Issue
Block a user