DEV: Use the new modal api (#26)
This commit is contained in:
parent
344f4dd0ea
commit
05a727efd5
|
@ -22,7 +22,7 @@ div.d-wrap[data-wrap="placeholder"] {
|
||||||
|
|
||||||
p,
|
p,
|
||||||
.discourse-placeholder-name {
|
.discourse-placeholder-name {
|
||||||
font-size: $font-down-1;
|
font-size: var(--font-down-1);
|
||||||
color: var(--primary-or-secondary);
|
color: var(--primary-or-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ div.d-wrap[data-wrap="placeholder"] {
|
||||||
.discourse-placeholder-value {
|
.discourse-placeholder-value {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
line-height: $line-height-small;
|
line-height: var(--line-height-small);
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
background-color: var(--secondary);
|
background-color: var(--secondary);
|
||||||
border: 1px solid var(--primary-medium);
|
border: 1px solid var(--primary-medium);
|
||||||
|
@ -50,19 +50,17 @@ div.d-wrap[data-wrap="placeholder"] {
|
||||||
.discourse-placeholder-select {
|
.discourse-placeholder-select {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
line-height: $line-height-small;
|
line-height: var(--line-height-small);
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
background-color: var(--secondary);
|
background-color: var(--secondary);
|
||||||
border: 1px solid var(--primary-medium);
|
border: 1px solid var(--primary-medium);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.discourse-placeholder-builder-modal {
|
.placeholder-builder {
|
||||||
.input {
|
.input input {
|
||||||
input {
|
margin: 0;
|
||||||
margin: 0;
|
width: 100%;
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.multi-select {
|
.multi-select {
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<DModal
|
||||||
|
@title={{i18n (theme-prefix "builder.title")}}
|
||||||
|
@closeModal={{@closeModal}}
|
||||||
|
@tagName="form"
|
||||||
|
class="placeholder-builder"
|
||||||
|
>
|
||||||
|
<:body>
|
||||||
|
<div class="control">
|
||||||
|
<span class="label">
|
||||||
|
{{theme-i18n "builder.key.label"}}
|
||||||
|
</span>
|
||||||
|
<div class="input">
|
||||||
|
<Input
|
||||||
|
{{on "input" this.updateKey}}
|
||||||
|
@value={{readonly form.key}}
|
||||||
|
class="placeholder-builder__key"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="description">{{theme-i18n "builder.key.description"}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control">
|
||||||
|
<span class="label">
|
||||||
|
{{theme-i18n "builder.description.label"}}
|
||||||
|
</span>
|
||||||
|
<div class="input">
|
||||||
|
<Input
|
||||||
|
{{on "input" this.updateDescription}}
|
||||||
|
@value={{readonly form.description}}
|
||||||
|
class="placeholder-builder__description"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="description">
|
||||||
|
{{theme-i18n "builder.description.description"}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control">
|
||||||
|
<span class="label">
|
||||||
|
{{theme-i18n "builder.values.label"}}
|
||||||
|
</span>
|
||||||
|
<div class="input">
|
||||||
|
<MultiSelect
|
||||||
|
@valueProperty={{null}}
|
||||||
|
@nameProperty={{null}}
|
||||||
|
@value={{form.values}}
|
||||||
|
@content={{form.values}}
|
||||||
|
@options={{hash allowAny=true placementStrategy="absolute"}}
|
||||||
|
@onChange={{fn (mut form.values)}}
|
||||||
|
class="placeholder-builder__default-values"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="description">{{theme-i18n "builder.values.description"}}</p>
|
||||||
|
</div>
|
||||||
|
</:body>
|
||||||
|
|
||||||
|
<:footer>
|
||||||
|
<DButton
|
||||||
|
@action={{this.insertPlaceholder}}
|
||||||
|
@label={{theme-prefix "builder.insert"}}
|
||||||
|
class="btn-primary"
|
||||||
|
/>
|
||||||
|
</:footer>
|
||||||
|
</DModal>
|
|
@ -0,0 +1,52 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import EmberObject, { action } from "@ember/object";
|
||||||
|
import { isBlank } from "@ember/utils";
|
||||||
|
import I18n from "I18n";
|
||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
|
||||||
|
export default class DiscoursePlaceholderBuilder extends Component {
|
||||||
|
@service dialog;
|
||||||
|
|
||||||
|
form = EmberObject.create({
|
||||||
|
key: null,
|
||||||
|
description: null,
|
||||||
|
values: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
@action
|
||||||
|
updateKey(event) {
|
||||||
|
this.form.set("key", event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
updateDescription(event) {
|
||||||
|
this.form.set("description", event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
insertPlaceholder() {
|
||||||
|
if (isBlank(this.form.key)) {
|
||||||
|
this.dialog.alert(I18n.t(themePrefix("builder.errors.no_key")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = `[wrap=placeholder key="${this.form.key}"`;
|
||||||
|
|
||||||
|
if (this.form.description) {
|
||||||
|
output += ` description="${this.form.description}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.form.values.length) {
|
||||||
|
if (this.form.values.length === 1) {
|
||||||
|
output += ` default="${this.form.values.firstObject}"`;
|
||||||
|
} else {
|
||||||
|
output += ` defaults="${this.form.values.join(",")}"`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output += "][/wrap]";
|
||||||
|
this.model.toolbarEvent.addText(output);
|
||||||
|
|
||||||
|
this.closeModal();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,50 +0,0 @@
|
||||||
import Controller from "@ember/controller";
|
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
|
||||||
import EmberObject, { action } from "@ember/object";
|
|
||||||
import { isBlank } from "@ember/utils";
|
|
||||||
import I18n from "I18n";
|
|
||||||
import { inject as service } from "@ember/service";
|
|
||||||
|
|
||||||
export default Controller.extend(ModalFunctionality, {
|
|
||||||
dialog: service(),
|
|
||||||
form: null,
|
|
||||||
|
|
||||||
onShow() {
|
|
||||||
this.set(
|
|
||||||
"form",
|
|
||||||
EmberObject.create({
|
|
||||||
key: null,
|
|
||||||
description: null,
|
|
||||||
values: [],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
onClose() {},
|
|
||||||
|
|
||||||
@action
|
|
||||||
insertPlaceholder() {
|
|
||||||
if (isBlank(this.form.key)) {
|
|
||||||
this.dialog.alert(I18n.t(themePrefix("builder.errors.no_key")));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let output = `[wrap=placeholder key="${this.form.key}"`;
|
|
||||||
|
|
||||||
if (this.form.description) {
|
|
||||||
output = `${output} description="${this.form.description}"`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.form.values.length) {
|
|
||||||
if (this.form.values.length === 1) {
|
|
||||||
output = `${output} default="${this.form.values.firstObject}"`;
|
|
||||||
} else {
|
|
||||||
output = `${output} defaults="${this.form.values.join(",")}"`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.model.toolbarEvent.addText(`${output}][/wrap]`);
|
|
||||||
|
|
||||||
this.send("closeModal");
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,6 +1,6 @@
|
||||||
import showModal from "discourse/lib/show-modal";
|
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
import { debounce, later } from "@ember/runloop";
|
import { debounce, later } from "@ember/runloop";
|
||||||
|
import DiscoursePlaceholderBuilder from "../components/modal/discourse-placeholder-builder";
|
||||||
|
|
||||||
const VALID_TAGS =
|
const VALID_TAGS =
|
||||||
"h1, h2, h3, h4, h5, h6, p, code, blockquote, .md-table, li p";
|
"h1, h2, h3, h4, h5, h6, p, code, blockquote, .md-table, li p";
|
||||||
|
@ -296,7 +296,8 @@ export default {
|
||||||
label: themePrefix("toolbar.builder"),
|
label: themePrefix("toolbar.builder"),
|
||||||
icon: "file",
|
icon: "file",
|
||||||
action: (toolbarEvent) => {
|
action: (toolbarEvent) => {
|
||||||
showModal("discourse-placeholder-builder", {
|
const modal = container.lookup("service:modal");
|
||||||
|
modal.show(DiscoursePlaceholderBuilder, {
|
||||||
model: {
|
model: {
|
||||||
toolbarEvent,
|
toolbarEvent,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
{{#d-modal-body
|
|
||||||
title=(theme-prefix "builder.title")
|
|
||||||
class="discourse-placeholder-builder"
|
|
||||||
style="overflow: auto"
|
|
||||||
}}
|
|
||||||
<form>
|
|
||||||
<div class="control">
|
|
||||||
<span class="label">
|
|
||||||
{{theme-i18n "builder.key.label"}}
|
|
||||||
</span>
|
|
||||||
<div class="input">
|
|
||||||
{{input
|
|
||||||
value=(readonly form.key)
|
|
||||||
input=(action (mut form.key) value="target.value")
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<p class="description">{{theme-i18n "builder.key.description"}}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control">
|
|
||||||
<span class="label">
|
|
||||||
{{theme-i18n "builder.description.label"}}
|
|
||||||
</span>
|
|
||||||
<div class="input">
|
|
||||||
{{input
|
|
||||||
value=(readonly form.description)
|
|
||||||
input=(action (mut form.description) value="target.value")
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<p class="description">
|
|
||||||
{{theme-i18n "builder.description.description"}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control">
|
|
||||||
<span class="label">
|
|
||||||
{{theme-i18n "builder.values.label"}}
|
|
||||||
</span>
|
|
||||||
<div class="input">
|
|
||||||
{{multi-select
|
|
||||||
valueProperty=null
|
|
||||||
nameProperty=null
|
|
||||||
value=form.values
|
|
||||||
content=form.values
|
|
||||||
options=(hash allowAny=true placementStrategy="absolute")
|
|
||||||
onChange=(action (mut form.values))
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<p class="description">{{theme-i18n "builder.values.description"}}</p>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{{/d-modal-body}}
|
|
||||||
|
|
||||||
<div class="modal-footer discourse-local-dates-create-modal-footer">
|
|
||||||
{{d-button
|
|
||||||
class="btn-primary"
|
|
||||||
action=(action "insertPlaceholder")
|
|
||||||
label=(theme-prefix "builder.insert")
|
|
||||||
}}
|
|
||||||
</div>
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { click, fillIn, visit } from "@ember/test-helpers";
|
||||||
|
import { test } from "qunit";
|
||||||
|
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||||
|
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
acceptance("Discourse Placeholder | Add a placeholder", function (needs) {
|
||||||
|
needs.user();
|
||||||
|
|
||||||
|
test("add a placeholder through the modal", async function (assert) {
|
||||||
|
await visit("/");
|
||||||
|
await click("#create-topic");
|
||||||
|
const categoryChooser = selectKit(".category-chooser");
|
||||||
|
await categoryChooser.expand();
|
||||||
|
await categoryChooser.selectRowByValue(2);
|
||||||
|
|
||||||
|
await click(".d-editor-button-bar .options");
|
||||||
|
await selectKit(".toolbar-popup-menu-options").expand();
|
||||||
|
const buttonSelector = `.select-kit-row[data-name='${I18n.t(
|
||||||
|
themePrefix("toolbar.builder")
|
||||||
|
)}']`;
|
||||||
|
assert.dom(buttonSelector).exists("it shows the composer button");
|
||||||
|
await click(buttonSelector);
|
||||||
|
|
||||||
|
assert.dom(".d-modal.placeholder-builder").exists();
|
||||||
|
|
||||||
|
await click(".d-modal .btn-primary");
|
||||||
|
assert
|
||||||
|
.dom(".dialog-body")
|
||||||
|
.hasText(I18n.t(themePrefix("builder.errors.no_key")));
|
||||||
|
await click(".dialog-footer .btn-primary");
|
||||||
|
|
||||||
|
await fillIn(".placeholder-builder__key", "password");
|
||||||
|
await fillIn(".placeholder-builder__description", "A secret password");
|
||||||
|
|
||||||
|
const dropdown = selectKit(".placeholder-builder__default-values");
|
||||||
|
await dropdown.expand();
|
||||||
|
await dropdown.fillInFilter("one");
|
||||||
|
await dropdown.keyboard("Enter");
|
||||||
|
await dropdown.fillInFilter("two");
|
||||||
|
await dropdown.keyboard("Enter");
|
||||||
|
|
||||||
|
await click(".d-modal .btn-primary");
|
||||||
|
assert.dom(".d-modal.placeholder-builder").doesNotExist();
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom("textarea.d-editor-input")
|
||||||
|
.hasValue(
|
||||||
|
`[wrap=placeholder key="password" description="A secret password" defaults="one,two"][/wrap]`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue