mirror of https://github.com/zulip/zulip.git
parent
ff52187289
commit
043d54d170
|
@ -109,6 +109,7 @@
|
||||||
<div id="manage_streams_container"></div>
|
<div id="manage_streams_container"></div>
|
||||||
<div id="manage_groups_container"></div>
|
<div id="manage_groups_container"></div>
|
||||||
<div id="drafts_table"></div>
|
<div id="drafts_table"></div>
|
||||||
|
<div id="scheduled_messages_overlay_container"></div>
|
||||||
<div id="settings_overlay_container" class="overlay" data-overlay="settings" aria-hidden="true">
|
<div id="settings_overlay_container" class="overlay" data-overlay="settings" aria-hidden="true">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,8 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/reminder.js",
|
"web/src/reminder.js",
|
||||||
"web/src/resize.js",
|
"web/src/resize.js",
|
||||||
"web/src/rows.js",
|
"web/src/rows.js",
|
||||||
|
"web/src/scheduled_messages.js",
|
||||||
|
"web/src/scheduled_messages_overlay_ui.js",
|
||||||
"web/src/scroll_bar.ts",
|
"web/src/scroll_bar.ts",
|
||||||
"web/src/search_pill_widget.js",
|
"web/src/search_pill_widget.js",
|
||||||
"web/src/sent_messages.js",
|
"web/src/sent_messages.js",
|
||||||
|
|
|
@ -38,6 +38,7 @@ import "../../styles/modal.css";
|
||||||
import "../../styles/settings.css";
|
import "../../styles/settings.css";
|
||||||
import "../../styles/image_upload_widget.css";
|
import "../../styles/image_upload_widget.css";
|
||||||
import "../../styles/subscriptions.css";
|
import "../../styles/subscriptions.css";
|
||||||
|
import "../../styles/scheduled_messages.css";
|
||||||
import "../../styles/drafts.css";
|
import "../../styles/drafts.css";
|
||||||
import "../../styles/input_pill.css";
|
import "../../styles/input_pill.css";
|
||||||
import "../../styles/informational_overlays.css";
|
import "../../styles/informational_overlays.css";
|
||||||
|
|
|
@ -15,6 +15,7 @@ export const ERROR = "error";
|
||||||
const MESSAGE_SENT_CLASSNAMES = {
|
const MESSAGE_SENT_CLASSNAMES = {
|
||||||
sent_scroll_to_view: "sent_scroll_to_view",
|
sent_scroll_to_view: "sent_scroll_to_view",
|
||||||
narrow_to_recipient: "narrow_to_recipient",
|
narrow_to_recipient: "narrow_to_recipient",
|
||||||
|
scheduled_message_banner: "scheduled_message_banner",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CLASSNAMES = {
|
export const CLASSNAMES = {
|
||||||
|
|
|
@ -208,6 +208,7 @@ export function is_overlay_hash(hash) {
|
||||||
"message-formatting",
|
"message-formatting",
|
||||||
"search-operators",
|
"search-operators",
|
||||||
"about-zulip",
|
"about-zulip",
|
||||||
|
"scheduled",
|
||||||
];
|
];
|
||||||
const main_hash = get_hash_category(hash);
|
const main_hash = get_hash_category(hash);
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import * as overlays from "./overlays";
|
||||||
import {page_params} from "./page_params";
|
import {page_params} from "./page_params";
|
||||||
import * as recent_topics_ui from "./recent_topics_ui";
|
import * as recent_topics_ui from "./recent_topics_ui";
|
||||||
import * as recent_topics_util from "./recent_topics_util";
|
import * as recent_topics_util from "./recent_topics_util";
|
||||||
|
import * as scheduled_messages_overlay_ui from "./scheduled_messages_overlay_ui";
|
||||||
import * as search from "./search";
|
import * as search from "./search";
|
||||||
import * as settings from "./settings";
|
import * as settings from "./settings";
|
||||||
import * as settings_panel_menu from "./settings_panel_menu";
|
import * as settings_panel_menu from "./settings_panel_menu";
|
||||||
|
@ -212,6 +213,7 @@ function do_hashchange_normal(from_reload) {
|
||||||
case "#organization":
|
case "#organization":
|
||||||
case "#settings":
|
case "#settings":
|
||||||
case "#about-zulip":
|
case "#about-zulip":
|
||||||
|
case "#scheduled":
|
||||||
blueslip.error("overlay logic skipped for: " + hash);
|
blueslip.error("overlay logic skipped for: " + hash);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -368,6 +370,10 @@ function do_hashchange_overlay(old_hash) {
|
||||||
if (base === "about-zulip") {
|
if (base === "about-zulip") {
|
||||||
about_zulip.launch();
|
about_zulip.launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (base === "scheduled") {
|
||||||
|
scheduled_messages_overlay_ui.launch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hashchanged(from_reload, e) {
|
function hashchanged(from_reload, e) {
|
||||||
|
|
|
@ -85,6 +85,10 @@ export function drafts_open(): boolean {
|
||||||
return open_overlay_name === "drafts";
|
return open_overlay_name === "drafts";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function scheduled_messages_open(): boolean {
|
||||||
|
return open_overlay_name === "scheduled";
|
||||||
|
}
|
||||||
|
|
||||||
export function active_modal(): string | undefined {
|
export function active_modal(): string | undefined {
|
||||||
if (!is_modal_open()) {
|
if (!is_modal_open()) {
|
||||||
blueslip.error("Programming error — Called active_modal when there is no modal open");
|
blueslip.error("Programming error — Called active_modal when there is no modal open");
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import $ from "jquery";
|
||||||
|
|
||||||
|
import * as channel from "./channel";
|
||||||
|
import * as compose from "./compose";
|
||||||
|
import * as compose_actions from "./compose_actions";
|
||||||
|
import * as compose_fade from "./compose_fade";
|
||||||
|
import * as compose_ui from "./compose_ui";
|
||||||
|
import * as narrow from "./narrow";
|
||||||
|
import * as overlays from "./overlays";
|
||||||
|
import * as people from "./people";
|
||||||
|
import * as popover_menus from "./popover_menus";
|
||||||
|
|
||||||
|
// This is only updated when user opens the scheduled messages overlay.
|
||||||
|
export let scheduled_messages_data = [];
|
||||||
|
|
||||||
|
export function override_scheduled_messages_data(data) {
|
||||||
|
scheduled_messages_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function edit_scheduled_message(scheduled_msg_id) {
|
||||||
|
const scheduled_msg = scheduled_messages_data.find(
|
||||||
|
(msg) => msg.message_id === scheduled_msg_id,
|
||||||
|
);
|
||||||
|
|
||||||
|
let compose_args;
|
||||||
|
|
||||||
|
if (scheduled_msg.type === "stream") {
|
||||||
|
compose_args = {
|
||||||
|
type: "stream",
|
||||||
|
stream: scheduled_msg.stream_name,
|
||||||
|
topic: scheduled_msg.topic,
|
||||||
|
content: scheduled_msg.content,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const recipient_emails = [];
|
||||||
|
if (scheduled_msg.to) {
|
||||||
|
for (const recipient_id of scheduled_msg.to) {
|
||||||
|
recipient_emails.push(people.get_by_user_id(recipient_id).email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compose_args = {
|
||||||
|
type: scheduled_msg.type,
|
||||||
|
private_message_recipient: recipient_emails.join(","),
|
||||||
|
content: scheduled_msg.content,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compose_args.type === "stream") {
|
||||||
|
narrow.activate(
|
||||||
|
[
|
||||||
|
{operator: "stream", operand: compose_args.stream},
|
||||||
|
{operator: "topic", operand: compose_args.topic},
|
||||||
|
],
|
||||||
|
{trigger: "edit scheduled message"},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
narrow.activate([{operator: "pm-with", operand: compose_args.private_message_recipient}], {
|
||||||
|
trigger: "edit scheduled message",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
overlays.close_overlay("scheduled");
|
||||||
|
compose_fade.clear_compose();
|
||||||
|
compose.clear_preview_area();
|
||||||
|
compose_actions.start(compose_args.type, compose_args);
|
||||||
|
compose_ui.autosize_textarea($("#compose-textarea"));
|
||||||
|
$("#compose-textarea").attr("data-scheduled-message-id", scheduled_msg_id);
|
||||||
|
popover_menus.show_schedule_confirm_button(scheduled_msg.formatted_send_at_time, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function delete_scheduled_message(scheduled_msg_id) {
|
||||||
|
channel.del({
|
||||||
|
url: "/json/scheduled_messages/" + scheduled_msg_id,
|
||||||
|
success() {
|
||||||
|
// TODO: Do this via events received from the server in server_events_dispatch.
|
||||||
|
if (overlays.scheduled_messages_open()) {
|
||||||
|
$(
|
||||||
|
`#scheduled_messages_overlay .scheduled-message-row[data-message-id=${scheduled_msg_id}]`,
|
||||||
|
).remove();
|
||||||
|
}
|
||||||
|
if ($("#compose-textarea").attr("data-scheduled-message-id")) {
|
||||||
|
const compose_scheduled_msg_id = $("#compose-textarea").attr(
|
||||||
|
"data-scheduled-message-id",
|
||||||
|
);
|
||||||
|
// If user deleted the scheduled message which is being edited in compose, we clear
|
||||||
|
// the scheduled message id from there which converts this editing state into a normal
|
||||||
|
// schedule message state. So, clicking "Schedule" will now create a new scheduled message.
|
||||||
|
if (compose_scheduled_msg_id === scheduled_msg_id) {
|
||||||
|
$("#compose-textarea").removeAttr("data-scheduled-message-id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function delete_scheduled_message_if_sent_directly() {
|
||||||
|
// Delete old scheduled message if it was sent.
|
||||||
|
if ($("#compose-textarea").attr("data-scheduled-message-id")) {
|
||||||
|
delete_scheduled_message($("#compose-textarea").attr("data-scheduled-message-id"));
|
||||||
|
$("#compose-textarea").removeAttr("data-scheduled-message-id");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
import * as date_fns from "date-fns";
|
||||||
|
import $ from "jquery";
|
||||||
|
|
||||||
|
import render_scheduled_message from "../templates/scheduled_message.hbs";
|
||||||
|
import render_scheduled_messages_overlay from "../templates/scheduled_messages_overlay.hbs";
|
||||||
|
|
||||||
|
import * as blueslip from "./blueslip";
|
||||||
|
import * as browser_history from "./browser_history";
|
||||||
|
import * as channel from "./channel";
|
||||||
|
import * as loading from "./loading";
|
||||||
|
import * as overlays from "./overlays";
|
||||||
|
import * as people from "./people";
|
||||||
|
import * as scheduled_messages from "./scheduled_messages";
|
||||||
|
import * as stream_color from "./stream_color";
|
||||||
|
import * as stream_data from "./stream_data";
|
||||||
|
import * as timerender from "./timerender";
|
||||||
|
|
||||||
|
function hide_loading_indicator() {
|
||||||
|
loading.destroy_indicator($("#scheduled_messages_overlay .loading-indicator"));
|
||||||
|
$(".scheduled-messages-loading").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function format(scheduled_messages) {
|
||||||
|
const formatted_msgs = [];
|
||||||
|
for (const msg of scheduled_messages) {
|
||||||
|
const msg_render_context = {...msg};
|
||||||
|
if (msg.type === "stream") {
|
||||||
|
msg_render_context.is_stream = true;
|
||||||
|
msg_render_context.stream_id = msg.to[0];
|
||||||
|
msg_render_context.stream_name = stream_data.maybe_get_stream_name(
|
||||||
|
msg_render_context.stream_id,
|
||||||
|
);
|
||||||
|
const color = stream_data.get_color(msg_render_context.stream_name);
|
||||||
|
msg_render_context.recipient_bar_color = stream_color.get_recipient_bar_color(color);
|
||||||
|
msg_render_context.stream_privacy_icon_color =
|
||||||
|
stream_color.get_stream_privacy_icon_color(color);
|
||||||
|
} else {
|
||||||
|
msg_render_context.is_stream = false;
|
||||||
|
msg_render_context.recipients = people.get_recipients(msg.to.join(","));
|
||||||
|
}
|
||||||
|
const time = new Date(msg.deliver_at);
|
||||||
|
msg_render_context.full_date_time = timerender.get_full_datetime(time);
|
||||||
|
msg_render_context.formatted_send_at_time = date_fns.format(time, "MMM d yyyy h:mm a");
|
||||||
|
formatted_msgs.push(msg_render_context);
|
||||||
|
}
|
||||||
|
return formatted_msgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function launch() {
|
||||||
|
$("#scheduled_messages_overlay_container").empty();
|
||||||
|
$("#scheduled_messages_overlay_container").append(render_scheduled_messages_overlay());
|
||||||
|
overlays.open_overlay({
|
||||||
|
name: "scheduled",
|
||||||
|
$overlay: $("#scheduled_messages_overlay"),
|
||||||
|
on_close() {
|
||||||
|
browser_history.exit_overlay();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
loading.make_indicator($("#scheduled_messages_overlay .loading-indicator"), {
|
||||||
|
abs_positioned: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
channel.get({
|
||||||
|
url: "/json/scheduled_messages",
|
||||||
|
success(data) {
|
||||||
|
hide_loading_indicator();
|
||||||
|
if (data.scheduled_messages.length === 0) {
|
||||||
|
$(".no-overlay-messages").show();
|
||||||
|
} else {
|
||||||
|
// Saving formatted data is helpful when user is trying to edit a scheduled message.
|
||||||
|
scheduled_messages.override_scheduled_messages_data(
|
||||||
|
format(data.scheduled_messages),
|
||||||
|
);
|
||||||
|
const rendered_list = render_scheduled_message({
|
||||||
|
scheduled_messages_data: scheduled_messages.scheduled_messages_data,
|
||||||
|
});
|
||||||
|
const $messages_list = $("#scheduled_messages_overlay .overlay-messages-list");
|
||||||
|
$messages_list.append(rendered_list);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error(xhr) {
|
||||||
|
hide_loading_indicator();
|
||||||
|
blueslip.error(xhr);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initialize() {
|
||||||
|
$("body").on("click", ".scheduled-message-row .restore-overlay-message", (e) => {
|
||||||
|
let scheduled_msg_id = $(e.currentTarget)
|
||||||
|
.closest(".scheduled-message-row")
|
||||||
|
.attr("data-message-id");
|
||||||
|
scheduled_msg_id = Number.parseInt(scheduled_msg_id, 10);
|
||||||
|
scheduled_messages.edit_scheduled_message(scheduled_msg_id);
|
||||||
|
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("body").on("click", ".scheduled-message-row .delete-overlay-message", (e) => {
|
||||||
|
const scheduled_msg_id = $(e.currentTarget)
|
||||||
|
.closest(".scheduled-message-row")
|
||||||
|
.attr("data-message-id");
|
||||||
|
scheduled_messages.delete_scheduled_message(scheduled_msg_id);
|
||||||
|
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
}
|
|
@ -72,6 +72,7 @@ import * as reload from "./reload";
|
||||||
import * as rendered_markdown from "./rendered_markdown";
|
import * as rendered_markdown from "./rendered_markdown";
|
||||||
import * as resize from "./resize";
|
import * as resize from "./resize";
|
||||||
import * as rows from "./rows";
|
import * as rows from "./rows";
|
||||||
|
import * as scheduled_messages_overlay_ui from "./scheduled_messages_overlay_ui";
|
||||||
import * as scroll_bar from "./scroll_bar";
|
import * as scroll_bar from "./scroll_bar";
|
||||||
import * as search from "./search";
|
import * as search from "./search";
|
||||||
import * as search_pill_widget from "./search_pill_widget";
|
import * as search_pill_widget from "./search_pill_widget";
|
||||||
|
@ -647,6 +648,7 @@ export function initialize_everything() {
|
||||||
spoilers.initialize();
|
spoilers.initialize();
|
||||||
lightbox.initialize();
|
lightbox.initialize();
|
||||||
click_handlers.initialize();
|
click_handlers.initialize();
|
||||||
|
scheduled_messages_overlay_ui.initialize();
|
||||||
copy_and_paste.initialize();
|
copy_and_paste.initialize();
|
||||||
overlays.initialize();
|
overlays.initialize();
|
||||||
invite.initialize();
|
invite.initialize();
|
||||||
|
|
|
@ -1264,6 +1264,7 @@
|
||||||
background-color: hsl(212deg 28% 18%);
|
background-color: hsl(212deg 28% 18%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scheduled-messages-loading-logo,
|
||||||
.alert-zulip-logo,
|
.alert-zulip-logo,
|
||||||
.top-messages-logo,
|
.top-messages-logo,
|
||||||
.bottom-messages-logo {
|
.bottom-messages-logo {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#scheduled_messages_overlay_container {
|
||||||
|
.scheduled-messages-loading {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
grid-row-start: 1;
|
||||||
|
grid-column-start: 1;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-overlay-messages {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -201,6 +201,7 @@ p.n-margin {
|
||||||
padding-top: var(--header-padding-bottom);
|
padding-top: var(--header-padding-bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scheduled-messages-loading-logo,
|
||||||
.alert-zulip-logo,
|
.alert-zulip-logo,
|
||||||
.top-messages-logo,
|
.top-messages-logo,
|
||||||
.bottom-messages-logo {
|
.bottom-messages-logo {
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
{{#each scheduled_messages_data}}
|
||||||
|
<div class="scheduled-message-row overlay-message-row" data-message-id="{{message_id}}">
|
||||||
|
<div class="overlay-message-info-box" tabindex="0">
|
||||||
|
{{#if is_stream}}
|
||||||
|
<div class="message_header message_header_stream">
|
||||||
|
<div class="message-header-contents" style="background: {{recipient_bar_color}};">
|
||||||
|
<div class="message_label_clickable stream_label">
|
||||||
|
<span class="stream-privacy-modified-color-{{stream_id}} stream-privacy filter-icon" style="color: {{stream_privacy_icon_color}}">
|
||||||
|
{{> stream_privacy}}
|
||||||
|
</span>
|
||||||
|
{{stream_name}}
|
||||||
|
</div>
|
||||||
|
<span class="stream_topic_separator"><i class="zulip-icon zulip-icon-chevron-right"></i></span>
|
||||||
|
<span class="stream_topic">
|
||||||
|
<div class="message_label_clickable narrows_by_topic">
|
||||||
|
{{topic}}
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span class="recipient_bar_controls"></span>
|
||||||
|
<div class="recipient_row_date">{{ formatted_send_at_time }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="message_header message_header_private_message">
|
||||||
|
<div class="message-header-contents">
|
||||||
|
<div class="message_label_clickable stream_label">
|
||||||
|
<span class="private_message_header_icon"><i class="zulip-icon zulip-icon-user"></i></span>
|
||||||
|
{{t "You and {recipients}" }}
|
||||||
|
</div>
|
||||||
|
<div class="recipient_row_date">{{ formatted_send_at_time }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div class="message_row{{^is_stream}} private-message{{/is_stream}}" role="listitem">
|
||||||
|
<div class="messagebox">
|
||||||
|
<div class="messagebox-content">
|
||||||
|
<div class="message_top_line">
|
||||||
|
<div class="overlay_message_controls">
|
||||||
|
<i class="fa fa-pencil fa-lg restore-overlay-message tippy-zulip-tooltip" aria-hidden="true" data-tooltip-template-id="restore-scheduled-message-tooltip-template"></i>
|
||||||
|
<template id="restore-scheduled-message-tooltip-template">
|
||||||
|
{{t 'Edit or reschedule message' }}
|
||||||
|
{{tooltip_hotkey_hints "Enter"}}
|
||||||
|
</template>
|
||||||
|
<i class="fa fa-trash-o fa-lg delete-overlay-message tippy-zulip-tooltip" aria-hidden="true" data-tooltip-template-id="delete-scheduled-message-tooltip-template"></i>
|
||||||
|
<template id="delete-scheduled-message-tooltip-template">
|
||||||
|
{{t 'Delete scheduled message' }}
|
||||||
|
{{tooltip_hotkey_hints "Backspace"}}
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="message_content rendered_markdown restore-overlay-message" title="{{t 'Edit or reschedule message' }}">{{rendered_markdown rendered_content}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<div id="scheduled_messages_overlay" class="overlay new-style" data-overlay="scheduled">
|
||||||
|
<div class="flex overlay-content">
|
||||||
|
<div class="overlay-messages-container modal-bg">
|
||||||
|
<div class="overlay-messages-header">
|
||||||
|
<h1>{{t 'Scheduled messages' }}</h1>
|
||||||
|
<div class="exit">
|
||||||
|
<span class="exit-sign">×</span>
|
||||||
|
</div>
|
||||||
|
<div class="removed-drafts">
|
||||||
|
{{#tr}}
|
||||||
|
Click on the pencil (<z-pencil-icon></z-pencil-icon>) icon to reschedule a message.
|
||||||
|
{{#*inline "z-pencil-icon"}}<i class="fa fa-pencil"></i>{{/inline}}
|
||||||
|
{{/tr}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="scheduled-messages-loading">
|
||||||
|
<div class="scheduled-messages-loading-logo">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 773.12 773.12">
|
||||||
|
<circle cx="386.56" cy="386.56" r="386.56"></circle>
|
||||||
|
<path d="M566.66 527.25c0 33.03-24.23 60.05-53.84 60.05H260.29c-29.61 0-53.84-27.02-53.84-60.05 0-20.22 9.09-38.2 22.93-49.09l134.37-120c2.5-2.14 5.74 1.31 3.94 4.19l-49.29 98.69c-1.38 2.76.41 6.16 3.25 6.16h191.18c29.61 0 53.83 27.03 53.83 60.05zm0-281.39c0 20.22-9.09 38.2-22.93 49.09l-134.37 120c-2.5 2.14-5.74-1.31-3.94-4.19l49.29-98.69c1.38-2.76-.41-6.16-3.25-6.16H260.29c-29.61 0-53.84-27.02-53.84-60.05s24.23-60.05 53.84-60.05h252.54c29.61 0 53.83 27.02 53.83 60.05z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="loading-indicator"></div>
|
||||||
|
</div>
|
||||||
|
<div class="overlay-messages-list">
|
||||||
|
<div class="no-overlay-messages">
|
||||||
|
{{t 'No scheduled messages.'}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue