This is preparation for our migration of our JS pipeline to webpack,
which includes as part of the process a hack of exporting globals via
the window object.
This commit makes it so that any query for
which we do a local filter leads to us
examining the full list of unread message
ids in our cache to find a potentially
unread message that passes the filter. This
can often allow us to more immediately
jump to a new narrow with an appropriately
selected message.
Fixes#9319
We want to be able to call get_first_unread_info() even
if we cannot apply a search locally. It was returning
the correct value before, but this change removes a
blueslip warning that will allow our callers to remove
some guard code in a subsequent commit.
We want to update message.submessages for new events, even
though our couple of widgets (poll/tictactoe) that can process
"update" events currently just apply events as "deltas"
to their current data.
This does fix a subtle issue where you may get incoming
events for a message that the client knows about but which
it hasn't yet activated as a widget. Up until now,
we've rarely seen the bug that's fixed here, since it's
usually the case that as soon as we receive a message, we
widgetize it right away.
The user can now specify the value while creating a stream.
An admin can later change it via `Change stream permissions`
modal. Add is_announcement_only to subscription type text.
For some reason in my original version I was sending both
content and data to the client for submessage events,
where data === JSON.parse(content). There's no reason
to not just let the client parse it, since the client
already does it for data that comes on the original
message, and since we might eventually have non-JSON
payloads.
The server still continues to validate that the payload
is JSON, and the client will blueslip if the server
regressses and sends bad JSON for some reason.
Fixes#3380.
The blueslip warning mentioned in #3380 were from paths ending at
people.email_list_to_user_ids_string. Some additional blueslip warnings
were raised after using that function.
Although we can put a validation check somewhere in the call stack of
people.email_list_to_user_ids_string, this function itself is used to
validate the operand by the higher order functions, so it wouldn't make
sense to put a validation check before that. Instead, removing the
blueslip warning altogether was chosen.
people.email_list_to_user_ids_string was replaced by
people.reply_to_to_user_ids_string which is a blueslip-free version
of the same. Other blueslip warnings were removed.
If atleast one of the private_message_recipients is invalid, compose
box will not be opened.
Thanks to Aastha Gupta <aastha.gupta4104@gmail.com> for some preliminary
work on this.
The Botserver uses section headers in the flaskbotrc to
determine which bot to run. Silently setting the section
headers to a bot's username is confusing and makes it
harder for Botserver users to figure out how to get the
Botserver to run the bots they want. This commit empties
all flaskbotrc section headers and thus makes the assignment
of bots explicit and mandatory.
Fixes#6515.
New suggestions for `sender:King ha` will respect spaces and the new
suggestion will be `Sent by King Hamlet <email>` instead of `Sent by King,
search for ha`. But if first term of sender operand is a valid user email,
tokens will be seperated by spaces. e.g `sender:hamlet@zulip.com abc`
will show `Sent by King Hamlet <email>, search for abc`.
This starts the concept of a schema checker, similar to
zerver/lib/validator.py on the server. We can use this
to validate incoming data. Our server should filter most
of our incoming data, but it's useful to have client-side
checking to defend against things like upgrade
regressions (i.e. what if we change the name of the field
on the server side without updating all client uses).
We have less urgency to test all templates now. The
most common error is probably unbalanced tags, and our
python-based template checker catches those problems
pretty well.
It's still possible to create bad templates, of course,
but the node tests have never been super deep at finding
semantic errors.
This is a trial to have the first reply hotspot in the bottom
whitespace (and stick there until "Got it!" is pressed).
Tweaked by tabbott to clean it up a bit. Still needs more work on the
visuals.
Fixes#9492.
`is` operator uses predefined categories. This commit
displays an invalid operand message if the operand does not fall into
any of these categories and the `is` operator is not at the last.
e.g. `is:abc sender:abc@zulipchat.com` will have `invalid abc operand
for has operator, sent by abc@zulipchat.com` as a prefix for all its
suggestions.
Fixes#9492.
Default suggestion e.g `abc messages` as a suggestion for `is:abc`
is not shown in a new suggestion. But if the is operator is already
present before any other operator, the default message text will be
used. e.g `is:abc sender:abc@zulipchat.com` will have all the suggestions
with the prefix `abc messages, sent by abc@zulipchat.com`.
`get_containing_suggestions` was used to get the operand suggestions
for the `has` operator. `get_special_filter_suggestions` is now used
to get both the operand and operator suggestions for `has`.
Partially fixes#9461.
Negated suggestion for both operand and operators are handle in
get_special_filter_suggestions. A bug is get_operator_suggestions
causing the removal of `-` symbol from the operand was also fixed.
Now that we've moved it into a bulleted set of options inside a modal,
there's no good reason to have separate variables for the corner cases
around who can manage a stream.
Our logic for stream_has_topics never accounted for
us creating essentially "empty" stream buckets that
don't have topics, but we recently added some code
related to unread counts that violated the original
assumptions of the code.
Now we check deeper into the stream bucket to find
actual topics.
This bug manifested in the left sidebar where users
were seeing streams as recently active just because
some muted topics had unread counts, when in fact
the stream was inactive for practical purposes.
Dropdown element for outgoing interface type was not showing correct
value, cause the way default value was set to dropdown was incorrect
(it should have been setting the selected parameter on the selected
option if it were going to be selected via the template code).
Fixes#9419.
This also updates node_tests to use new constructor which is uppercase,
and some properties that are changed to be more clear now, like
jsdom().defaultView which is meant to the window object is now called window.
Ref: https://github.com/jsdom/jsdom/blob/master/Changelog.md
When suggesting operators to chose, category wise suggestions are
shown instead of a single default suggestion. e.g suggestions for
all the categories of has operator will be show instead of `Messages
with one or more` suggestion which did not make sense.
`has` operator uses predefined categories. This commit displays an
invalid operand message if the operand does not fall in to any of
these categories and the `has` operator is not at the last.
e.g. `has:abc sender:abc@zulipchat.com` will have `invalid abc
operand for has operator, sent by abc@zulipchat.com` as a prefix for
all its suggestions.
Fixes#9384.
Default suggestion e.g `messages with one or more abc` as a suggestion
for `has:abc` is not shown in a new suggestion. But if the has operator
is already present before any other operator, the default message text
will be used. e.g `has:abc sender:abc@zulipchat.com` will have all the
suggestions with the prefix `messages with one or more abc, sent by
abc@zulipchat.com`.
This commit lays the foundation to handle submessages for
plugin widgets. Right now it just logs events, but subsequent
commits will add widget functionality.
Partially fixes#4708.
Implements a first version (v1) for the feature. The next step would be
to allow admins to toggle `is_announcement_only` in the UI.
We now initialize most modules in ui_init.js, which
isn't the perfect place to do it, but at least now
we have a mostly consolidated entry point.
All the new foo.initialize() methods introduced in
this module run the same order relative to each
other as before this commit. (I did some console
logging with a hacked version of the program to
get the order right.) They happen a bit later than
before, though.
A couple modules still have the `$(function() {`
idiom for miscellaneous reasons:
archive - is a different bundle
common - used elsewhere
list_render - non-standard code style
scroll_bar - no exports
setup - probably special?
socket - $(function () is nested!
transmit - coupled to socket
translations - i18n is a bigger problem
ui_init - this bootstraps everything
We now work with MessageListData objects while populating
data from local narrows, before actually making the
wrapper MessageList object.
This change will simplify unit testing (less view stuff
to fake out) in certain situations.
It will also allow us to eliminate the delay_render flag.
We used to have positional parameters for table_name
and filter, but we don't use them for message_list.all
and we're about to replace filter in some cases.
Passing everything in on opts is more consistent and
self-documenting in the calling code, plus lots of
unit tests can get away with passing in `{}` now
for situations where table_name does not matter.
All of our callers pass in muting_enabled, so we
remove the default value for it. And then the
collapse_messages variable doesn't have to live on
`this` as it's only being passed through down to the
view.
Before this change, the way to add messages had a lot
of ping-pong-ing between MessageList and MessageListData,
where first the data got triaged, but not actually
inserted into data structures, and then subsequent
calls would add the data and get filtered results.
Now we have a simple API for MessageListData.add_messages
that does all the data stuff up front. Having a fully
function MLD.add_messages not only makes the ML.add_messages
function about four lines shorter, it also sets us up
to easily build standalone MLD objects before making
the heavier ML objects.
We will need this for cases where the topic names in
unread.js are a superset of the names we got from messages.
It's important to pass in a dict of existing dicts to avoid
expensive max() calls to get the max ids of topics (otherwise
the plan would have been to merge the lists in the caller).
Fixes#9305.
Empty operators are not allowed while parsing narrowing URLs.
`parse_narrow` stops parsing further if it encounters an empty string
operator.
This run_test helper sets up a convention that allows
us to give really short tracebacks for errors, and
eventually we can have more control over running
individual tests. (The latter goal has some
complications, since we often intentionally leak
setup in tests.)
If we find unread messages for a sender, we will
try to render locally narrow for sender searches.
Note that our current implementation brute forces
through all the unread ids. We can improve this,
although it's not really a bottleneck until we
also support buckets for general filtering.
We now try harder to find the first unread message in an
upcoming narrow, which has the user-visible effect that we
select the unread message before waiting for search results.
Before this change, we only applied this logic to searches
that were things like exactly stream/topic or exactly is-private.
Now we will also handle things like stream/topic/sender. For
the stream/topic piece we look up candidate unread ids using
the steam/topic buckets in unread.js, but then we still filter
those messages by stream/topic/sender as we look for the first
unread id.
I renamed get_unread_ids() to _possible_unread_message_ids().
The name is deliberately verbose, since we're about
to make it have kind of unusual semantics that only make sense
for its one caller.
The outside code will continue to call get_first_unread_info().
In the tests I wrap this function in a wrapper with the more
pleasant name of "candidate_ids", since in the test there's
less worry about unwittingly exposing a kind of janky function.
We will use this to find the first id from a list of
message ids that matches a filter. (This will help us
during narrowing to determine whether we have at least
one good message locally, so that we can render something
useful before waiting for the server.)
This new API replaces some more specific functions that were
only recently introduced:
is_stream_only
is_stream_topic_only
is_pm_with_only
is_for_only
We use the deterministically sorted "term_type" values for
matching. (Notably "stream" will come before "topic".)
The "Short/Long Text" option for custom profile fields wasn't properly
capitalized (i.e. "Text" should have been all lowercase), and also
wasn't properly tagged for translation.
For the sake of consistency, the change to proper capitalization has
also been applied to the models and any tests involving this feature.
Due to a bug in Django, it complained about the models having changed
and thus not being consistent with the migrations. That isn't actually
true (since the database stores the numeric values for each key), but
the migrations have been modified to avoid this error. This does not
affect the migrations' behaviour in any way.
This should help prevent problems with folks introducing new code that
doesn't match our whitespace style.
There's a couple things I don't like about this configuration:
* How it handles multi-line JS lists (i.e. the [] syntax)
* That we ended up having to turn off indentation on a half-dozen
files that apparently don't use our standard IIFE indentation style.
* That we have it completely turned off for the node tests; ideally,
we'd just have slightly different rules around the IIFE identation story.
But otherwise, this works pretty well, and should catch a pretty wide
range of indentation regressions.
This works for other text boxes as well, but compose is the main one
that one would want to do a search from.
It's possible we'll find after doing this that "getting back into
compose" becomes a problem, but I guess we can handle that when the
time comes.
This makes a few important cleanup changes:
* Using the more standard data-field-id name for the ID value.
* Using $(e.target).closest() rather than `.parent`, which is more
robust to future changes in markup.