diff --git a/client/html/user_edit.tpl b/client/html/user_edit.tpl index d518aabb..22dcd835 100644 --- a/client/html/user_edit.tpl +++ b/client/html/user_edit.tpl @@ -68,6 +68,12 @@ <% } %> + + <% if (ctx.canEditBlocklist) { %> +
  • + <%= ctx.makeTextInput({text: 'Blocklist'}) %> +
  • + <% } %>
    diff --git a/client/js/controllers/user_controller.js b/client/js/controllers/user_controller.js index 8cf46584..bd41aa1e 100644 --- a/client/js/controllers/user_controller.js +++ b/client/js/controllers/user_controller.js @@ -89,6 +89,7 @@ class UserController { canEditAvatar: api.hasPrivilege( `users:edit:${infix}:avatar` ), + canEditBlocklist: api.hasPrivilege(`users:edit:${infix}:blocklist`), canEditAnything: api.hasPrivilege(`users:edit:${infix}`), canListTokens: api.hasPrivilege( `userTokens:list:${infix}` diff --git a/client/js/models/user.js b/client/js/models/user.js index 28dc3efe..40b6ebec 100644 --- a/client/js/models/user.js +++ b/client/js/models/user.js @@ -3,11 +3,19 @@ const api = require("../api.js"); const uri = require("../util/uri.js"); const events = require("../events.js"); +const misc = require("../util/misc.js"); class User extends events.EventTarget { constructor() { + const TagList = require("./tag_list.js"); + super(); this._orig = {}; + + for (let obj of [this, this._orig]) { + obj._blocklist = new TagList(); + } + this._updateFromResponse({}); } @@ -71,6 +79,10 @@ class User extends events.EventTarget { throw "Invalid operation"; } + get blocklist() { + return this._blocklist; + } + set name(value) { this._name = value; } @@ -95,6 +107,10 @@ class User extends events.EventTarget { this._password = value; } + set blocklist(value) { + this._blocklist = value || ""; + } + static fromResponse(response) { const ret = new User(); ret._updateFromResponse(response); @@ -121,6 +137,11 @@ class User extends events.EventTarget { if (this._rank !== this._orig._rank) { detail.rank = this._rank; } + if (misc.arraysDiffer(this._blocklist, this._orig._blocklist)) { + detail.blocklist = this._blocklist.map( + (relation) => relation.names[0] + ); + } if (this._avatarStyle !== this._orig._avatarStyle) { detail.avatarStyle = this._avatarStyle; } @@ -187,6 +208,10 @@ class User extends events.EventTarget { _dislikedPostCount: response.dislikedPostCount, }; + for (let obj of [this, this._orig]) { + obj._blocklist.sync(response.blocklist); + } + Object.assign(this, map); Object.assign(this._orig, map); diff --git a/client/js/views/user_edit_view.js b/client/js/views/user_edit_view.js index 4886726a..bee0bb4f 100644 --- a/client/js/views/user_edit_view.js +++ b/client/js/views/user_edit_view.js @@ -4,6 +4,8 @@ const events = require("../events.js"); const api = require("../api.js"); const views = require("../util/views.js"); const FileDropperControl = require("../controls/file_dropper_control.js"); +const TagInputControl = require("../controls/tag_input_control.js") +const misc = require("../util/misc.js"); const template = views.getTemplate("user-edit"); @@ -41,6 +43,13 @@ class UserEditView extends events.EventTarget { }); } + if (this._blocklistFieldNode) { + new TagInputControl( + this._blocklistFieldNode, + this._user.blocklist + ); + } + this._formNode.addEventListener("submit", (e) => this._evtSubmit(e)); } @@ -83,6 +92,10 @@ class UserEditView extends events.EventTarget { ? this._rankInputNode.value : undefined, + blocklist: this._blocklistFieldNode + ? misc.splitByWhitespace(this._blocklistFieldNode.value) + : undefined, + avatarStyle: this._avatarStyleInputNode ? this._avatarStyleInputNode.value : undefined, @@ -101,6 +114,10 @@ class UserEditView extends events.EventTarget { return this._hostNode.querySelector("form"); } + get _blocklistFieldNode() { + return this._formNode.querySelector(".blocklist input"); + } + get _rankInputNode() { return this._formNode.querySelector("[name=rank]"); }