mirror of https://github.com/zulip/zulip.git
parent
df001db1a9
commit
b7335d0dec
|
@ -9,7 +9,7 @@ const $ = require("../zjsunit/zjquery");
|
|||
const upload_widget = mock_esm("../../static/js/upload_widget");
|
||||
const settings_emoji = zrequire("settings_emoji");
|
||||
|
||||
run_test("build_emoji_upload_widget", () => {
|
||||
run_test("add_custom_emoji_post_render", () => {
|
||||
let build_widget_stub = false;
|
||||
upload_widget.build_widget = (
|
||||
get_file_input,
|
||||
|
@ -25,6 +25,6 @@ run_test("build_emoji_upload_widget", () => {
|
|||
assert.deepEqual(upload_button, $("#emoji_upload_button"));
|
||||
build_widget_stub = true;
|
||||
};
|
||||
settings_emoji.build_emoji_upload_widget();
|
||||
settings_emoji.add_custom_emoji_post_render();
|
||||
assert.ok(build_widget_stub);
|
||||
});
|
||||
|
|
|
@ -179,21 +179,15 @@ async function test_organization_permissions(page: Page): Promise<void> {
|
|||
}
|
||||
|
||||
async function test_add_emoji(page: Page): Promise<void> {
|
||||
await common.fill_form(page, "form.admin-emoji-form", {name: "zulip logo"});
|
||||
await common.fill_form(page, "#add-custom-emoji-form", {name: "zulip logo"});
|
||||
|
||||
const emoji_upload_handle = await page.$("#emoji_file_input");
|
||||
assert.ok(emoji_upload_handle);
|
||||
await (emoji_upload_handle as ElementHandle<HTMLInputElement>).uploadFile(
|
||||
"static/images/logo/zulip-icon-128x128.png",
|
||||
);
|
||||
await page.click("#admin_emoji_submit");
|
||||
|
||||
const emoji_status = "div#admin-emoji-status";
|
||||
await page.waitForSelector(emoji_status, {visible: true});
|
||||
assert.strictEqual(
|
||||
await common.get_text_from_selector(page, emoji_status),
|
||||
"Custom emoji added!",
|
||||
);
|
||||
await page.click("#add-custom-emoji-modal .dialog_submit_button");
|
||||
await common.wait_for_micromodal_to_close(page);
|
||||
|
||||
await page.waitForSelector("tr#emoji_zulip_logo", {visible: true});
|
||||
assert.strictEqual(
|
||||
|
@ -217,7 +211,8 @@ async function test_delete_emoji(page: Page): Promise<void> {
|
|||
|
||||
async function test_custom_realm_emoji(page: Page): Promise<void> {
|
||||
await page.click("li[data-section='emoji-settings']");
|
||||
await page.waitForSelector(".admin-emoji-form", {visible: true});
|
||||
await page.click("#add-custom-emoji-button");
|
||||
await common.wait_for_micromodal_to_open(page);
|
||||
|
||||
await test_add_emoji(page);
|
||||
await test_delete_emoji(page);
|
||||
|
|
|
@ -3,6 +3,7 @@ import $ from "jquery";
|
|||
import emoji_codes from "../generated/emoji/emoji_codes.json";
|
||||
import render_confirm_deactivate_custom_emoji from "../templates/confirm_dialog/confirm_deactivate_custom_emoji.hbs";
|
||||
import emoji_settings_warning_modal from "../templates/confirm_dialog/confirm_emoji_settings_warning.hbs";
|
||||
import render_add_emoji from "../templates/settings/add_emoji.hbs";
|
||||
import render_admin_emoji_list from "../templates/settings/admin_emoji_list.hbs";
|
||||
import render_settings_emoji_settings_tip from "../templates/settings/emoji_settings_tip.hbs";
|
||||
|
||||
|
@ -47,10 +48,10 @@ export function update_custom_emoji_ui() {
|
|||
$("#emoji-settings").find(".emoji-settings-tip-container").html(rendered_tip);
|
||||
if (!settings_data.user_can_add_custom_emoji()) {
|
||||
$(".add-emoji-text").hide();
|
||||
$(".admin-emoji-form").hide();
|
||||
$("#add-custom-emoji-button").hide();
|
||||
} else {
|
||||
$(".add-emoji-text").show();
|
||||
$(".admin-emoji-form").show();
|
||||
$("#add-custom-emoji-button").show();
|
||||
}
|
||||
|
||||
populate_emoji();
|
||||
|
@ -138,7 +139,16 @@ export function populate_emoji() {
|
|||
loading.destroy_indicator($("#admin_page_emoji_loading_indicator"));
|
||||
}
|
||||
|
||||
export function build_emoji_upload_widget() {
|
||||
export function add_custom_emoji_post_render() {
|
||||
$("#add-custom-emoji-modal .dialog_submit_button").prop("disabled", true);
|
||||
|
||||
$("#add-custom-emoji-form").on("input", "input", () => {
|
||||
$("#add-custom-emoji-modal .dialog_submit_button").prop(
|
||||
"disabled",
|
||||
$("#emoji_name").val() === "" || $("#emoji_file_input").val() === "",
|
||||
);
|
||||
});
|
||||
|
||||
const get_file_input = function () {
|
||||
return $("#emoji_file_input");
|
||||
};
|
||||
|
@ -149,8 +159,11 @@ export function build_emoji_upload_widget() {
|
|||
const $upload_button = $("#emoji_upload_button");
|
||||
const $preview_text = $("#emoji_preview_text");
|
||||
const $preview_image = $("#emoji_preview_image");
|
||||
const $placeholder_icon = $("#emoji_placeholder_icon");
|
||||
|
||||
return upload_widget.build_widget(
|
||||
$preview_image.hide();
|
||||
|
||||
upload_widget.build_widget(
|
||||
get_file_input,
|
||||
$file_name_field,
|
||||
$input_error,
|
||||
|
@ -159,11 +172,130 @@ export function build_emoji_upload_widget() {
|
|||
$preview_text,
|
||||
$preview_image,
|
||||
);
|
||||
|
||||
get_file_input().on("input", () => {
|
||||
$placeholder_icon.hide();
|
||||
$preview_image.show();
|
||||
});
|
||||
|
||||
$preview_text.show();
|
||||
$clear_button.on("click", (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
$("#add-custom-emoji-modal .dialog_submit_button").prop("disabled", true);
|
||||
|
||||
$preview_image.hide();
|
||||
$placeholder_icon.show();
|
||||
$preview_text.show();
|
||||
$preview_image.attr("src", "/static/images/default-avatar.png");
|
||||
});
|
||||
}
|
||||
|
||||
function show_modal() {
|
||||
const html_body = render_add_emoji();
|
||||
|
||||
function add_custom_emoji(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
dialog_widget.show_dialog_spinner();
|
||||
|
||||
const $emoji_status = $("#dialog_error");
|
||||
const emoji = {};
|
||||
|
||||
function submit_custom_emoji_request(formData) {
|
||||
channel.post({
|
||||
url: "/json/realm/emoji/" + encodeURIComponent(emoji.name),
|
||||
data: formData,
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success() {
|
||||
dialog_widget.close_modal();
|
||||
},
|
||||
error(xhr) {
|
||||
$("#dialog_error").hide();
|
||||
dialog_widget.hide_dialog_spinner();
|
||||
const errors = JSON.parse(xhr.responseText).msg;
|
||||
xhr.responseText = JSON.stringify({msg: errors});
|
||||
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $emoji_status);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
for (const obj of $("#add-custom-emoji-form").serializeArray()) {
|
||||
emoji[obj.name] = obj.value;
|
||||
}
|
||||
|
||||
if (emoji.name.trim() === "") {
|
||||
ui_report.client_error(
|
||||
$t_html({defaultMessage: "Failed: Emoji name is required."}),
|
||||
$emoji_status,
|
||||
);
|
||||
dialog_widget.hide_dialog_spinner();
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_custom_emoji(emoji.name)) {
|
||||
ui_report.client_error(
|
||||
$t_html({
|
||||
defaultMessage: "Failed: A custom emoji with this name already exists.",
|
||||
}),
|
||||
$emoji_status,
|
||||
);
|
||||
dialog_widget.hide_dialog_spinner();
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
for (const [i, file] of Array.prototype.entries.call($("#emoji_file_input")[0].files)) {
|
||||
formData.append("file-" + i, file);
|
||||
}
|
||||
|
||||
if (is_default_emoji(emoji.name)) {
|
||||
if (!page_params.is_admin) {
|
||||
ui_report.client_error(
|
||||
$t_html({
|
||||
defaultMessage:
|
||||
"Failed: There is a default emoji with this name. Only administrators can override default emoji.",
|
||||
}),
|
||||
$emoji_status,
|
||||
);
|
||||
dialog_widget.hide_dialog_spinner();
|
||||
return;
|
||||
}
|
||||
|
||||
dialog_widget.close_modal(() => {
|
||||
const html_body = emoji_settings_warning_modal({
|
||||
emoji_name: emoji.name,
|
||||
});
|
||||
confirm_dialog.launch({
|
||||
html_heading: $t_html({defaultMessage: "Override default emoji?"}),
|
||||
html_body,
|
||||
on_click: () => submit_custom_emoji_request(formData),
|
||||
});
|
||||
});
|
||||
} else {
|
||||
submit_custom_emoji_request(formData);
|
||||
}
|
||||
}
|
||||
dialog_widget.launch({
|
||||
html_heading: $t_html({defaultMessage: "Add a new emoji"}),
|
||||
html_body,
|
||||
html_submit_button: $t_html({defaultMessage: "Confirm"}),
|
||||
id: "add-custom-emoji-modal",
|
||||
loading_spinner: true,
|
||||
on_click: add_custom_emoji,
|
||||
post_render: add_custom_emoji_post_render,
|
||||
});
|
||||
}
|
||||
|
||||
export function set_up() {
|
||||
meta.loaded = true;
|
||||
|
||||
$("#add-custom-emoji-button").on("click", show_modal);
|
||||
|
||||
loading.make_indicator($("#admin_page_emoji_loading_indicator"));
|
||||
|
||||
// Populate emoji table
|
||||
|
@ -191,97 +323,4 @@ export function set_up() {
|
|||
loading_spinner: true,
|
||||
});
|
||||
});
|
||||
|
||||
const emoji_widget = build_emoji_upload_widget();
|
||||
|
||||
$(".organization form.admin-emoji-form")
|
||||
.off("submit")
|
||||
.on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const $emoji_status = $("#admin-emoji-status");
|
||||
const emoji = {};
|
||||
|
||||
function submit_custom_emoji_request() {
|
||||
$("#admin_emoji_submit").prop("disabled", true);
|
||||
const formData = new FormData();
|
||||
for (const [i, file] of Array.prototype.entries.call(
|
||||
$("#emoji_file_input")[0].files,
|
||||
)) {
|
||||
formData.append("file-" + i, file);
|
||||
}
|
||||
|
||||
channel.post({
|
||||
url: "/json/realm/emoji/" + encodeURIComponent(emoji.name),
|
||||
data: formData,
|
||||
cache: false,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success() {
|
||||
$("#admin-emoji-status").hide();
|
||||
ui_report.success(
|
||||
$t_html({defaultMessage: "Custom emoji added!"}),
|
||||
$emoji_status,
|
||||
);
|
||||
$("form.admin-emoji-form input[type='text']").val("");
|
||||
$("#admin_emoji_submit").prop("disabled", false);
|
||||
emoji_widget.clear();
|
||||
},
|
||||
error(xhr) {
|
||||
$("#admin-emoji-status").hide();
|
||||
const errors = JSON.parse(xhr.responseText).msg;
|
||||
xhr.responseText = JSON.stringify({msg: errors});
|
||||
ui_report.error($t_html({defaultMessage: "Failed"}), xhr, $emoji_status);
|
||||
$("#admin_emoji_submit").prop("disabled", false);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
for (const obj of $(this).serializeArray()) {
|
||||
emoji[obj.name] = obj.value;
|
||||
}
|
||||
|
||||
if (emoji.name.trim() === "") {
|
||||
ui_report.client_error(
|
||||
$t_html({defaultMessage: "Failed: Emoji name is required."}),
|
||||
$emoji_status,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_custom_emoji(emoji.name)) {
|
||||
ui_report.client_error(
|
||||
$t_html({
|
||||
defaultMessage: "Failed: A custom emoji with this name already exists.",
|
||||
}),
|
||||
$emoji_status,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_default_emoji(emoji.name)) {
|
||||
if (!page_params.is_admin) {
|
||||
ui_report.client_error(
|
||||
$t_html({
|
||||
defaultMessage:
|
||||
"Failed: There is a default emoji with this name. Only administrators can override default emoji.",
|
||||
}),
|
||||
$emoji_status,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const html_body = emoji_settings_warning_modal({
|
||||
emoji_name: emoji.name,
|
||||
});
|
||||
|
||||
confirm_dialog.launch({
|
||||
html_heading: $t_html({defaultMessage: "Override default emoji?"}),
|
||||
html_body,
|
||||
on_click: submit_custom_emoji_request,
|
||||
});
|
||||
} else {
|
||||
submit_custom_emoji_request();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -622,17 +622,10 @@ input[type="checkbox"] {
|
|||
}
|
||||
}
|
||||
|
||||
.add-new-emoji-box,
|
||||
.add-new-export-box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.add-new-emoji-box .new-emoji-form,
|
||||
.add-new-export-box {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.add-new-emoji-box,
|
||||
.add-new-default-stream-box {
|
||||
input[type="text"] {
|
||||
padding: 6px;
|
||||
|
@ -640,19 +633,32 @@ input[type="checkbox"] {
|
|||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.add-new-emoji-box #emoji-file-name {
|
||||
width: 0;
|
||||
top: -19px;
|
||||
left: 3px;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
#add-custom-emoji-modal {
|
||||
form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.emoji_name_input {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#emoji-file-name {
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
height: 1rem;
|
||||
font-style: italic;
|
||||
color: hsl(0, 0%, 67%);
|
||||
}
|
||||
|
||||
#emoji_preview_text {
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
#emoji_file_input_error {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<form class="new-style" id="add-custom-emoji-form">
|
||||
<div>
|
||||
<input type="file" name="emoji_file_input" class="notvisible"
|
||||
id="emoji_file_input" value="{{t 'Upload image or GIF' }}"/>
|
||||
<button class="button white rounded" style="display: none;" id="emoji_image_clear_button">{{t "Clear image" }}</button>
|
||||
<button class="button rounded" id="emoji_upload_button">{{t "Upload image or GIF" }}</button>
|
||||
<div style="display: none;" id="emoji_preview_text">
|
||||
Preview: <i id="emoji_placeholder_icon" class="fa fa-file-image-o" aria-hidden="true"></i><img class="emoji" id="emoji_preview_image" src=""/>
|
||||
</div>
|
||||
<div id="emoji-file-name"></div>
|
||||
</div>
|
||||
<div id="emoji_file_input_error" class="text-error"></div>
|
||||
<div class="emoji_name_input">
|
||||
<label for="emoji_name">{{t "Emoji name" }}</label>
|
||||
<input type="text" name="name" id="emoji_name" placeholder="{{t 'leafy green vegetable' }}" />
|
||||
</div>
|
||||
</form>
|
|
@ -5,32 +5,9 @@
|
|||
<p class="add-emoji-text {{#unless can_add_emojis}}hide{{/unless}}">
|
||||
{{#tr}}Add extra emoji for members of the {realm_name} organization.{{/tr}}
|
||||
</p>
|
||||
<form class="admin-emoji-form {{#unless can_add_emojis}}hide{{/unless}}">
|
||||
<div class="add-new-emoji-box grey-box">
|
||||
<div class="new-emoji-form">
|
||||
<div class="settings-section-title new-emoji-section-title no-padding">{{t "Add a new emoji" }}</div>
|
||||
<div class="alert" id="admin-emoji-status"></div>
|
||||
<div class="inline-block">
|
||||
<label for="emoji_name">{{t "Emoji name" }}</label>
|
||||
<input type="text" name="name" id="emoji_name" placeholder="{{t 'leafy green vegetable' }}" />
|
||||
</div>
|
||||
<div class="inline-block">
|
||||
<span id="emoji-file-name"></span>
|
||||
<input type="file" name="emoji_file_input" class="notvisible"
|
||||
id="emoji_file_input" value="{{t 'Upload image or GIF' }}"/>
|
||||
<button class="button white rounded" style="display: none;" id="emoji_image_clear_button">{{t "Clear emoji image" }}</button>
|
||||
<button class="button rounded" id="emoji_upload_button">{{t "Upload image or GIF" }}</button>
|
||||
</div>
|
||||
<button id="admin_emoji_submit" type="submit" class="button rounded sea-green">
|
||||
{{t 'Add emoji' }}
|
||||
<button id="add-custom-emoji-button" class="button rounded sea-green">
|
||||
{{t 'Add a new emoji' }}
|
||||
</button>
|
||||
</div>
|
||||
<span id="emoji_file_input_error" class="text-error"></span>
|
||||
<span style="display: none;" id="emoji_preview_text">
|
||||
Preview: <img class="emoji" id="emoji_preview_image" />
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="settings_panel_list_header">
|
||||
<h3>{{t "Custom emoji"}}</h3>
|
||||
|
|
Loading…
Reference in New Issue