archive: Remove non-functional archive code.

This removes a bunch of non-functional duplicate JavaScript, HTML, and
CSS that was interfering with maintenance on the functional originals,
because it was never clear how to update the duplicates or how to
check that you’d updated the duplicates correctly.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2021-07-27 13:45:06 -07:00 committed by Anders Kaseorg
parent 3531463ac9
commit 17749cb608
14 changed files with 2 additions and 599 deletions

View File

@ -1,148 +0,0 @@
import {format, isSameDay} from "date-fns";
import $ from "jquery";
import _ from "lodash";
import render_archive_message_group from "../templates/archive_message_group.hbs";
import * as color_data from "./color_data";
import * as floating_recipient_bar from "./floating_recipient_bar";
import * as timerender from "./timerender";
function should_separate_into_groups(current_msg_time, next_msg_time) {
return isSameDay(current_msg_time * 1000, next_msg_time * 1000);
}
function all_message_timestamps_to_human_readable() {
$(".message_time").each(function () {
$(this).text(format(Number.parseInt($(this).text(), 10) * 1000, "h:mm a"));
});
}
export function initialize() {
const all_message_groups = [];
let current_message_group = {};
const today = new Date();
const recipient_and_topic = $("#display_recipient").html();
const stream_name = recipient_and_topic.split("-")[0];
const topic = recipient_and_topic.split("-")[1];
const recipient_color = color_data.pick_color();
current_message_group.message_containers = [];
current_message_group.show_group_date_divider = false;
current_message_group.display_recipient = stream_name;
current_message_group.topic = topic;
current_message_group.background_color = recipient_color;
function separate_into_groups(current_message_row, cur_msg_time, next_msg_time) {
const time = new Date(next_msg_time * 1000);
const prev_time = new Date(cur_msg_time * 1000);
current_message_group.message_containers.push(current_message_row[0].outerHTML);
const date_element = timerender.render_date(prev_time, undefined, today)[0];
current_message_group.date = date_element.outerHTML;
all_message_groups.push(current_message_group);
current_message_group = {};
current_message_group.message_containers = [];
current_message_group.group_date_divider_html = timerender.render_date(
time,
prev_time,
today,
)[0].outerHTML;
current_message_group.show_group_date_divider = true;
current_message_group.display_recipient = stream_name;
current_message_group.topic = topic;
current_message_group.background_color = recipient_color;
}
$(".message_row").each(function () {
const current_message_row = $(this);
const cur_msg_time = Number.parseInt(
current_message_row.find(".message_time").first().html(),
10,
);
const next_msg_time = Number.parseInt(
current_message_row.next().find(".message_time").first().html(),
10,
);
if (current_message_row.next().length === 0) {
separate_into_groups(current_message_row, cur_msg_time);
return;
}
if (should_separate_into_groups(cur_msg_time, next_msg_time)) {
separate_into_groups(current_message_row, cur_msg_time, next_msg_time);
return;
}
current_message_group.message_containers.push(current_message_row[0].outerHTML);
const time = new Date(cur_msg_time * 1000);
const date_element = timerender.render_date(time, undefined, today)[0];
current_message_group.date = date_element.outerHTML;
});
const context = {
message_groups: all_message_groups,
};
const message_groups_html = render_archive_message_group(context);
$(".message_row").each(function () {
$(this).detach();
});
$(".message_table").prepend(message_groups_html);
$(".messagebox").css("box-shadow", "inset 2px 0px 0px 0px " + recipient_color);
$("#display_recipient").remove();
// Fixing include_sender after rendering groups.
let prev_sender;
$(".recipient_row").each(function () {
if (prev_sender !== undefined) {
const first_group_msg = $(this).find(".message_row").first();
const message_sender = first_group_msg.find(".message_sender");
if (!message_sender.find(".inline_profile_picture").length) {
message_sender.replaceWith(prev_sender.clone());
}
}
const all_senders = $(this).find(".message_sender").has(".inline_profile_picture");
prev_sender = all_senders.last();
});
$(".app").scrollTop($(".app").height());
all_message_timestamps_to_human_readable();
}
export const current_msg_list = {
selected_row() {
return $(".message_row").last();
},
};
export const rows = {
get_message_recipient_row(message_row) {
return $(message_row).parent(".recipient_row");
},
first_message_in_group(message_group) {
return $("div.message_row", message_group).first();
},
id(message_row) {
return Number.parseFloat(message_row.attr("zid"));
},
};
let scroll_timer;
function scroll_finish() {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(floating_recipient_bar.update, 100);
}
$(() => {
$.fn.safeOuterHeight = function (...args) {
return this.outerHeight(...args) || 0;
};
$.fn.safeOuterWidth = function (...args) {
return this.outerWidth(...args) || 0;
};
$(".app").on(
"scroll",
_.throttle(() => {
scroll_finish();
}, 50),
);
initialize();
});

View File

@ -1,44 +0,0 @@
body {
font-family: "Source Sans 3", sans-serif;
font-size: 14px;
}
.header {
padding: 5px 0 5px 15px;
line-height: 10px;
}
.header-main .logo {
margin-top: 5px;
.brand-logo {
margin-top: 4px;
}
}
.message_area_padder {
margin-top: 60px;
}
.top-links {
position: relative;
right: 20px;
margin-top: 12px;
}
@media (width <= 500px) {
.header {
height: 40px;
line-height: 10px;
}
.header-main .logo {
margin-top: 5px;
.brand-logo {
margin-top: 4px;
}
}
#floating_recipient_bar {
top: 50px;
}
}

View File

@ -1,17 +0,0 @@
{{#each message_groups}}
{{#with this}}
{{#if show_group_date_divider}}
<div class="date_row no-select">{{{group_date_divider_html}}}</div>
{{/if}}
<div class="recipient_row">
{{> archive_recipient_row }}
{{#each message_containers}}
{{{ this }}}
{{/each}}
</div>
{{/with}}
{{/each}}

View File

@ -1,23 +0,0 @@
<div class="message_header message_header_stream right_part">
<div class="message-header-wrapper">
<div class="message-header-contents">
{{! stream link }}
<a class="message_label_clickable narrows_by_recipient stream_label {{color_class}}"
style="background: {{background_color}}; border-left-color: {{background_color}};"
href="{{stream_url}}"
title="{{#tr}}Narrow to stream &quot;{display_recipient}&quot;{{/tr}}">
{{display_recipient}}
</a>
{{! topic stuff }}
<span class="stream_topic">
{{! topic link }}
<a class="message_label_clickable narrows_by_topic"
href="{{topic_url}}"
title="{{#tr}}Narrow to stream &quot;{display_recipient}&quot;, topic &quot;{topic}&quot;{{/tr}}">
{{topic}}
</a>
</span>
<span class="recipient_row_date">{{{date}}}</span>
</div>
</div>
</div>

View File

@ -1,18 +0,0 @@
<div class="message_area_padder message_list" id="main_div">
{% if is_web_public and message_list %}
<div class="message_table focused_table" id="zhome">
<span id="display_recipient">{{ stream }}-{{ topic }}</span>
{% for msg in message_list %}
{{ msg|safe }}
{% endfor %}
</div>
{% elif is_web_public %}
<p>
This topic does not exist.
</p>
{% else %}
<p>
This stream does not exist.
</p>
{% endif %}
</div>

View File

@ -1,40 +0,0 @@
{% extends "zerver/base.html" %}
{% set entrypoint = "archive" %}
{% block customhead %}
<style>
.portico-header {
padding-bottom: 0px;
padding-top: 10px;
padding-left: 5px;
width: auto;
}
</style>
{% endblock %}
{% block content %}
{% include 'zerver/portico-header.html' %}
<div class="app">
<div class="app-main">
<div class="column-left">
{% include "zerver/archive/left_sidebar.html" %}
</div>
<div class="column-middle">
<div class="column-middle-inner tab-content">
<div class="fixed-app" id="floating_recipient_bar">
<div class="app-main recipient_bar_content">
<div class="column-middle column-overlay recipient-bar-main">
<div class="floating_recipient">
<div id="current_label_stream" class="recipient_row">
<div class="message_label_clickable message_header message_header_stream right_part"></div>
</div>
</div>
</div>
</div>
</div>
{% include "zerver/archive/home.html" %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,2 +0,0 @@
<div class="left-sidebar" id="left-sidebar">
</div>

View File

@ -1,36 +0,0 @@
<div class="message_row {% if include_sender %} include-sender {% endif %}">
<div class="messagebox">
<div class="messagebox-content">
<div class="message_top_line">
<span class="message_sender{% if status_message %} sender_info_hover{% endif %} no-select">
{% if include_sender %}
<div class="inline_profile_picture">
<img src="{{ avatar_url }}" alt="" class="no-drag"/>
</div>
{% if status_message %}
<span class="sender-status">
<span class="sender_name-in-status">{{ sender_full_name }}</span>
{% if sender_is_bot %}
<i class="zulip-icon zulip-icon-bot" aria-hidden="true"></i>
{% endif %}
<span class="status-message">
{{ status_message }}
</span>
</span>
{% else %}
<span class="sender_name auto-select">{{ sender_full_name }}</span>
{% if sender_is_bot %}
<i class="zulip-icon zulip-icon-bot" aria-hidden="true"></i>
{% endif %}
{% endif %}
{% endif %}
</span>
<span class="message_time{% if status_message %} status-time{% endif %}">{{ timestampstr }}</span>
</div>
{% if not status_message %}
<div class="message_content">{{ message_content|safe }}</div>
{% endif %}
</div>
</div>
</div>

View File

@ -108,12 +108,7 @@ def check_html_templates(templates: Iterable[str], all_dups: bool, fix: bool) ->
print(fn)
return bad_ids_dict
bad_ids_list: List[str] = []
archive_templates = [fn for fn in templates if "templates/zerver/archive" in fn]
templates = [fn for fn in templates if "templates/zerver/archive" not in fn]
bad_ids_list += list(check_for_duplicate_ids(archive_templates).keys())
bad_ids_list += list(check_for_duplicate_ids(templates).keys())
bad_ids_list = list(check_for_duplicate_ids(templates).keys())
if bad_ids_list:
print("Exiting--please clean up all duplicates before running this again.")

View File

@ -5,21 +5,6 @@
"./static/js/analytics/activity",
"./static/styles/portico/activity.css"
],
"archive": [
"./static/js/bundles/portico",
"./static/js/archive",
"./static/js/colorspace",
"./static/js/floating_recipient_bar",
"./static/js/timerender",
"./static/js/templates",
"./static/js/stream_color",
"./static/js/scroll_bar",
"katex/dist/katex.css",
"./static/styles/rendered_markdown.css",
"./static/styles/zulip.css",
"./static/styles/portico/archive.css",
"./static/generated/emoji-styles/google-sprite.css"
],
"billing": [
"./static/js/bundles/portico",
"./static/js/portico/landing-page",

View File

@ -7298,7 +7298,7 @@ def get_occupied_streams(realm: Realm) -> QuerySet:
return occupied_streams
def get_web_public_streams(realm: Realm) -> List[Dict[str, Any]]:
def get_web_public_streams(realm: Realm) -> List[Dict[str, Any]]: # nocoverage
query = Stream.objects.filter(realm=realm, deactivated=False, is_web_public=True)
streams = Stream.get_client_data(query)
return streams

View File

@ -1,156 +0,0 @@
from django.http import HttpResponse
from zerver.lib.actions import (
do_deactivate_stream,
do_make_stream_web_public,
get_web_public_streams,
get_web_public_subs,
)
from zerver.lib.test_classes import ZulipTestCase
from zerver.models import get_realm
class GlobalPublicStreamTest(ZulipTestCase):
def test_non_existant_stream_id(self) -> None:
# Here we use a relatively big number as stream id assuming such an id
# won't exist in the test DB.
result = self.client_get("/archive/streams/100000000/topics/TopicGlobal")
self.assert_in_success_response(["This stream does not exist."], result)
def test_non_web_public_stream(self) -> None:
test_stream = self.make_stream("Test public archives")
result = self.client_get(
"/archive/streams/" + str(test_stream.id) + "/topics/notpublicglobalstream",
)
self.assert_in_success_response(["This stream does not exist."], result)
def test_non_existant_topic(self) -> None:
test_stream = self.make_stream("Test public archives")
do_make_stream_web_public(test_stream)
result = self.client_get(
"/archive/streams/" + str(test_stream.id) + "/topics/nonexistenttopic",
)
self.assert_in_success_response(["This topic does not exist."], result)
def test_web_public_stream_topic(self) -> None:
test_stream = self.make_stream("Test public archives")
do_make_stream_web_public(test_stream)
def send_msg_and_get_result(msg: str) -> HttpResponse:
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
msg,
"TopicGlobal",
)
return self.client_get(
"/archive/streams/" + str(test_stream.id) + "/topics/TopicGlobal",
)
result = send_msg_and_get_result("Test message 1")
self.assert_in_success_response(["Test message 1"], result)
result = send_msg_and_get_result("/me goes testing.")
self.assert_in_success_response(["goes testing."], result)
def test_get_web_public_streams(self) -> None:
realm = get_realm("zulip")
public_streams = get_web_public_streams(realm)
self.assert_length(public_streams, 1)
public_stream = public_streams[0]
self.assertEqual(public_stream["name"], "Rome")
info = get_web_public_subs(realm)
self.assert_length(info.subscriptions, 1)
self.assertEqual(info.subscriptions[0]["name"], "Rome")
self.assert_length(info.unsubscribed, 0)
self.assert_length(info.never_subscribed, 0)
# Now add a second public stream
test_stream = self.make_stream("Test public archives")
do_make_stream_web_public(test_stream)
public_streams = get_web_public_streams(realm)
self.assert_length(public_streams, 2)
info = get_web_public_subs(realm)
self.assert_length(info.subscriptions, 2)
self.assert_length(info.unsubscribed, 0)
self.assert_length(info.never_subscribed, 0)
self.assertNotEqual(info.subscriptions[0]["color"], info.subscriptions[1]["color"])
do_deactivate_stream(test_stream, acting_user=None)
public_streams = get_web_public_streams(realm)
self.assert_length(public_streams, 1)
info = get_web_public_subs(realm)
self.assert_length(info.subscriptions, 1)
self.assert_length(info.unsubscribed, 0)
self.assert_length(info.never_subscribed, 0)
class WebPublicTopicHistoryTest(ZulipTestCase):
def test_non_existant_stream_id(self) -> None:
result = self.client_get("/archive/streams/100000000/topics")
self.assert_json_success(result)
history = result.json()["topics"]
self.assertEqual(history, [])
def test_non_web_public_stream(self) -> None:
test_stream = self.make_stream("Test public archives")
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
"Test message",
"TopicGlobal",
)
result = self.client_get(
"/archive/streams/" + str(test_stream.id) + "/topics",
)
self.assert_json_success(result)
history = result.json()["topics"]
self.assertEqual(history, [])
def test_web_public_stream(self) -> None:
test_stream = self.make_stream("Test public archives")
do_make_stream_web_public(test_stream)
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
"Test message 3",
topic_name="first_topic",
)
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
"Test message",
topic_name="TopicGlobal",
)
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
"Test message 2",
topic_name="topicglobal",
)
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
"Test message 3",
topic_name="second_topic",
)
self.send_stream_message(
self.example_user("iago"),
"Test public archives",
"Test message 4",
topic_name="TopicGlobal",
)
result = self.client_get(
"/archive/streams/" + str(test_stream.id) + "/topics",
)
self.assert_json_success(result)
history = result.json()["topics"]
self.assert_length(history, 3)
# Should be sorted with latest topic first
self.assertEqual(history[0]["name"], "TopicGlobal")
self.assertEqual(history[1]["name"], "second_topic")
self.assertEqual(history[2]["name"], "first_topic")

View File

@ -1,89 +0,0 @@
from typing import List, Optional
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render
from django.template import loader
from zerver.lib.avatar import get_gravatar_url
from zerver.lib.exceptions import JsonableError
from zerver.lib.request import get_request_notes
from zerver.lib.response import json_success
from zerver.lib.streams import access_web_public_stream
from zerver.lib.timestamp import datetime_to_timestamp
from zerver.lib.topic import get_topic_history_for_public_stream, messages_for_topic
from zerver.models import Message, UserProfile
def archive(request: HttpRequest, stream_id: int, topic_name: str) -> HttpResponse:
def get_response(
rendered_message_list: List[str], is_web_public: bool, stream_name: str
) -> HttpResponse:
return render(
request,
"zerver/archive/index.html",
context={
"is_web_public": is_web_public,
"message_list": rendered_message_list,
"stream": stream_name,
"topic": topic_name,
},
)
try:
realm = get_request_notes(request).realm
assert realm is not None
stream = access_web_public_stream(stream_id, realm)
except JsonableError:
return get_response([], False, "")
all_messages = list(
messages_for_topic(
stream_recipient_id=stream.recipient_id,
topic_name=topic_name,
)
.select_related("sender")
.order_by("date_sent"),
)
if not all_messages:
return get_response([], True, stream.name)
rendered_message_list = []
prev_sender: Optional[UserProfile] = None
for msg in all_messages:
include_sender = False
status_message = Message.is_status_message(msg.content, msg.rendered_content)
if not prev_sender or prev_sender != msg.sender or status_message:
if status_message:
prev_sender = None
else:
prev_sender = msg.sender
include_sender = True
if status_message:
status_message = msg.rendered_content[4 + 3 : -4]
context = {
"sender_full_name": msg.sender.full_name,
"timestampstr": datetime_to_timestamp(
msg.last_edit_time if msg.last_edit_time else msg.date_sent
),
"message_content": msg.rendered_content,
"avatar_url": get_gravatar_url(msg.sender.delivery_email, 1),
"include_sender": include_sender,
"status_message": status_message,
}
rendered_msg = loader.render_to_string("zerver/archive/single_message.html", context)
rendered_message_list.append(rendered_msg)
return get_response(rendered_message_list, True, stream.name)
def get_web_public_topics_backend(request: HttpRequest, stream_id: int) -> HttpResponse:
try:
realm = get_request_notes(request).realm
assert realm is not None
stream = access_web_public_stream(stream_id, realm)
except JsonableError:
return json_success(dict(topics=[]))
result = get_topic_history_for_public_stream(recipient_id=stream.recipient_id)
return json_success(dict(topics=result))

View File

@ -18,7 +18,6 @@ from zerver.lib.integrations import WEBHOOK_INTEGRATIONS
from zerver.lib.rest import rest_path
from zerver.tornado.views import cleanup_event_queue, get_events, get_events_internal, notify
from zerver.views.alert_words import add_alert_words, list_alert_words, remove_alert_words
from zerver.views.archive import archive, get_web_public_topics_backend
from zerver.views.attachments import list_by_user, remove
from zerver.views.auth import (
api_fetch_api_key,
@ -590,9 +589,6 @@ i18n_urls = [
path("new/<creation_key>", create_realm, name="create_realm"),
# Realm reactivation
path("reactivate/<confirmation_key>", realm_reactivation, name="realm_reactivation"),
# Global public streams (Zulip's way of doing archives)
path("archive/streams/<int:stream_id>/topics/<topic_name>", archive),
path("archive/streams/<int:stream_id>/topics", get_web_public_topics_backend),
# Login/registration
path("register/", accounts_home, name="register"),
path("login/", login_page, {"template_name": "zerver/login.html"}, name="login_page"),