mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	recent_topics: Add functionality to sort rows via header.
Add custom sorting for stream and topic headers.
This commit is contained in:
		@@ -74,6 +74,16 @@ set_global('list_render', {
 | 
			
		||||
            formatted_topics.push(opts.modifier(item));
 | 
			
		||||
            opts.filter.predicate(item);
 | 
			
		||||
        }
 | 
			
		||||
        // Just for coverage, the mechanisms
 | 
			
		||||
        // are tested in list_render
 | 
			
		||||
        if (mapped_topic_values.length >= 2) {
 | 
			
		||||
            opts.sort_fields.stream_sort(mapped_topic_values[0], mapped_topic_values[1]);
 | 
			
		||||
            opts.sort_fields.stream_sort(mapped_topic_values[1], mapped_topic_values[0]);
 | 
			
		||||
            opts.sort_fields.stream_sort(mapped_topic_values[0], mapped_topic_values[0]);
 | 
			
		||||
            opts.sort_fields.topic_sort(mapped_topic_values[0], mapped_topic_values[1]);
 | 
			
		||||
            opts.sort_fields.topic_sort(mapped_topic_values[1], mapped_topic_values[0]);
 | 
			
		||||
            opts.sort_fields.topic_sort(mapped_topic_values[0], mapped_topic_values[0]);
 | 
			
		||||
        }
 | 
			
		||||
        return list_render;
 | 
			
		||||
    },
 | 
			
		||||
    hard_redraw: noop,
 | 
			
		||||
