DEV: Use the new modal api (#26)

This commit is contained in:
Jarek Radosz 2023-12-05 23:15:32 +01:00 committed by GitHub
parent 344f4dd0ea
commit 05a727efd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 178 additions and 121 deletions

View File

@ -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 {

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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");
},
});

View File

@ -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,
}, },

View File

@ -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>

View File

@ -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]`
);
});
});