DEV: Adopt modern ember primitives (#66)

Modernise components and controllers
This commit is contained in:
Selase Krakani 2022-11-22 12:30:03 +00:00 committed by GitHub
parent 7137499c69
commit a9d6614526
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 177 additions and 96 deletions

1
.discourse-compatibility Normal file
View File

@ -0,0 +1 @@
2.8.11: 7137499c69065928c0fdd8795a3fb8d175e1ff3d

View File

@ -1 +1 @@
{{show-user-notes show=(action "showUserNotes") count=userNotesCount}}
<ShowUserNotes @show={{action "showUserNotes"}} @count={{this.userNotesCount}} />

View File

@ -1,5 +1,5 @@
{{#if userNotesCount}}
<a href {{action "showUserNotes"}} title={{userNotesTitle}}>
<DButton @class="btn btn-flat" @translatedTitle={{userNotesTitle}} @action={{action "showUserNotes"}}>
{{#if emojiEnabled}}
<img
src={{emojiUrl}}
@ -10,5 +10,5 @@
{{else}}
{{d-icon "sticky-note"}}
{{/if}}
</a>
</DButton>
{{/if}}

View File

@ -1,5 +1,5 @@
{{#if userNotesCount}}
<a href {{action "showUserNotes"}} title={{userNotesTitle}}>
<DButton @class="btn btn-flat" @translatedTitle={{userNotesTitle}} @action={{action "showUserNotes"}}>
{{#if emojiEnabled}}
<img
src={{emojiUrl}}
@ -10,5 +10,5 @@
{{else}}
{{d-icon "sticky-note"}}
{{/if}}
</a>
</DButton>
{{/if}}

View File

@ -1 +1 @@
{{show-user-notes show=(action "showUserNotes") count=userNotesCount}}
<ShowUserNotes @show={{action "showUserNotes"}} @count={{this.userNotesCount}} />

View File

@ -0,0 +1,6 @@
<DButton
@class="btn btn-default"
@action={{@show}}
@icon="pencil-alt"
@translatedLabel={{this.label}}
/>

View File

@ -1,8 +1,12 @@
import Component from "@ember/component";
import { gt } from "@ember/object/computed";
import Component from "@glimmer/component";
import I18n from "I18n";
export default Component.extend({
tagName: "",
showCount: gt("count", 0),
});
export default class ShowUserNotes extends Component {
get label() {
if (this.args.count > 0) {
return I18n.t("user_notes.show", { count: this.args.count });
} else {
return I18n.t("user_notes.title");
}
}
}

View File

@ -1,70 +1,74 @@
import I18n from "I18n";
import discourseComputed, { on } from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error";
import Controller from "@ember/controller";
import I18n from "I18n";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { tracked } from "@glimmer/tracking";
export default Controller.extend({
dialog: service(),
newNote: null,
saving: false,
user: null,
export default class UserNotesController extends Controller {
@service dialog;
@on("init")
reset() {
this.setProperties({ newNote: null, saving: false, callback: null });
},
@tracked newNote;
@tracked userId;
@tracked saving = false;
@discourseComputed("newNote", "saving")
attachDisabled(newNote, saving) {
return saving || !newNote || newNote.length === 0;
},
_refreshCount() {
#refreshCount() {
if (this.callback) {
this.callback(this.get("model.length"));
this.callback(this.model.length);
}
},
}
actions: {
attachNote() {
const note = this.store.createRecord("user-note");
const userId = parseInt(this.userId, 10);
reset() {
this.newNote = null;
this.userId = null;
this.callback = null;
this.saving = false;
}
this.set("saving", true);
let args = {
raw: this.newNote,
user_id: userId,
};
get attachDisabled() {
return this.saving || !this.newNote || this.newNote.length === 0;
}
if (this.postId) {
args.post_id = parseInt(this.postId, 10);
}
@action
attachNote() {
const note = this.store.createRecord("user-note");
const userId = parseInt(this.userId, 10);
note
.save(args)
.then(() => {
this.set("newNote", "");
this.model.insertAt(0, note);
this._refreshCount();
})
.catch(popupAjaxError)
.finally(() => this.set("saving", false));
},
this.saving = true;
removeNote(note) {
this.dialog.deleteConfirm({
message: I18n.t("user_notes.delete_confirm"),
didConfirm: () => {
note
.destroyRecord()
.then(() => {
this.model.removeObject(note);
this._refreshCount();
})
.catch(popupAjaxError);
},
});
},
},
});
const args = {
raw: this.newNote,
user_id: userId,
};
if (this.postId) {
args.post_id = parseInt(this.postId, 10);
}
note
.save(args)
.then(() => {
this.newNote = "";
this.model.insertAt(0, note);
this.#refreshCount();
})
.catch(popupAjaxError)
.finally(() => (this.saving = false));
}
@action
removeNote(note) {
this.dialog.deleteConfirm({
message: I18n.t("user_notes.delete_confirm"),
didConfirm: () => {
note
.destroyRecord()
.then(() => {
this.model.removeObject(note);
this.#refreshCount();
})
.catch(popupAjaxError);
},
});
}
}

View File

@ -1,8 +0,0 @@
<a {{action show}} href class="btn btn-default">
{{d-icon "pencil-alt"}}
{{#if showCount}}
{{i18n "user_notes.show" count=count}}
{{else}}
{{i18n "user_notes.title"}}
{{/if}}
</a>

View File

@ -1,18 +1,18 @@
{{#d-modal-body class="user-notes-modal"}}
{{textarea value=newNote}}
{{d-button
action=(action "attachNote")
label="user_notes.attach"
class="btn-primary"
disabled=attachDisabled
}}
<DModalBody @class="user-notes-modal">
<Textarea @value={{this.newNote}} />
<DButton
@action={{action "attachNote"}}
@label="user_notes.attach"
@class="btn-primary"
@disabled={{this.attachDisabled}}
/>
{{#each model as |n|}}
<div class="user-note">
<div class="posted-by">
{{#user-link user=n.created_by}}
<UserLink @user={{n.created_by}}>
{{avatar n.created_by imageSize="small"}}
{{/user-link}}
</UserLink>
</div>
<div class="note-contents">
<div class="note-info">
@ -21,12 +21,12 @@
{{#if n.can_delete}}
<span class="controls">
{{d-button
action=(action "removeNote" n)
icon="far-trash-alt"
class="btn-small btn-danger"
title="user_notes.remove"
}}
<DButton
@action={{action "removeNote" n}}
@icon="far-trash-alt"
@class="btn-small btn-danger"
@title="user_notes.remove"
/>
</span>
{{/if}}
</div>
@ -45,4 +45,4 @@
<div class="clearfix"></div>
</div>
{{/each}}
{{/d-modal-body}}
</DModalBody>

View File

@ -6,6 +6,18 @@
.show-user-notes-on-flags {
display: inline-block;
button {
display: inline;
padding: 0;
}
}
.show-user-notes-on-card {
button {
display: inline;
padding: 0;
}
}
.modal-body.user-notes-modal {

View File

@ -0,0 +1,62 @@
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
import { test } from "qunit";
import { click, fillIn, visit } from "@ember/test-helpers";
import I18n from "I18n";
acceptance("User Notes", function (needs) {
needs.user();
needs.settings({ user_notes_enabled: true });
needs.pretender((server, helper) => {
server.get("/user_notes", () => {
return helper.response(200, {
extras: { username: "eviltrout" },
user_notes: [],
});
});
server.post("/user_notes", () => {
return helper.response(200, {
user_note: {
id: "6d945d25740e9801920e54c71c516c7b",
user_id: 1,
raw: "Helpful user",
created_by: {
id: 2,
username: "sam",
name: null,
avatar_template:
"/letter_avatar_proxy/v4/letter/s/ac8455/{size}.png",
},
created_at: "2022-11-16T22:00:00.000Z",
can_delete: true,
post_id: null,
post_url: "",
post_title: null,
},
});
});
});
test("creates note from user's profile", async function (assert) {
await visit("/admin/users/1/eviltrout");
assert.dom(".user-controls button").hasText(I18n.t("user_notes.title"));
assert.dom(".user-notes-modal.modal-body").isNotVisible();
await click(".user-controls button");
assert.dom(".user-notes-modal.modal-body").isVisible();
await fillIn(".user-notes-modal textarea", "Helpful user");
assert.dom(".user-notes-modal.modal-body button").isEnabled();
await click(".user-notes-modal.modal-body button");
await click(".user-notes-modal button.modal-close");
assert
.dom(".user-controls button")
.hasText(I18n.t("user_notes.show", { count: 1 }));
});
});