@@ -88,6 +98,7 @@ set_global('list_render', {
 | 
			
		||||
const stream1 = 1;
 | 
			
		||||
const stream2 = 2;
 | 
			
		||||
const stream3 = 3;
 | 
			
		||||
const stream4 = 4;
 | 
			
		||||
 | 
			
		||||
// Topics in the stream, all unread except topic1 & stream1.
 | 
			
		||||
const topic1 = "topic-1";  // No Other sender & read.
 | 
			
		||||
@@ -99,6 +110,7 @@ const topic6 = "topic-6";  // other sender
 | 
			
		||||
const topic7 = "topic-7";  // muted topic
 | 
			
		||||
const topic8 = "topic-8";
 | 
			
		||||
const topic9 = "topic-9";
 | 
			
		||||
const topic10 = "topic-10";
 | 
			
		||||
 | 
			
		||||
set_global('muting', {
 | 
			
		||||
    is_topic_muted: (stream_id, topic) => {
 | 
			
		||||
@@ -221,6 +233,16 @@ messages[9] = {
 | 
			
		||||
    type: 'stream',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// a message of stream4
 | 
			
		||||
messages[10] = {
 | 
			
		||||
    stream_id: stream4,
 | 
			
		||||
    stream: 'stream4',
 | 
			
		||||
    id: id += 1,
 | 
			
		||||
    topic: topic10,
 | 
			
		||||
    sender_id: sender1,
 | 
			
		||||
    type: 'stream',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function generate_topic_data(topic_info_array) {
 | 
			
		||||
    // Since most of the fields are common, this function helps generate fixtures
 | 
			
		||||
    // with non common fields.
 | 
			
		||||
@@ -355,6 +377,7 @@ run_test('test_filter_unread', () => {
 | 
			
		||||
 | 
			
		||||
    const row_data = generate_topic_data([
 | 
			
		||||
        // stream_id, topic, unread_count,  muted, participated
 | 
			
		||||
        [4, 'topic-10', 1, false, true],
 | 
			
		||||
        [1, 'topic-7', 1, true, true],
 | 
			
		||||
        [1, 'topic-6', 1, false, true],
 | 
			
		||||
        [1, 'topic-5', 1, false, true],
 | 
			
		||||
@@ -420,6 +443,7 @@ run_test('test_filter_participated', () => {
 | 
			
		||||
 | 
			
		||||
    const row_data = generate_topic_data([
 | 
			
		||||
        // stream_id, topic, unread_count,  muted, participated
 | 
			
		||||
        [4, 'topic-10', 1, false, true],
 | 
			
		||||
        [1, 'topic-7', 1, true, true],
 | 
			
		||||
        [1, 'topic-6', 1, false, true],
 | 
			
		||||
        [1, 'topic-5', 1, false, true],
 | 
			
		||||
@@ -499,19 +523,19 @@ run_test('basic assertions', () => {
 | 
			
		||||
    generate_topic_data([[1, 'topic-7', 1, false, true]]);
 | 
			
		||||
    rt.process_messages([messages[9]]);
 | 
			
		||||
    // Check for expected lengths.
 | 
			
		||||
    // total 7 topics, 1 muted
 | 
			
		||||
    assert.equal(all_topics.size, 7);
 | 
			
		||||
    // total 8 topics, 1 muted
 | 
			
		||||
    assert.equal(all_topics.size, 8);
 | 
			
		||||
    assert.equal(Array.from(all_topics.keys()).toString(),
 | 
			
		||||
                 '1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1');
 | 
			
		||||
                 '4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1');
 | 
			
		||||
 | 
			
		||||
    rt.process_message({
 | 
			
		||||
        type: 'private',
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Private msgs are not processed.
 | 
			
		||||
    assert.equal(all_topics.size, 7);
 | 
			
		||||
    assert.equal(all_topics.size, 8);
 | 
			
		||||
    assert.equal(Array.from(all_topics.keys()).toString(),
 | 
			
		||||
                 '1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1');
 | 
			
		||||
                 '4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1');
 | 
			
		||||
 | 
			
		||||
    // participated
 | 
			
		||||
    verify_topic_data(all_topics, stream1, topic1, messages[0].id, true);
 | 
			
		||||
@@ -533,7 +557,7 @@ run_test('basic assertions', () => {
 | 
			
		||||
 | 
			
		||||
    all_topics = rt.get();
 | 
			
		||||
    assert.equal(Array.from(all_topics.keys()).toString(),
 | 
			
		||||
                 '1:topic-3,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-2,1:topic-1');
 | 
			
		||||
                 '1:topic-3,4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-2,1:topic-1');
 | 
			
		||||
    verify_topic_data(all_topics, stream1, topic3, id, true);
 | 
			
		||||
 | 
			
		||||
    // Send new message to topic7 (muted)
 | 
			
		||||
@@ -548,7 +572,7 @@ run_test('basic assertions', () => {
 | 
			
		||||
 | 
			
		||||
    all_topics = rt.get();
 | 
			
		||||
    assert.equal(Array.from(all_topics.keys()).toString(),
 | 
			
		||||
                 '1:topic-7,1:topic-3,1:topic-6,1:topic-5,1:topic-4,1:topic-2,1:topic-1');
 | 
			
		||||
                 '1:topic-7,1:topic-3,4:topic-10,1:topic-6,1:topic-5,1:topic-4,1:topic-2,1:topic-1');
 | 
			
		||||
 | 
			
		||||
    // update_topic_is_muted now relies on external libraries completely
 | 
			
		||||
    // so we don't need to check anythere here.
 | 
			
		||||
@@ -607,7 +631,7 @@ run_test('test_topic_edit', () => {
 | 
			
		||||
 | 
			
		||||
    let all_topics = rt.get();
 | 
			
		||||
    assert.equal(Array.from(all_topics.keys()).toString(),
 | 
			
		||||
                 '1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1');
 | 
			
		||||
                 '4:topic-10,1:topic-7,1:topic-6,1:topic-5,1:topic-4,1:topic-3,1:topic-2,1:topic-1');
 | 
			
		||||
 | 
			
		||||
    ////////////////// test change topic //////////////////
 | 
			
		||||
    verify_topic_data(all_topics, stream1, topic6, messages[8].id, true);
 | 
			
		||||
 
 | 
			
		||||
@@ -249,6 +249,29 @@ exports.update_filters_view = function () {
 | 
			
		||||
    topics_widget.hard_redraw();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function stream_sort(a, b) {
 | 
			
		||||
    const a_stream = message_store.get(a.last_msg_id).stream;
 | 
			
		||||
    const b_stream = message_store.get(b.last_msg_id).stream;
 | 
			
		||||
    if (a_stream > b_stream) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else if (a_stream === b_stream) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function topic_sort(a, b) {
 | 
			
		||||
    const a_topic = message_store.get(a.last_msg_id).topic;
 | 
			
		||||
    const b_topic = message_store.get(b.last_msg_id).topic;
 | 
			
		||||
    if (a_topic > b_topic) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else if (a_topic === b_topic) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.complete_rerender = function () {
 | 
			
		||||
    if (!overlays.recent_topics_open()) {
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -272,6 +295,7 @@ exports.complete_rerender = function () {
 | 
			
		||||
 | 
			
		||||
    topics_widget = list_render.create(container, mapped_topic_values, {
 | 
			
		||||
        name: "recent_topics_table",
 | 
			
		||||
        parent_container: $("#recent_topics_table"),
 | 
			
		||||
        modifier: function (item) {
 | 
			
		||||
            return render_recent_topic_row(format_topic(item));
 | 
			
		||||
        },
 | 
			
		||||
@@ -282,6 +306,10 @@ exports.complete_rerender = function () {
 | 
			
		||||
                return !is_topic_hidden(topic_data);
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        sort_fields: {
 | 
			
		||||
            stream_sort: stream_sort,
 | 
			
		||||
            topic_sort: topic_sort,
 | 
			
		||||
        },
 | 
			
		||||
        html_selector: get_topic_row,
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -76,8 +76,6 @@
 | 
			
		||||
            position: sticky;
 | 
			
		||||
            top: 0;
 | 
			
		||||
            z-index: 1000;
 | 
			
		||||
            background-color: hsl(0, 0%, 27%);
 | 
			
		||||
            color: hsl(0, 0%, 100%);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #recent_topics_filter_buttons {
 | 
			
		||||
@@ -151,5 +149,42 @@
 | 
			
		||||
        .recent_avatars_others {
 | 
			
		||||
            background-color: hsl(205.2, 76.5%, 50%);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        thead th {
 | 
			
		||||
            background-color: inherit;
 | 
			
		||||
            color: inherit;
 | 
			
		||||
            border-top: 1px solid hsla(0, 0%, 0%, 0.2) !important;
 | 
			
		||||
            border-bottom: 1px solid hsla(0, 0%, 0%, 0.2) !important;
 | 
			
		||||
 | 
			
		||||
            &.active::after,
 | 
			
		||||
            &[data-sort]:hover::after {
 | 
			
		||||
                content: " \f0d8";
 | 
			
		||||
                white-space: pre;
 | 
			
		||||
                display: inline-block;
 | 
			
		||||
                position: absolute;
 | 
			
		||||
                padding-top: 3px;
 | 
			
		||||
                font: normal normal normal 12px/1 FontAwesome;
 | 
			
		||||
                font-size: inherit;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &.active {
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
                transition: opacity 100ms ease-out;
 | 
			
		||||
 | 
			
		||||
                &.descend::after {
 | 
			
		||||
                    content: " \f0d7";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &[data-sort]:hover {
 | 
			
		||||
                cursor: pointer;
 | 
			
		||||
                background-color: hsla(0, 0%, 0%, 0.05);
 | 
			
		||||
                transition: background-color 100ms ease-in-out;
 | 
			
		||||
 | 
			
		||||
                &:not(.active)::after {
 | 
			
		||||
                    opacity: 0.3;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,11 +11,11 @@
 | 
			
		||||
    <table class="table table-responsive table-hover">
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th>{{t 'Stream' }}</th>
 | 
			
		||||
                <th>{{t 'Topic' }}</th>
 | 
			
		||||
                <th data-sort="stream_sort">{{t 'Stream' }}</th>
 | 
			
		||||
                <th data-sort="topic_sort">{{t 'Topic' }}</th>
 | 
			
		||||
                <th>{{t 'Actions' }}</th>
 | 
			
		||||
                <th>{{t 'Participants' }}</th>
 | 
			
		||||
                <th>{{t 'Last message' }}</th>
 | 
			
		||||
                <th data-sort="numeric" data-sort-prop="last_msg_id" class="active descend">{{t 'Last message' }}</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user