mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Define form template field inputs (#20430)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<div class="form-templates--form">
|
||||
<div class="form-templates__form">
|
||||
<div class="control-group">
|
||||
<label for="template-name">
|
||||
{{i18n "admin.form_templates.new_template_form.name.label"}}
|
||||
@@ -6,24 +6,38 @@
|
||||
<TextField
|
||||
@value={{this.templateName}}
|
||||
@name="template-name"
|
||||
@class="form-templates--form-name-input"
|
||||
@class="form-templates__form-name-input"
|
||||
@placeholderKey="admin.form_templates.new_template_form.name.placeholder"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="control-group form-templates--quick-insert-field-buttons">
|
||||
<span>
|
||||
{{I18n "admin.form_templates.quick_insert_fields.add_new_field"}}
|
||||
</span>
|
||||
{{#each this.quickInsertFields as |field|}}
|
||||
<div class="control-group form-templates__editor">
|
||||
<div class="form-templates__quick-insert-field-buttons">
|
||||
<span>
|
||||
{{I18n "admin.form_templates.quick_insert_fields.add_new_field"}}
|
||||
</span>
|
||||
{{#each this.quickInsertFields as |field|}}
|
||||
<DButton
|
||||
@class="btn-flat btn-icon-text quick-insert-{{field.type}}"
|
||||
@icon={{field.icon}}
|
||||
@label="admin.form_templates.quick_insert_fields.{{field.type}}"
|
||||
@action={{this.onInsertField}}
|
||||
@actionParam={{field.type}}
|
||||
/>
|
||||
{{/each}}
|
||||
<DButton
|
||||
@class="btn-flat btn-icon-text quick-insert-{{field.type}}"
|
||||
@icon={{field.icon}}
|
||||
@label="admin.form_templates.quick_insert_fields.{{field.type}}"
|
||||
@action={{this.onInsertField}}
|
||||
@actionParam={{field.type}}
|
||||
class="btn-flat btn-icon-text form-templates__validations-modal-button"
|
||||
@label="admin.form_templates.validations_modal.button_title"
|
||||
@icon="check-circle"
|
||||
@action={{this.showValidationOptionsModal}}
|
||||
/>
|
||||
{{/each}}
|
||||
</div>
|
||||
<DButton
|
||||
@class="form-templates__preview-button"
|
||||
@icon="eye"
|
||||
@label="admin.form_templates.new_template_form.preview"
|
||||
@action={{this.showPreview}}
|
||||
@disabled={{this.disablePreviewButton}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
@@ -36,7 +50,7 @@
|
||||
@label="admin.form_templates.new_template_form.submit"
|
||||
@icon="check"
|
||||
@action={{this.onSubmit}}
|
||||
@disabled={{this.formSubmitted}}
|
||||
@disabled={{this.disableSubmitButton}}
|
||||
/>
|
||||
|
||||
<DButton
|
||||
|
||||
@@ -6,14 +6,15 @@ import I18n from "I18n";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { templateFormFields } from "admin/lib/template-form-fields";
|
||||
import FormTemplate from "admin/models/form-template";
|
||||
import showModal from "discourse/lib/show-modal";
|
||||
|
||||
export default class FormTemplateForm extends Component {
|
||||
@service router;
|
||||
@service dialog;
|
||||
@tracked formSubmitted = false;
|
||||
@tracked templateContent = this.args.model?.template || "";
|
||||
@tracked templateName = this.args.model?.name || "";
|
||||
isEditing = this.args.model?.id ? true : false;
|
||||
templateName = this.args.model?.name;
|
||||
quickInsertFields = [
|
||||
{
|
||||
type: "checkbox",
|
||||
@@ -41,6 +42,17 @@ export default class FormTemplateForm extends Component {
|
||||
},
|
||||
];
|
||||
|
||||
get disablePreviewButton() {
|
||||
return Boolean(!this.templateName.length || !this.templateContent.length);
|
||||
}
|
||||
|
||||
get disableSubmitButton() {
|
||||
return (
|
||||
Boolean(!this.templateName.length || !this.templateContent.length) ||
|
||||
this.formSubmitted
|
||||
);
|
||||
}
|
||||
|
||||
@action
|
||||
onSubmit() {
|
||||
if (!this.formSubmitted) {
|
||||
@@ -54,27 +66,17 @@ export default class FormTemplateForm extends Component {
|
||||
|
||||
if (this.isEditing) {
|
||||
postData["id"] = this.args.model.id;
|
||||
|
||||
FormTemplate.updateTemplate(this.args.model.id, postData)
|
||||
.then(() => {
|
||||
this.formSubmitted = false;
|
||||
this.router.transitionTo("adminCustomizeFormTemplates.index");
|
||||
})
|
||||
.catch((e) => {
|
||||
popupAjaxError(e);
|
||||
this.formSubmitted = false;
|
||||
});
|
||||
} else {
|
||||
FormTemplate.createTemplate(postData)
|
||||
.then(() => {
|
||||
this.formSubmitted = false;
|
||||
this.router.transitionTo("adminCustomizeFormTemplates.index");
|
||||
})
|
||||
.catch((e) => {
|
||||
popupAjaxError(e);
|
||||
this.formSubmitted = false;
|
||||
});
|
||||
}
|
||||
|
||||
FormTemplate.createOrUpdateTemplate(postData)
|
||||
.then(() => {
|
||||
this.formSubmitted = false;
|
||||
this.router.transitionTo("adminCustomizeFormTemplates.index");
|
||||
})
|
||||
.catch((e) => {
|
||||
popupAjaxError(e);
|
||||
this.formSubmitted = false;
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
@@ -106,4 +108,33 @@ export default class FormTemplateForm extends Component {
|
||||
this.templateContent += `\n${structure}`;
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
showValidationOptionsModal() {
|
||||
return showModal("admin-form-template-validation-options", {
|
||||
admin: true,
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
showPreview() {
|
||||
const data = {
|
||||
name: this.templateName,
|
||||
template: this.templateContent,
|
||||
};
|
||||
|
||||
if (this.isEditing) {
|
||||
data["id"] = this.args.model.id;
|
||||
}
|
||||
|
||||
FormTemplate.validateTemplate(data)
|
||||
.then(() => {
|
||||
return showModal("form-template-form-preview", {
|
||||
model: {
|
||||
content: this.templateContent,
|
||||
},
|
||||
});
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ export default class FormTemplateRowItem extends Component {
|
||||
|
||||
@action
|
||||
viewTemplate() {
|
||||
showModal("admin-customize-form-template-view", {
|
||||
admin: true,
|
||||
showModal("customize-form-template-view", {
|
||||
model: this.args.template,
|
||||
refreshModel: this.args.refreshModel,
|
||||
});
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import { action } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import I18n from "I18n";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
|
||||
export default class AdminCustomizeFormTemplateView extends Controller.extend(
|
||||
ModalFunctionality
|
||||
) {
|
||||
@service router;
|
||||
@service dialog;
|
||||
|
||||
@action
|
||||
editTemplate() {
|
||||
this.router.transitionTo("adminCustomizeFormTemplates.edit", this.model);
|
||||
}
|
||||
|
||||
@action
|
||||
deleteTemplate() {
|
||||
return this.dialog.yesNoConfirm({
|
||||
message: I18n.t("admin.form_templates.delete_confirm", {
|
||||
template_name: this.model.name,
|
||||
}),
|
||||
didConfirm: () => {
|
||||
ajax(`/admin/customize/form-templates/${this.model.id}.json`, {
|
||||
type: "DELETE",
|
||||
})
|
||||
.then(() => {
|
||||
this.refreshModel();
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import Controller from "@ember/controller";
|
||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default class AdminFormTemplateValidationOptions extends Controller.extend(
|
||||
ModalFunctionality
|
||||
) {
|
||||
TABLE_HEADER_KEYS = ["key", "type", "description"];
|
||||
VALIDATION_KEYS = ["required", "minimum", "maximum", "pattern"];
|
||||
|
||||
get tableHeaders() {
|
||||
const translatedHeaders = [];
|
||||
this.TABLE_HEADER_KEYS.forEach((header) => {
|
||||
translatedHeaders.push(
|
||||
I18n.t(`admin.form_templates.validations_modal.table_headers.${header}`)
|
||||
);
|
||||
});
|
||||
|
||||
return translatedHeaders;
|
||||
}
|
||||
|
||||
get validations() {
|
||||
const translatedValidations = [];
|
||||
const prefix = "admin.form_templates.validations_modal.validations";
|
||||
this.VALIDATION_KEYS.forEach((validation) => {
|
||||
translatedValidations.push({
|
||||
key: I18n.t(`${prefix}.${validation}.key`),
|
||||
type: I18n.t(`${prefix}.${validation}.type`),
|
||||
description: I18n.t(`${prefix}.${validation}.description`),
|
||||
});
|
||||
});
|
||||
|
||||
return translatedValidations;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,75 @@
|
||||
// TODO(@keegan): Add translations for template strings
|
||||
import I18n from "I18n";
|
||||
|
||||
export const templateFormFields = [
|
||||
{
|
||||
type: "checkbox",
|
||||
structure: `- type: checkbox
|
||||
choices:
|
||||
- "Option 1"
|
||||
- "Option 2"
|
||||
- "Option 3"
|
||||
attributes:
|
||||
label: "Enter question here"
|
||||
description: "Enter description here"
|
||||
validations:
|
||||
required: true`,
|
||||
label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
|
||||
validations:
|
||||
# ${I18n.t("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
structure: `- type: input
|
||||
attributes:
|
||||
label: "Enter input label here"
|
||||
description: "Enter input description here"
|
||||
placeholder: "Enter input placeholder here"
|
||||
validations:
|
||||
required: true`,
|
||||
label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
|
||||
placeholder: "${I18n.t(
|
||||
"admin.form_templates.field_placeholders.placeholder"
|
||||
)}"
|
||||
validations:
|
||||
# ${I18n.t("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
{
|
||||
type: "textarea",
|
||||
structure: `- type: textarea
|
||||
attributes:
|
||||
label: "Enter textarea label here"
|
||||
description: "Enter textarea description here"
|
||||
placeholder: "Enter textarea placeholder here"
|
||||
validations:
|
||||
required: true`,
|
||||
label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
|
||||
placeholder: "${I18n.t(
|
||||
"admin.form_templates.field_placeholders.placeholder"
|
||||
)}"
|
||||
validations:
|
||||
# ${I18n.t("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
{
|
||||
type: "dropdown",
|
||||
structure: `- type: dropdown
|
||||
choices:
|
||||
- "Option 1"
|
||||
- "Option 2"
|
||||
- "Option 3"
|
||||
- "${I18n.t("admin.form_templates.field_placeholders.choices.first")}"
|
||||
- "${I18n.t("admin.form_templates.field_placeholders.choices.second")}"
|
||||
- "${I18n.t("admin.form_templates.field_placeholders.choices.third")}"
|
||||
attributes:
|
||||
label: "Enter dropdown label here"
|
||||
description: "Enter dropdown description here"
|
||||
validations:
|
||||
required: true`,
|
||||
none_label: "${I18n.t(
|
||||
"admin.form_templates.field_placeholders.none_label"
|
||||
)}"
|
||||
label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
|
||||
filterable: false
|
||||
validations:
|
||||
# ${I18n.t("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
{
|
||||
type: "upload",
|
||||
structure: `- type: upload
|
||||
attributes:
|
||||
file_types: "jpg, png, gif"
|
||||
label: "Enter upload label here"
|
||||
description: "Enter upload description here"`,
|
||||
allow_multiple: false
|
||||
label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
|
||||
validations:
|
||||
# ${I18n.t("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
{
|
||||
type: "multiselect",
|
||||
structure: `- type: multiple_choice
|
||||
structure: `- type: multi-select
|
||||
choices:
|
||||
- "Option 1"
|
||||
- "Option 2"
|
||||
- "Option 3"
|
||||
- "${I18n.t("admin.form_templates.field_placeholders.choices.first")}"
|
||||
- "${I18n.t("admin.form_templates.field_placeholders.choices.second")}"
|
||||
- "${I18n.t("admin.form_templates.field_placeholders.choices.third")}"
|
||||
attributes:
|
||||
label: "Enter multiple choice label here"
|
||||
description: "Enter multiple choice description here"
|
||||
validations:
|
||||
required: true`,
|
||||
none_label: "${I18n.t(
|
||||
"admin.form_templates.field_placeholders.none_label"
|
||||
)}"
|
||||
label: "${I18n.t("admin.form_templates.field_placeholders.label")}"
|
||||
validations:
|
||||
# ${I18n.t("admin.form_templates.field_placeholders.validations")}`,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -18,6 +18,14 @@ FormTemplate.reopenClass({
|
||||
});
|
||||
},
|
||||
|
||||
createOrUpdateTemplate(data) {
|
||||
if (data.id) {
|
||||
return this.updateTemplate(data.id, data);
|
||||
} else {
|
||||
return this.createTemplate(data);
|
||||
}
|
||||
},
|
||||
|
||||
deleteTemplate(id) {
|
||||
return ajax(`/admin/customize/form-templates/${id}.json`, {
|
||||
type: "DELETE",
|
||||
@@ -35,4 +43,11 @@ FormTemplate.reopenClass({
|
||||
return model.form_template;
|
||||
});
|
||||
},
|
||||
|
||||
validateTemplate(data) {
|
||||
return ajax(`/admin/customize/form-templates/preview.json`, {
|
||||
type: "GET",
|
||||
data,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<FormTemplate::InfoHeader />
|
||||
|
||||
{{#if this.model}}
|
||||
<table class="form-templates--table grid">
|
||||
<table class="form-templates__table grid">
|
||||
<thead>
|
||||
<th class="col heading">
|
||||
{{i18n "admin.form_templates.list_table.headings.name"}}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<DModalBody @rawTitle={{this.model.name}}>
|
||||
<HighlightedCode @lang="yaml" @code={{this.model.template}} />
|
||||
{{! ? TODO(@keegan): Perhaps add what places (ex. categories) the templates are active in }}
|
||||
</DModalBody>
|
||||
<div class="modal-footer">
|
||||
<DButton
|
||||
class="btn-primary"
|
||||
@action={{this.editTemplate}}
|
||||
@icon="pencil-alt"
|
||||
@label="admin.form_templates.view_template.edit"
|
||||
/>
|
||||
<DButton
|
||||
@action={{route-action "closeModal"}}
|
||||
@label="admin.form_templates.view_template.close"
|
||||
/>
|
||||
<DButton
|
||||
class="btn-danger"
|
||||
@action={{this.deleteTemplate}}
|
||||
@icon="trash-alt"
|
||||
@label="admin.form_templates.view_template.delete"
|
||||
/>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
<DModalBody
|
||||
@class="form-templates__validation-options"
|
||||
@title="admin.form_templates.validations_modal.modal_title"
|
||||
>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{{#each this.tableHeaders as |header|}}
|
||||
<th>{{header}}</th>
|
||||
{{/each}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each this.validations as |item|}}
|
||||
<tr>
|
||||
<td><pre>{{item.key}}</pre></td>
|
||||
<td>{{item.type}}</td>
|
||||
<td>{{item.description}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</DModalBody>
|
||||
Reference in New Issue
Block a user