mirror of
https://github.com/zulip/zulip.git
synced 2025-11-04 14:03:30 +00:00
Previously the emoji_status set by the user would only be seen in a few places, it was decided that it would be useful to show the emoji_status in a couple of other additional places as well. As such this commit uses the status_emoji template to show the status emoji in the compose_pm pills. Due to the fact that we use the same pills system to render in the user_group, we need to add a conditional to prevent rendering there since the user status is not valuable there. Status emoji changes do not live update these, but neither do user renames, so there's bigger problems if that's a concern.
376 lines
13 KiB
JavaScript
376 lines
13 KiB
JavaScript
import $ from "jquery";
|
|
import _ from "lodash";
|
|
|
|
import render_confirm_delete_user from "../templates/confirm_dialog/confirm_delete_user.hbs";
|
|
import render_admin_user_group_list from "../templates/settings/admin_user_group_list.hbs";
|
|
|
|
import * as channel from "./channel";
|
|
import * as confirm_dialog from "./confirm_dialog";
|
|
import {$t, $t_html} from "./i18n";
|
|
import {page_params} from "./page_params";
|
|
import * as people from "./people";
|
|
import * as pill_typeahead from "./pill_typeahead";
|
|
import * as settings_data from "./settings_data";
|
|
import * as ui_report from "./ui_report";
|
|
import * as user_groups from "./user_groups";
|
|
import * as user_pill from "./user_pill";
|
|
|
|
const meta = {
|
|
loaded: false,
|
|
};
|
|
|
|
export function reset() {
|
|
meta.loaded = false;
|
|
}
|
|
|
|
export function reload() {
|
|
if (!meta.loaded) {
|
|
return;
|
|
}
|
|
|
|
const user_groups_section = $("#user-groups").expectOne();
|
|
user_groups_section.html("");
|
|
populate_user_groups();
|
|
}
|
|
|
|
export function can_edit(group_id) {
|
|
if (!settings_data.user_can_edit_user_groups()) {
|
|
return false;
|
|
}
|
|
|
|
// Admins and moderators are allowed to edit user groups even if they
|
|
// are not a member of that user group. Members can edit user groups
|
|
// only if they belong to that group.
|
|
if (page_params.is_admin || page_params.is_moderator) {
|
|
return true;
|
|
}
|
|
|
|
return user_groups.is_member_of(group_id, people.my_current_user_id());
|
|
}
|
|
|
|
export function populate_user_groups() {
|
|
const user_groups_section = $("#user-groups").expectOne();
|
|
const user_groups_array = user_groups.get_realm_user_groups();
|
|
|
|
for (const data of user_groups_array) {
|
|
user_groups_section.append(
|
|
render_admin_user_group_list({
|
|
user_group: {
|
|
name: data.name,
|
|
id: data.id,
|
|
description: data.description,
|
|
},
|
|
}),
|
|
);
|
|
|
|
const pill_config = {
|
|
show_user_status_emoji: false,
|
|
};
|
|
|
|
const pill_container = $(`.pill-container[data-group-pills="${CSS.escape(data.id)}"]`);
|
|
const pills = user_pill.create_pills(pill_container, pill_config);
|
|
|
|
function get_pill_user_ids() {
|
|
return user_pill.get_user_ids(pills);
|
|
}
|
|
|
|
const userg = $(`div.user-group[id="${CSS.escape(data.id)}"]`);
|
|
for (const user_id of data.members) {
|
|
const user = people.get_by_user_id(user_id);
|
|
user_pill.append_user(user, pills);
|
|
}
|
|
|
|
function update_membership(group_id) {
|
|
if (can_edit(group_id)) {
|
|
return;
|
|
}
|
|
userg.find(".name").attr("contenteditable", "false");
|
|
userg.find(".description").attr("contenteditable", "false");
|
|
userg.addClass("ntm");
|
|
pill_container.find(".input").attr("contenteditable", "false");
|
|
pill_container.find(".input").css("display", "none");
|
|
pill_container.addClass("not-editable");
|
|
pill_container.off("keydown", ".pill");
|
|
pill_container.off("keydown", ".input");
|
|
pill_container.off("click");
|
|
pill_container.on("click", (e) => {
|
|
e.stopPropagation();
|
|
});
|
|
pill_container.find(".pill").on("mouseenter", () => {
|
|
pill_container.find(".pill").find(".exit").css("opacity", "0.5");
|
|
});
|
|
}
|
|
update_membership(data.id);
|
|
|
|
function is_user_group_changed() {
|
|
const draft_group = get_pill_user_ids();
|
|
const group_data = user_groups.get_user_group_from_id(data.id);
|
|
const original_group = Array.from(group_data.members);
|
|
const same_groups = _.isEqual(_.sortBy(draft_group), _.sortBy(original_group));
|
|
const description = $(`#user-groups #${CSS.escape(data.id)} .description`)
|
|
.text()
|
|
.trim();
|
|
const name = $(`#user-groups #${CSS.escape(data.id)} .name`)
|
|
.text()
|
|
.trim();
|
|
const user_group_status = $(`#user-groups #${CSS.escape(data.id)} .user-group-status`);
|
|
|
|
if (user_group_status.is(":visible")) {
|
|
return false;
|
|
}
|
|
|
|
if (
|
|
group_data.description === description &&
|
|
group_data.name === name &&
|
|
(!draft_group.length || same_groups)
|
|
) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function update_cancel_button() {
|
|
if (!can_edit(data.id)) {
|
|
return;
|
|
}
|
|
const cancel_button = $(`#user-groups #${CSS.escape(data.id)} .save-status.btn-danger`);
|
|
const saved_button = $(`#user-groups #${CSS.escape(data.id)} .save-status.sea-green`);
|
|
const save_instructions = $(`#user-groups #${CSS.escape(data.id)} .save-instructions`);
|
|
|
|
if (is_user_group_changed() && !cancel_button.is(":visible")) {
|
|
saved_button.fadeOut(0);
|
|
cancel_button.css({display: "inline-block", opacity: "0"}).fadeTo(400, 1);
|
|
save_instructions.css({display: "block", opacity: "0"}).fadeTo(400, 1);
|
|
} else if (!is_user_group_changed() && cancel_button.is(":visible")) {
|
|
cancel_button.fadeOut();
|
|
save_instructions.fadeOut();
|
|
}
|
|
}
|
|
|
|
function show_saved_button() {
|
|
const cancel_button = $(`#user-groups #${CSS.escape(data.id)} .save-status.btn-danger`);
|
|
const saved_button = $(`#user-groups #${CSS.escape(data.id)} .save-status.sea-green`);
|
|
const save_instructions = $(`#user-groups #${CSS.escape(data.id)} .save-instructions`);
|
|
if (!saved_button.is(":visible")) {
|
|
cancel_button.fadeOut(0);
|
|
save_instructions.fadeOut(0);
|
|
saved_button
|
|
.css({display: "inline-block", opacity: "0"})
|
|
.fadeTo(400, 1)
|
|
.delay(2000)
|
|
.fadeTo(400, 0);
|
|
}
|
|
}
|
|
|
|
function save_members() {
|
|
const draft_group = get_pill_user_ids();
|
|
const group_data = user_groups.get_user_group_from_id(data.id);
|
|
const original_group = Array.from(group_data.members);
|
|
const same_groups = _.isEqual(_.sortBy(draft_group), _.sortBy(original_group));
|
|
if (!draft_group.length || same_groups) {
|
|
return;
|
|
}
|
|
const added = _.difference(draft_group, original_group);
|
|
const removed = _.difference(original_group, draft_group);
|
|
channel.post({
|
|
url: "/json/user_groups/" + data.id + "/members",
|
|
data: {
|
|
add: JSON.stringify(added),
|
|
delete: JSON.stringify(removed),
|
|
},
|
|
success() {
|
|
setTimeout(show_saved_button, 200);
|
|
},
|
|
});
|
|
}
|
|
|
|
function save_name_desc() {
|
|
const user_group_status = $(`#user-groups #${CSS.escape(data.id)} .user-group-status`);
|
|
const group_data = user_groups.get_user_group_from_id(data.id);
|
|
const description = $(`#user-groups #${CSS.escape(data.id)} .description`)
|
|
.text()
|
|
.trim();
|
|
const name = $(`#user-groups #${CSS.escape(data.id)} .name`)
|
|
.text()
|
|
.trim();
|
|
|
|
if (group_data.description === description && group_data.name === name) {
|
|
return;
|
|
}
|
|
|
|
channel.patch({
|
|
url: "/json/user_groups/" + data.id,
|
|
data: {
|
|
name,
|
|
description,
|
|
},
|
|
success() {
|
|
user_group_status.hide();
|
|
setTimeout(show_saved_button, 200);
|
|
},
|
|
error(xhr) {
|
|
const errors = JSON.parse(xhr.responseText).msg;
|
|
xhr.responseText = JSON.stringify({msg: errors});
|
|
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, user_group_status);
|
|
update_cancel_button();
|
|
$(`#user-groups #${CSS.escape(data.id)} .name`).text(group_data.name);
|
|
$(`#user-groups #${CSS.escape(data.id)} .description`).text(
|
|
group_data.description,
|
|
);
|
|
},
|
|
});
|
|
}
|
|
|
|
function do_not_blur(except_class, event) {
|
|
// Event generated from or inside the typeahead.
|
|
if ($(event.relatedTarget).closest(".typeahead").length) {
|
|
return true;
|
|
}
|
|
|
|
if ($(event.relatedTarget).closest(`#user-groups #${CSS.escape(data.id)}`).length) {
|
|
return [".pill-container", ".name", ".description", ".input", ".delete"].some(
|
|
(class_name) =>
|
|
class_name !== except_class &&
|
|
$(event.relatedTarget).closest(class_name).length,
|
|
);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function auto_save(class_name, event) {
|
|
if (!can_edit(data.id)) {
|
|
return;
|
|
}
|
|
|
|
if (do_not_blur(class_name, event)) {
|
|
return;
|
|
}
|
|
if (
|
|
$(event.relatedTarget).closest(`#user-groups #${CSS.escape(data.id)}`) &&
|
|
$(event.relatedTarget).closest(".save-status.btn-danger").length
|
|
) {
|
|
reload();
|
|
return;
|
|
}
|
|
save_name_desc();
|
|
save_members();
|
|
}
|
|
|
|
$(`#user-groups #${CSS.escape(data.id)}`).on("blur", ".input", (event) => {
|
|
auto_save(".input", event);
|
|
});
|
|
|
|
$(`#user-groups #${CSS.escape(data.id)}`).on("blur", ".name", (event) => {
|
|
auto_save(".name", event);
|
|
});
|
|
$(`#user-groups #${CSS.escape(data.id)}`).on("input", ".name", () => {
|
|
update_cancel_button();
|
|
});
|
|
|
|
$(`#user-groups #${CSS.escape(data.id)}`).on("blur", ".description", (event) => {
|
|
auto_save(".description", event);
|
|
});
|
|
$(`#user-groups #${CSS.escape(data.id)}`).on("input", ".description", () => {
|
|
update_cancel_button();
|
|
});
|
|
|
|
const input = pill_container.children(".input");
|
|
if (can_edit(data.id)) {
|
|
const opts = {update_func: update_cancel_button, user: true};
|
|
pill_typeahead.set_up(input, pills, opts);
|
|
}
|
|
|
|
if (can_edit(data.id)) {
|
|
pills.onPillRemove(() => {
|
|
// onPillRemove is fired before the pill is removed from
|
|
// the DOM.
|
|
update_cancel_button();
|
|
setTimeout(() => {
|
|
input.trigger("focus");
|
|
}, 100);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
export function set_up() {
|
|
meta.loaded = true;
|
|
populate_user_groups();
|
|
|
|
$(".organization form.admin-user-group-form")
|
|
.off("submit")
|
|
.on("submit", function (e) {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
const user_group_status = $("#admin-user-group-status");
|
|
|
|
const group = {
|
|
members: JSON.stringify([people.my_current_user_id()]),
|
|
};
|
|
|
|
for (const obj of $(this).serializeArray()) {
|
|
if (obj.value.trim() === "") {
|
|
continue;
|
|
}
|
|
group[obj.name] = obj.value;
|
|
}
|
|
|
|
channel.post({
|
|
url: "/json/user_groups/create",
|
|
data: group,
|
|
success() {
|
|
user_group_status.hide();
|
|
ui_report.success(
|
|
$t_html({defaultMessage: "User group added!"}),
|
|
user_group_status,
|
|
);
|
|
$("form.admin-user-group-form input[type='text']").val("");
|
|
},
|
|
error(xhr) {
|
|
user_group_status.hide();
|
|
const errors = JSON.parse(xhr.responseText).msg;
|
|
xhr.responseText = JSON.stringify({msg: errors});
|
|
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, user_group_status);
|
|
},
|
|
});
|
|
});
|
|
|
|
$("#user-groups").on("click", ".delete", function () {
|
|
const group_id = Number.parseInt($(this).parents(".user-group").attr("id"), 10);
|
|
if (!can_edit(group_id)) {
|
|
return;
|
|
}
|
|
const user_group = user_groups.get_user_group_from_id(group_id);
|
|
const btn = $(this);
|
|
|
|
function delete_user_group() {
|
|
channel.del({
|
|
url: "/json/user_groups/" + group_id,
|
|
data: {
|
|
id: group_id,
|
|
},
|
|
error() {
|
|
btn.text($t({defaultMessage: "Failed!"}));
|
|
},
|
|
});
|
|
}
|
|
|
|
const html_body = render_confirm_delete_user({
|
|
group_name: user_group.name,
|
|
});
|
|
|
|
confirm_dialog.launch({
|
|
html_heading: $t_html({defaultMessage: "Delete user group"}),
|
|
html_body,
|
|
on_click: delete_user_group,
|
|
});
|
|
});
|
|
|
|
$("#user-groups").on("keypress", ".user-group h4 > span", (e) => {
|
|
if (e.key === "Enter") {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
}
|