Previously, we had this complicated layering where the right sidebar
logic would display "Last active: foo" but the user popovers would
just display "foo", which doens't make any sense, since the two
settings have equal context about the string.
We deduplicate that and also arrange that the "Last active:" prefix is
used when it's not clear what we're talking about; i.e. all the values
except for "Active now".
There is no clear reason to not use a button element here. According
to the spec pharasing content, which includes the <span> element,
are allowed in the button element.
Manually tested both buttons to make sure it works and made sure all
the selectors are updated by grepping all the selector classes/id in
the handlebars templates that are parents of the button or are
present on the button.
(One of the jQuery handler code got reformatted due to it fitting
the line limit due to one character deletion for the selector)
This commit fixes a rare flake where it accidentally clicks
on "Subscribe to more streams" instead of "Verona"
(stream). This happens because `#stream_filters` list
was not completely updated, i.e. It still had "Venice" and
"Verona" on the list, when it searched for "ver".
When it decided to click on the "Verona", "Venice"
disappeared, which causes "Verona" to move up and
causing "Subscribe to more streams" to click.
Tested by the adding a console log to the handlers and typing Tab
and Enter in the group PM and stream compose box. This two event
handlers are attached to form#send_message_form which is the compose
box form.
The tests set keyCode to 42 previously, which does not represent a
valid key, so I assume they were trying to test a random key, and
replace it with "a".
There is no functionality change caused by this change. We turn the
event key to lowercase so hotkeys work even when Caps Lock is on as
it did before.
Tested by using the keybinds with and without Caps Lock in compose
box:
- "Ctrl + B" and "Ctrl + Shift + B",
- "Ctrl + I", and
- "Ctrl + Shift + L".
(Also tested that "Ctrl + Shift + I" and "Ctrl + L" do not work.)
Tested by doing the following in the compose box input for PMs:
- "Enter" works as expcected with and without input
- "Backspace" when there is no input deletes the last pill
- Left arrow in the input focuses last pill
- Comma works as expected for correct and incorrect input
- Left arrow, Right arrow and Backspace work correctly for pills.
The Event.which and Event.keyCode are deprecated as pointed out by
TypeScript intellisense based on the jQuery types. We use Event.key
instead which behaves similarly to Event.which & Event.keyCode for
our use case.
The only difference in functionality by this change is that the vim
keys won't work when Caps Lock is on. This is because, in this case,
the key property will be "J" instead of 'j'. We can fix this by
adding a mapping for this, however, I think we don't want to handle
this case so I left this change out. Tested by trying out the
everywhere keydown_util is used.
Finally, we also turn off the new-cap rule for tests since I think
it fine to only enforce it on real code and exempting test code is
fine.
In options that we pass to pill_typeahead.set_up we
specify if we want typeahead to support stream or
user_group pills, and use users as source by default.
Using users for source by default, can have unnecessary
suggestions in typeaheads where only user_groups or streams
are needed.
So to solve that, we specify if we want users pill in the input.
This is then utilized in further commits, to clean up hacky code
that deals with intializing source for typeahead.
We make the typeahead a little more nicer but only showing one alias
per language. For example if the user searches for prefix "j", then
the typeahead list should contain "javascript" only, and not "js" and
"javascript".
We now organize the pygment language codes into meaningful categories
- default, custom and aliases.
Further the `lang.json` list now contains a dataset extracted from the
"language" section of https://insights.stackoverflow.com/survey/2020
and is prioritized based on current language trends.
On slower systems it may take more than 4 seconds for the
stataus message to dissapear from the DOM, so it's better
to wait for the default duration of 30 seconds before
proceeding.
Thanks to @Riken-Shah for suggesting the fix.
Since this is currently only useful to interpret presence data, we
send this only if presence is requested.
I'm not sure that server_timestamp is the right name for this field,
but ultimately it should match the main presence API format.
When quoting a reply or mentioning a person having full name matching
wildcard mention, in such case, `get_mention_syntax` doesn't return
mention syntax of format: **full_name|user_id**.
As a result, a normal user can't mention such users and users who
can mention them may unwillingly trigger wildcard mention.
This commit fixes such issue.
Prior to this, we restricted to show any user group suggestions
if silent mention syntax is used. But with the addition of
user group silent mentions, there are cases where one may want to
refer to some user groups without actually notifying them.
So, we add typeahead logic for such cases.
Test cases for silent syntax (@_*) and non-silent syntax (@*)
are added.
Fixes this KaTeX warning:
Warning: KaTeX doesn't work in quirks mode. Make sure your website has
a suitable doctype.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This is pretty much a verbatim code move,
except that I inlined noop and reset_jquery
in the new file.
Also, in the last test, I no longer reset
the compose state.
We split them in the commit: c50dbf8297
because at that time we thought markdown_katex was gonna
require rewireproxy magic in the later commits.
But we later removed the rewiremock dependency in the
commit: 30c7108955.
So now, we can safely merge `markdown_katex.js` test file
with `markdown.js` test file.
The extracted logic is in linkifier.js.
We have decided to name it linkifier.js instead of realm_linkifier.js
because in future when we will add stream-level linkifiers, we'll
likely want them to be managed by this same file.
I'm not sure that settings UI is particularly worth having puppeteer
tests for, so it's possible we shouldn't bring these back at all. But
in any case, it's worth disabling them as they've been failing for
some time.
This commit solves a rare flake, where the `realm
_linkifier.ts` test was failing because there was no
appropriate wait call for the table
(`#admin_linkifiers_table`) to get updated after editing
the pattern.
The command:
codespell --skip='./locale,*.svg,./docs/translating,postgresql.conf.template.erb,.*fixtures,./yarn.lock,./docs/THIRDPARTY,./tools/setup/emoji/emoji_names.py,./tools/setup/emoji/emoji_map.json,./zerver/management/data/unified_reactions.json' --ignore-words=codespell_ignore_words.txt .
The content of codespell_ignore_words:
```
te
ans
pullrequest
ist
cros
wit
nwe
circularly
ned
ba
ressemble
ser
sur
hel
fpr
alls
nd
ot
```
This tests the basic mechanics of list_cursor
more directly than the activity node tests.
It also sets the stage to eliminate some
tests from activity.js while maintaining
100% coverage on list_cursor.
This is mostly moving tests from activity.js
into user_search.js, but it's not a verbatim
code move.
The new module continues to make sure that
the boundary between activity and user_search
is correct, as most of the testing uses
the configuration of UserSearch from
static/js/activity.js.
It does not use a real buddy_list, though,
which simplifies some tests.
I cleaned up some tests by making sure we
were testing both sides of conditions more
rigorously.
After this change we no longer need the
bloated activity.js tests to maintain full
coverage on static/js/user_search.js.
This commit adds the dropdown in 'Stream settings' section of organization
permissions page to control who can move messages between streams and
also hides the stream-edit UI in message-edit form accordingly.
Fixes#14499.
This commit extracts the logic for testing user_can_invite_others_to_realm
user_can_create_streams, and user_can_subscribe_other_users to a single
function test_policy and this function test_policy is called passing
different policies and validation functions as arguments.
This helps in removing a lot of duplicated code.
This also handles a few other places missed earlier like
narrow headings, beacuse they use the same function.
We already rerender the PM list for events, so there's no
need to do anything special when someone is muted/unmuted.
`people.get_full_names` is now only used in the settings pages
while creating ListWidgets etc, so we add a new test for
it to ensure coverage.
Long ago, we changed Zulip to inspect server-provided topic history in
our compose and search typeahead modules, but did not trigger a query
to the server to fetch data.
This could result in confusing experiences where someone thought that
a topic doesn't exist that just isn't present in recent history.
Once we merge this, we may want to adjust the messaging in typeahead
to advertise that the first option will create a new topic, since this
change may make it feel more like creating topics is a heavyweight
operation.
Fixes#9857.
Previously, the hook to save drafts when closing the compose box was a
focusout on #compose-textarea. This mostly worked, and was essentially
invisible to users (because the animation to notify you about saved
drafts was in the close_compose_ui widget that is hidden), but you'd
end up seeing the tooltip appear (in the wrong place) if you closed
the compose box immediately after sending a message with Tab+Enter.
The correct fix is for the drafts hook to be just before we start
clearing compose box state, inside hide_box.
This was difficult to catch in a development environment, since one
doesn't use that flow with "Enter sends" enabled.
We were apparently not using the ListWidget API for replacing the
content of a widget without removing the whole thing from the DOM and
replacing it.
Unless ListWidget has unexpected bugs, this should have the exact same
result as the previous logic, with much a nicer user experience.
We use styling same as that of the number shown for overflow
(e.g "+3") which has a gray background.
To keep these avatars up-to-date, we need to rerender the
recent topics view after receiving a `muted_users` event.
Also update the user documentation to mention this detail.
We deliberately avoid mentioning "recent topics" because
this applies to mobile too.
This seems more consistent with what users would expect; Recent topics
may be a better default view in general, but if a user has picked
another default view, we should use that where the default view is
desired.
The default label for empty narrows depends on whether it's a
stream/topic narrow or a PMs narrow.
We leave some default text in compose.hbs for reply label
because it take some time for the js to display the
correct label.
The browser seems to autofill the `Name` field of the add-playground
form. Most likely this behavior is a result of value of the `name`
input field being `name`, causing the browser do to something weird
here. This name is now changed to `playground_name`.
Share code between `safe_full_names` and `get_display_full_names`
functions, and rename `safe_full_names` to `get_full_names_for_poll`,
because that was the only place where this was used earlier.
This also has the nice side effect of showing "Muted user" instead
of the muted username in poll results.
The reason for this flake is it missed clicking on the Set
All button (`.subs_set_all_users`) because it calculated
its position before/during it starts scrolling.
There are two scrolling events caused by typing `ot`,
* First is due to internal focus call before typing
which scrolled down the page to bring input in the view.
* Second is after it typed `ot` the user list is updated to
one value, which caused the modal height to decrease rapidly.
Note: It theory, there is three scrolling event,
First is of course internal focus then, after it typed `o`
the list is updated to two values and one is after `t` the
list is updated to a single value.
But as puppeteer is very quick it directly jumped to the
scrolling event after it typed `ot`.
For a more detailed explanation read,
https://chat.zulip.org/#narrow/stream/43-automated-testing/topic/master.20failing/near/1173996.
This commit just temporarily fixes this flake, it's not the
best approach to use time-based delays as they can't be
robust (e.g If the machine is super slow then time-based
delays can fail.).
We don't want to rely on browser hash to check if RT is visible
because soon we want to display default_view without any hash
and RT may or may not be visible in that hash.
Active stream's hash look like this - `#streams/1/announce`
Since the stream_id is present where typically hash section
is for all other hashes, get_current_hash_section should return
the same result.
A modal is added to edit the realm linkifier which
supports ui_report error.
Puppeteer tests to verify linkifier update and an
invalid test to verify that linkifier error messages
are reported on the modal are added as well.
Previously, we used to hide 1:1 PMs with muted users everywhere
in the UI. This commit makes it so that such messages will now be
visible in `pm-with/<muted_user>` narrows, meaning these will not
be excluded from message lists, but will still be hidden under
the "This message was hidden." dialog implemented earlier.
* We hide 1:1 PMs from and to muted users throughout
the UI, because doing so will not lead to loss of
conversational context. The "to" part is also important,
because the last few messages sent to a user before
muting them would probably be asking them to stop
spamming.
* After this change, we will need to do filtering for either
user or topic muting in pretty much all narrows, so we need
to keep the `_all_items` list in MessageListData always
up-to-date.
* A further commit will relax this and make it possible to
view these messages only when in a `pm-with/muted_user`
narrow.
This basically reverts 4bd7ec7c36 and
3a9dfc02e6.
The plan earlier was to have compeletely different codepaths
for user and topic muting, so that we could call seperate
functions in the message list class on receiving the respective
events.
However, this cannot be done, because if we, for example, on
receiving a `muted_users` event, filter `_all_items` based on
just user mutes, and store the result in `_items`, then, that
result may still contain topic-muted messages, which is
undesirable. Hence whenever we filter messages, we must do so
based on both user as well as topic muting.
(The code for the former will be added in further commits.)
So, we will have a single function which will handle updating
the message lists for muting.
These mock objects did not buy any ease in testing, as
evident from the fact that this commit hardly contains
any changes to the tests themselves.
This commit also removes some unnecessary `filter: undefined`,
parameters sent to MessageList constructor.
Add a function which is called before every render to
get the number of items it can render. This can be used by
instance to load custom number of items as per its state.
We allow ListWidget instances to pass functions in opts that can
be called after scrolling to determine when to render.
Also, allow a callback function to be called pre render.
We move compose from being a part of message feed to
being a part of middle column which is a common parent of recent
topics and message feed. This allows us to use a common compose
box for both the views. Fortunately, compose actions were
independent of this change so there weren't any evident
side effects.
Fixes#17543
This corner case was reported in #17320, basically, the
issue was when two or more alert words were used
consecutively with a single space between them, it didn't
detect the even number word as `alert word`.
This button will allow users to avoid a distracting red banner across
their screen, while they wait for their sysadmin to do the upgrade
work.
Fixes: #18359
Since we don't process private messages yet, we don't
need to re-render when we receive a new private message
as it doesn't change any data related to recent_topics.
This will allow us to avoid duplication of array filtering
logic of the form-
`Array.filter((user_id) => !muting.is_user_muted(user_id))` and
`Array.filter((person) => !muting.is_user_muted(person.user_id))`
We want to exclude 1:1 PMs from muted users everywhere
except in `pm-with/<muted_user>`.
This method will help us determine whether we are in such
a narrow.
* We show a "Click here to reveal." hyperlink in the hidden
message dialog for user to click on and read a hidden message.
* The "reveal" action is temporary, in the sense that a revealed
message will again be hidden once the broswer tab reloads or
if the user renarrows.
* When a message is revealed, we make sure to show the sender
of that message, even if it isn't the first message of it's group.
This is because the first message of that message group (which
would have otherwise shown the sender) can still be hidden.
* Reactions and background color after revealing a message are
the same as if the message hadn'e been hidden at all in the
first place.
* We hide the sender and reactions on messages sent by muted
users, and replace the content with a "This message was hidden"
dialog.
* Ideally, we should collapse a series of consequetive
messages sent by muted users into one such dialog, but
that could break the cursor behaviour and `near/<message_id`
links, so we as of now show one dialog per muted message.
* Because we hide the sender, there is a chance of the first
hidden message in a group looking like it was sent by the
author of the message above it. To tackle this, we intentionally
make the hidden message dialog float-left, so that it is clear
that this is a special type of message.
* For context, we still show the timestamp of the message.
* Starring, editing, deleting etc a message still work just like
before.
A further commit will add the ability to reveal a
hidden message.
We also add a check to see if `message_feed_container` is visible,
since it is possible that recent topics could be visible which
was not a possibility when this logic was written.
The 'reply' button shows the stream>topic or recipient(s) of the
selected message, for better UX. It also expands to fill the
remaining horizontal space in the button bar -- this should help make
it easier for new users to figure out how to reply.
Finally, it uses "Message" instead of "Reply", to better match the
compose box.
Fixes#17940.
This test was wrong, in that it checked for the English status string
when the current language was expected to be German; this happened to
work until now because with i18next we were failing to include the
string in question in our translation data; and early today I did the
first translation data sync since our translators had translated that
string for German.
Replacing the group PMs icon with "fa fa-group" icon
drops the color class "fraction_present" logic. As there
is no more use of fraction_present class this commit
cleanups its all existence from the codebase.
As of now, editing a widget doesn't update the rendered content.
It's important to ensure that existing votes or options added later on
don't get deleted when rendered.
This seems more complex than it's worth.
For now, we just prevent edits to widgets.
This commit makes the UI clearer that editing widgets isn't allowed.
See also:
https://github.com/zulip/zulip/issues/14229https://github.com/zulip/zulip/issues/14799Fixes#17156
This commit fixes a rare flake which was most probably
caused when we clicked on the `Check All` button, and
we instantly cleared the filter when it was still marking
the user `checked`, which nullified the effect of clicking
on `Check All` button.
Currently, when there are some old starred messages
in a topic, it is possible that some of them won't be
unstarred on doing "Unstar all messages in topic".
This happens when those messages haven't been fetched
yet from the server, and we have no way to verify if
they actually belong to the topic.
This commit fixes that by changing this mechanism to
first fetch all starred messages in the topic from
the server, and then send their IDs back to the backend
to unstar them.
While doing this, we assume that the user does not
have more than 1000 starred messages in that topic.
Note that, we still depend on the local data to
decide whether or not the "Unstar all messages in
topic" option should be shown in the topic popover.
A method similar to the above cannot be used here, because
making server requests before opening the popover
could visually slow down the popover opening.
Using local data for the topic popover would probably
not be a big problem, because users would want to
unstar all messages in a topic probably after noticing
that there are a lot of them, meaning there was at least
one starred message from that topic which was already
fetched, which is sufficient for us to conclude that
we need to show the option in the topic popover.
Fixes#17790
This logic is already thoroughly tested in node tests for
the `MessageListData` class, and the `unmuted_messages`
method of `MessageList` only directly call the corresponding
method of the data class.
We hide a conversation from the top-left corner PM list if
it is-
* A 1:1 PM where the other user has been muted, or
* Huddle where all users have been muted.
* Extract out data as common variable so that it can
be reused in other tests in the future.
* Use consistent dummy user_ids across tests.
* Expand the data set to cover all possible cases-
- 1:1 PMs
- Huddles
- PMs with self
This commit adds code for live updating the role field of person
object on receiving role change event from server and thus enables
live update of role in users list of settings overlay.
This commit adds code to live update page_params.is_moderator and
person.is_moderator on receiving role change event.
The code for changing role to moderator and from moderator to any
other role was added in previous commit.
This commit modifies the code to show "Moderator" correctly for
realm moderators.
As, we show role using settings_config.user_role_values object and
the same is used for showing options in changing role dropdown, this
commit also adds the moderator option in that dropdown and thus allows
the user to change role to moderator and from moderator to any other
role from frontend.
But the code for live updating page_params.is_moderator and
person.is_moderator will be in further commit.
This commit adds 'admins and moderators' option in frontend for
invite_to_realm_policy.
The logic for moderator for checking whether user is allowed to invite
others or not was added in previous commit as we use common helper
user_has_permission for all policies.
But the test user_can_invite_others_to_relam is updated for including
moderator role in this commit.
Since, we now get role value in person objects sent from server, we
can simply user user_role_map to display role in different places
instead of having multiple if-else conditions to check flags like
is_admin, is_guest, etc.
This commit modifies the user objects returned by 'GET /users',
'GET /users/me', 'GET /users/{user_id}' and 'GET /users/{email}'
endpoints to include role field.
We also include role field in the page_params['realm_users'] dict
and in the person object sent in (type="realm_user", op="add")
event.
This help mobile and terminal clients understand whether a server
restart changed API feature levels or not, which in turn determines
whether they will need to resynchronize their data.
Also add tests and documentation for this previously undocumented
event type.
Fixes: #18205.
There were some changes that were lost/added by mistake
during a rebase of #17707 after #18154 was merged.
Fixes the GIF icon being hidden / displayed incorrectly
with respect to the settings.
These changes were originally part of
67527a2517 but
were lost during the rebase.
This commit adds 'user_can_create_streams' helper which is
used to check whether user can create streams or not and
replaces all the instances of 'page_params.can_create_streams'.
This change helps us to remove the complex logic of updating
'page_params.can_create_streams' for 'realm_update' event in
'server_events_dispatch.js', as we will always get the updated
values from the added helper for checking whether the users can
create streams or not.
This commit adds 'user_can_subscribe_other_users' helper in
settings_data.js amd this helper will replaced all the
instances of page_params.can_subscribe_other_users.
We also remove the incorrect code in server_events_dispatch.js
where we were updating page_params.can_invite_to_stream which
is actually not used in other parts of code and instead of it
page_params.can_subscribe_other_users is used to check whether
user is allowed to subscribe others or not. This code was
added in 272ed9068.
Though this could have been done in a different commit, but as
we are adding the code to use the correct updated value in this
commit only, this has been fixed here.
There is also no need of adding that complex logic to update the
correct 'page_params.can_subscribe_other_users' field on
'realm_update' event, as we are using user_can_subscribe_other_users
helper and thus we always use the updated values to check whether
the user is allowed to subscribe others or not.
This commit adds 'user_can_invite_others_to_realm' function
in settings_data.js which replaces all the instances of
'page_params.can_invite_others_to_realm'.
This change makes it possible to remove the complex logic of
updating 'page_params.can_invite_others_to_realm' on
'realm_update' event as we are using above added helper instead
of using page_params object and thus we always use the updated
value to check whether user can invite others or not.
The 'user_has_permission' helper will be used by functions added
for create_stream_policy and invite_to_stream_policy in further
commits and will help in avoiding code duplication.
This commit replaces different objects - create_stream_policy_values,
invite_to_realm_policy_values and invite_to_stream_policy_values,
with a single object common_policy_values.
Though invite_to_realm_policy do not use other fields of objects like
description, order, etc. but we can keep it as it is for now as we
would separate this setting from "Are invitations required...."
dropdown and these fields will be used then.
This is a prep commit for commits that will add helper functions in
settings_data for these policies replacing the usage of page_params
object.
This prevents the regex from requiring multiple spaces between
adjacent alert words by using lookahead and lookbehind (rather than
the before/after checks each needing to eat a whitespace character) so
that consecutive alert words (if any) can be highlighted.
With a frontend test covering adjacent corner cases by tabbott.
Fixes#17320
This extends the /json/typing endpoint to also accept
stream_id and topic. With this change, the requests
sent to /json/typing should have these:
* `to`: a list set to
- recipients for a PM
- stream_id for a stream message
* `topic`, in case of stream message
along with `op`(start or stop).
On receiving a request with stream_id and topic, we send
typing events to clients with stream_typing_notifications set
to True for all users subscribed to that stream.
Previously, we used to do a kind of "local echo"
whenever the user muted/unmuted a topic. Meaning,
we used to do most of the UI update work before making
the API call to mute the topic, instead of after
receiving the `muted_topics` event. This behavior
has been so since the beginning of time
(b4b6fa14d3) and isn't ideal because:
1. If the request fails on the backend, the UI
could end up in an incorrect state.
2. Adds code complexity.
3. Makes it difficult to catch bugs related to
live-update (like the one fixed by
f725711ff2).
4. Isn't consistent with other parts of the
codebase, which do the UI update while handling
events.
This commit makes it so that all the UI update
work is done only after recieving the `muted_topics`
event.
The only possible issue with this strategy could
be users sending another duplicate request in the small
time span before receiving the event. But that isn't
a big problem, because all requests involved here are
idempotent, and the worst that can happen is a HTTP 400.
This commit adds support for a `None` option in the dropdown menu
of `Notification sound`. When this option is selected, no audible
notification is sent to the user.
`None` will appear as the first option in the dropdown menu, since
this is not categorized as a playable audio.
This new option is added so that folks can disable audio notifications
without losing their other notification configuration (like for PMs, mentions).
Necessary test case is added for this new option.
Fixes#16090.
Item field is added to the pill items, this is done to utilize
it wherever possible, to distinguish between diffrent types
of pill items(stream|user_groups|users).
It is also a preparatory commit to support expanding of stream
and user group pills.
We convert the following elements to use a class instead of
id for accessing them across the codebase:
* markdown_preview
* undo_markdown_preview
* markdown_preview_spinner
* message_edit_content
* preview_content
Converted them together since changes to one impacted the other in
some modules like click_handlers.
Also, added a function in rows to get `message_row`.
We use `.compose_upload_file` across compose and message_edit_form
for file upload icon. This will help us share common code between
`compose` and `message_edit_form`.
In both compose and `message_edit_form` we use `file_input`
class to identify the file `input` element. This will help
to more easily share common elements between compose and message_edit.
Since we can have multiple instances of `message_edit_form`, it
makes sense to have it as a class.
We track the message_edit_form by setting an id to
`form` element dependent on message_id.
This commit makes it so that muted users never appear
in the right sidebar buddy list, filter text or not.
The hiding is done in the frontend only, and we still
recieve presence data from the server as before, so
no extra work is required on unmuting someone, other
than to rerender the user list.
Long term if we find that there are too many muted users,
we may want to optimize how we send presence data, but
that is unlikely to happen.
The other less extreme option is to gray out muted users,
but that cannot be done because it would conflict
with the graying out we do for non-recipients when the
compose box is open.
Moved `admin_user_group_list` template to `/templates/settings/` folder
as earlier, it was inaccurately placed within the `/templates` folder
and should have been within the `/templates/settings` folder.
Also modified the node tests to reflect the new changes.
Moved `admin_profile_field_list` template to `/templates/settings/` folder
as earlier, it was inaccurately placed within the `/templates` folder
rather than the `/templates/settings` folder.
Also modified the node tests to reflect the new changes.
This improves the UX of creating a stream for atleast 1000+ users
realm by showing the the stream creation form much faster than
before.
Search, user addition, scrolling worked smoothly on 15k+
users realm as tested on dev setup.
Also, simplebar is used to replace the default scrollbar.
Fixes#16805
This allows us to use different "Show password" and "Hide password"
for these labels, which is more consistent with how other products
implement this.
It also lets us delete N duplicate copies of these strings in the HTML.
The show password feature is a functionality to
toggle the visibility of the password fields in forms
so that one can check if they have entered the correct
password or not. We implement this using an eye icon
toggling which converts input field type from password
to text and vice-versa.
Fixes part of #17301.
Since the "mute users" feature isn't complete yet,
this UI is shown only in development setups.
Ideally we should have had this commit after the whole
feature was completed and merged, but doing so makes it
difficult to test and merge subparts of the feature one by
one (which is a better workflow, while we still decide what
exactly we want this feature to do).
This commit adds a new button in the user info popover
to mute or unmute the user, and uses a confirmation
dialog while muting, because muting a user accidently can lead
to the muter losing out on a lot of information.
TODOs when making this UI visible in production-
1. Make a /help page and link to it from the confirmation
dialog and the API docs.
This extra commit adds support for creating user group pills
in cases that do not use typeahead like, pasting the group
name, copying it from the user group pill.
This completes the remaining work required to support
addition of all members of a user groups to stream.
Fixes#15186.
We update the pills typeahead logic to also include user group
results and pass the "user_group" key in `opts` to enable this
option for Add subscriber form.
The changes includes:
* Exporting the `query_matches_name_description` function, to
deduplicate the typeahead `matcher` logic.
* Creating a `people.is_known_user` function, to deduplicate
the typeahead `sorter` logic.
* Add a new `user_group_pill.js`, to allow adding user group
pills in input widgets that support pills.
This has been tested manually as well as by adding some new
node tests.
This commit removes`typeahead_helper.sort_recipientbox_typeahead`
which was introduced in 639ec9380a
for the private message recipient box when it used to accept comma
separated text input for recipients. All it doew was cleaning away
invalid recipients from string, like:
"a, , b" was cleaned to [a, b].
This can be now removed because it was now used only in
pill_typeahead.setup code path, and the pills code already handles
invalid cases by filtering out all falsy (invalid) recipients.
We move compose.html to compose.hbs file while keeping
`#compose` still in `home.html` as a hanger
where append rest of the elements.
This will provide us with two benefits:
* We could share common elements between message_edit_form and
compose.
* We can insert compose directly in any element. We may decide to
do it for recent topics.
Adds a setting UI to list all configured playgrounds
in a realm. The filter functionality can be used to
search playgrounds by its name or language.
Default sort is provided on the 'pygments_language'
field.
Front tests added to maintain server_event_dispatch
coverage. The `settings_playgrounds.js` file is added
to coverage exclusion list since it is majorly UI
based and will be tested using puppeteer tests (in
following commits).
This is in preparation for moving this code to @zulip/shared for use in
the mobile app, where we will want to use Sentry for reporting errors,
rather than blueslip.
The way I've done this only allows for reporting one type of error
(currently, blueslip.warn), but seeing as we only have one place we
report an error, that seems like something we can fix if we want more
error levels at a later date.
This reduces the complexity of our dependency graph.
It also makes sub_store.get parallel to message_store.get.
For both you pass in the relevant id to get the
full validated object.
This breaks an indirect dependency of stream_data
on the channel module.
It's a verbatim code move, apart from the one-line
helper `has_history_for`. It's not totally clear
to me why the original code doesn't call into
`is_complete_for_stream_id` to early-exit, but
figuring that out is outside the scope of my
change.
It's possible that we will eventually just subsume
this tiny module into topic_list once we finish
breaking all dependencies, but we may want to
reuse this for something like Recent Topics
or other similar UIs.
It's also possible that we'll want to rename
stream_topic_history -> stream_topic_history_data
sometime soon, possibly after we clean up its
dependency on message_util soon.
This widget only filters the user's subscription -- it's only suggest
public streams that the user is not subscribed to. "Filter" is the
correct label for a widget with this use case.
We only update the `.private_messages_header` here since
unread_counts of `.expanded_private_message` are updated
via `pm_list.update_private_messages`.
This fixes the bug of PMs in `.expanded_private_message` having
the same unread count as `private_messages_header`.
Since we rerender the DOM of `.expanded_private_message` every
time we update unread count of PMs, we don't need to manually
update them here. Also, we always keep them on display since
there is no real need to toggle them. They are not visible
when they have 0 unread counts via `.zero_count`.
While rest of the app has ported to the new system of updating
unread_counts `activity` was not ported. This resulted in
unread count in buddy list not being updated when new
PMs arrive.
The series of commits to consolidate CSS classes
for the various unread-count spans across our app
created a bug where the stream_list.js code's selector
starting capturing the unread spans in topic list items.
Suppose you had a stream with these topics:
Foo 10
a 3
b 3
c 4
If another unread came in, you would briefly see:
Foo 11
a 11
b 11
c 11
Now we just use subscription_block to find the
element that we want to tweak.
I remove a convoluted node test here. Part of the
reason the node test was convoluted was that the
original implementation was overly complex. I will
try to re-introduce a simpler test soon, but this
is a bit of an emergency fix.
This reduces our dependency on message_list code (via
message_util), and it makes moving streams/topics and
deleting messages more performant.
For every single message that was being updated or
deleted, the previous code was basically re-computing
lots of things, including having to iterate through
every message in memory to find the messages matching
your topic.
Now everything basically happens in O(1) time.
The only O(N) computation is that we now lazily
re-compute the max message id every time you need it
for typeahead logic, and then we cache it for
subsequent use. The N here is the number of messages
that the particular sender has sent to the particular
stream/topic combination, so it should always be quite
small, except for certain spammy bots.
Once the max has been calculated, the common operation
of adding a message doesn't invalidate our cached
value. We only invalidate the cache on deletes.
The main change that we make here from a data
standpoint is that we just keep track of all
message_ids for all senders. The storage overhead here
should be negligible. By keeping track of our own
messages, we don't have to punt to other code for
update/delete situations.
There is similar code in recent_topics that I think can
be improved in similar ways, and it would allow us to
eliminate functions like this one:
export function get_messages_in_topic(stream_id, topic) {
return message_list.all
.all_messages()
.filter(
(x) =>
x.type === "stream" &&
x.stream_id === stream_id &&
x.topic.toLowerCase() === topic.toLowerCase(),
);
}
In an effort to use a common class to display unread counts across
the app, we simplify the elements used to show unreads and use a
single `span` with `unread_count` class to do so.
This reverts commit f81cc16a0f (#17999).
The {{#tr}} helper now includes the functionality that we wanted from
this.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
* This introduces a new event type `realm_linkifiers` and
a new key for the initial data fetch of the same name.
Newer clients will be expected to use these.
* Backwards compatibility is ensured by changing neither
the current event nor the /register key. The data which
these hold is the same as before, but internally, it is
generated by processing the `realm_linkifiers` data.
We send both the old and the new event types to clients
whenever the linkifiers are changed.
Older clients will simply ignore the new event type, and
vice versa.
* The `realm/filters:GET` endpoint (which returns tuples)
is currently used by none of the official Zulip clients.
This commit replaces it with `realm/linkifiers:GET` which
returns data in the new dictionary format.
TODO: Update the `get_realm_filters` method in the API
bindings, to hit this new URL instead of the old one.
* This also updates the webapp frontend to use the newer
events and keys.
Changed the name of the test-user cordelia from `Cordelia Lear` to
`Cordelia, Lear's daughter`.
This change will enable us to test users with escape characters in
their names.
I also updated the Node, Puppeteer, Backend tests and Fixtures to
support this change.
* Don't require strings to be unnecessarily JSON-encoded.
* Use check_capped_string rather than custom code for length checks.
* Update frontend to pass the right parameters.
With a much simplified populate_data_for_request design suggested by
Anders; we only support a handful of data types, all of which are
correctly encoded automatically by jQuery.
Fixes part of #18035.
Long labels like "Deactivate xyz" or "Delete xyz" can
be confusing for translators and it can also create bad
strings that can end with like 4 long words in German.
It is better to have the simple options like "Confirm"
and "Cancel". This commit fixes this issue by changing
the text to "Confirm" in their respective template files.
Fixes#17926.
We no longer need to add_tooltip_to_left_panel_row since
tippyjs.delegate will automatically do that for us.
Tippyjs automatically places it to left on small widths and bottom
for large widhts.
When the user's full name is long, the full name + `(you)`
in the buddy list starts to truncate, but when hover, the
tooltip displays the full name but not `(you)`.
This commit fixes this by adding `(you)` in the tooltip.
There was a bug where invite users link is shown in the Invitations
section of settings overlay, irrespective if the user is allowed to
invite or not based on the realm settings. So here we just use the
'can_invite_others_to_realm' field of page_params, that was added in
previous commit itself to hide the link accordingly.
Also added the code in server_events_dispatch.js for this field.
Though it doesn't do live update when the overlay is opened similar
to other policies like create_stream_policy, but it ensures that the
visibility of link is correct if the overlay is opened after the
settings has changed.
We should probably do the complete live update in future of the
elements related to such realm settings.
Since the base hash for org settings and user settings are
different (organization and settings), the hashchange module
gets confused that we are going from one overlay to other.
A reproducer for this flow is to visit the organization "Bots" page,
click on your own profile as the owner of a bot, and then click "Edit
profile" from there.
So, we fix this by making an exception for this particular case
in the module.
Fixes part of #18011.
Muted users are stored in a map with key as user ID and
the value as the timestamp of muting.
Names can be easily fetched from existing functions
in `people.js` and hence not stored.
This change should make live-update code less brittle,
or at least less cumbersome.
Instead of having to re-compute calculated fields for
every change to a stream message, we now just compute
the fields right before we render stream settings UI.
This is mostly a pure code move.
In passing I remove an unneeded call to
update_calculated_fields in the dispatch code,
plus some tests that don't need them.
For filter values which don't exist or are invalid in some
way, we return false to show user that there are no messages
in the filter user is trying to render. Our previous behaviour
was to show all the messages and ignore the filter which
isn't good.
The only downside of this is that it makes it harder to control the
order of these tests; which isn't that important. And the structure
of naming each with its test order fundamentally requires renaming
files when adding/deleting tests, so if we want to control the default
test order, we'd be better off doing that by just hardcoding a list in
the test runner code.
Previously we were liable to have false positives in our tests here
because we did not reset the visible state for these selectors, this
commit adds a helper and relevant calls to it in order to prevent such
false positives.
This commit changes some fragile selectors (like
`a[href=#link]`) to more stable selectors because they
are more prone to break from doing something normal
like adding another link in the app.
It also solves an inconsistency in `07-navigation.ts`,
where the subscription overlay was opened by clicking
on the header stream instead of the menu list.
It also fixes a rare flake (in `07-navigation.ts`), where
the close button of subscription overlay was not clicked
due to a delay in the opening. The delay was caused by
clicking the header stream to open subscription overlay
which caused unnecessary loading of the stream
setting(Verona).
As we are using the 'navigate_to' function to navigate
the links on the left sidebar, It'd be more clear to rename
the function to 'navigate_using_left_sidebar'.
Also adding '#left-sidebar' when selecting the element,
to be sure it will select the element from the left sidebar.
We recently added the commit to add the log-out call
after each test (52706908b).
This commit cleans that approach by using
just one log-out call after the test is executed at
`common.ts`
This commit adds waitForFunction to wait till the background mouse events
are enabled after closing the modal in the settings test.
This change is needed to avoid the failure that will be caused after we
change the code to handle re-enabling of mouse events only at one place
using 'hidden.bs.modal' event of bootstrap, as this event is fired only
after the modal is completely hidden, and we would want the mouse events
to be enabled before using clicks in further tests.
We now consistently set the PM counts for the right
sidebar toggle in unread_ui, similar to what we
do for the overall counts in the left sidebar toggle.
(Use a thin window to see the code in action.)
This breaks a dependency cycle.
In passing I improve the test coverage for the
actual job that pm_list still does (updating its
own total count in the "Private Messages" section).
This data structure has never been one that we actually render into
the DOM; instead, its role is to support clicking into view that
contain muted streams and topics quickly.
This downgrade makes that situation much more explicit, and is also
useful refactoring to help simpify the upcoming changes in #16746.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
I lift this function out of message_store to
break some dependencies, and it's also more
consistent with the rest of the codebase:
alert_words.process_message
pm_conversations.process_message
recent_topics.process_messages
recent_senders.process_message_for_senders
We can do further cleanup to make these names
consistent (and possibly have them all work in
bulk), but that's out of the scope of the current PR.
We move the message_store.add_message_metadata function
(and all its dependencies) into a new module called
message_helper and rename the function to process_new_message.
(It does a bit more than adding message metadata, such
as updating our message store.)
We also have a "protected" interface now in message_store,
so that message_helper can access the message store:
update_message_cache
get_cached_message
Because update_message_cache is identical to
the former create_mock_message, we just renamed it
in the tests.
Most callers should use these functions:
message_helper.process_new_message (setting)
message_store.get (getting)
It's slightly annoying that the setter interface
is in a different module than the getter interface,
but that's how you break a bunch of dependencies.
We also extract the tiny message_user_ids class:
user_ids()
add_user_ids()
All the code moves here are pretty trivial, and
the code that was moved maintains 100% line
coverage.
The module name `message_helper` is not ideal, but it's a single
function and it'll save time to just do the topology change now and
leave thinking through the right name to later.
When migrating from Casper to Puppeteer, some tests
were missed for adding log-out calls at the end.
This commit adds log-out calls to those missed tests.
Also, As we are resetting the test database after each
run (from 99f8be6a12) it will better to log out because we are
not resetting Tornado's internal state. It'd help us prevent
any future flakes.
Before this we did not have remove event in server_events_dispatch.js
for the user group delete event even though server had. This was
leading to blueslip errors. Extracted the logic which was used in
success() of channel.del for user_groups into the remove case in
server_events_dispatch. Also removed the redundant reload call as
we already do that in server events.
This is a mostly verbatim extraction.
I re-phrased one line of code to work around a lint
false alarm. (Look for `preamble` in the diff.)
There are about 8 lines missing coverage here, so
the new module might be a good candidate to get
100% line coverage on.
Before this change, you would need to remove 74
edges from our dependency graph to make it
acyclic. Now it's 72.
This change does not impact the overall complexity
of our dependency graph (at least in terms of the
number of edges that we would need to remove to get
a tree), but it does clarify the picture a bit.
* `op` (operation) field, added in f6fb88549f, was never intended for
`custom_profile_fields` event. This commit removes the `op` as it doesn't
have any use in the code.
* As a part of cleanup, this also eliminates the schema check warnings
for `custom_profile_fields` event, mentioned in #17568.
When a user entered an invalid character (whitespace or characters not
present in a name), the cleaned-up array, and hence the query,
would be empty which resulted in an error.
Fixes#17542
Extend our markdown system to support mentioning of users
by id also. Following these changes, it would be possible
to mention users with @**|user_id** and silently mention
using @_**|user_id**.
Main intention for extending the mention syntax is to make
it convenient for bots to mention a users using their ids. It
is to be noted that previous syntax are also supported.
Documentation tweaked by tabbott for better readability.
The changes were tested manually in development server, and also
by adding some new backend and frontend tests.
Fixes: #17487.
These were introduced in ff9a929d7a
with no explanation of why they were necessary.
Generally you only render a few things, and it's
important that they're up to date.
We weren't doing a good job of invalidating the cache.
Eliminating the cache will fix bugs (like presence circles
being out of date) and break some dependencies.
I removed some very fragile test code that was relying
on invalid values taken out of the cache. (We now have
less line coverage, but if we want to test our rendering,
there are much cleaner ways to do it.)
As part of testing this, I renamed Hamlet to "aaron", so
that there are two aarons, and then I logged on as Iago
to see the "secondary" code in action that shows their
emails to distinguish them.
This add the schema checker, openapi schema, and also a test for
realm/deactivated event.
With several block comments by tabbott explaining the logic behind our
behavior here.
Part of #17568.
This adds support for unstarring all (starred)
messages from a particular topic, from the topic
popover.
The earlier implementation of this in #16898
was reverted in bc55aa6a01 (#17429)
because it had two problems-
1. The crash reported in bc55aa6a01
was due to message_store returning undefined. This happens
when the message itself hasn't been fetched from the server
yet, but we know that the message is starred from the ids
in `page_params` in `starred_messages.js`.
This commit handles this case explicitly.
Note that, we simply ignore those messages which
we haven't fetched, and because of this, it may
happen that we don't unstar some messages from that
topic. The correct implementation for this would
be to ask the backend for starred IDs in a topic.
2. The earlier implementation actually unstarred **all**
messages. This was because it grabbed the topic and stream_id
from the topic popover `data` attributes, after the topic
popover had been closed. This passed `undefined`, which
the function then interpreted as an action to unstar all
messages.
With this commit, we use the confirm_dialog widget,
which eliminates the need to store this data in the DOM.
This is mostly a refactoring to break the unnecessary
dependency of bot_data on settings_bots.
This is a bit more than a refactoring, as I remove all
the debounced calls to render bots during the
initialization of bot_data. (The debouncing probably
meant we only rendered once, but it was still needless
work.)
We don't need to explicitly render bots during
bot_data.initialize(), which you can verify by loading
"#settings/your-bots" as the home page. It was just an
artifact of how add() was implemented.
Note that for the **admin** screen, we did not and
still do not do live updates for add/remove; we only do
it for updates. Fixing that is out of the scope of this
change. The code that was moved here affects
**personal** bot settings.
Note that the debounce code is quite fragile. See my
code comment that explains it. I don't have time to go
down the rabbit hole of a deep fix here. The puppeteer
tests would fail without the debounce, even though I
was able to eliminate the debounce in an earlier
version of this fix and see good results during manual
testing. (My testing may have just been on the "lucky"
side of the race.) I created #17743 to address this
problem.
This mainly extracts a new module called
browser_history. It has much fewer dependencies
than hashchange.js, so any modules that just
need the smaller API from browser_history now
have fewer transitive dependencies.
Here are some details:
* Move is_overlay_hash to hash_util.
* Rename hashchange.update_browser_history to
brower_history.update
* Move go_to_location verbatim.
* Remove unused argument for exit_overlay.
* Introduce helper functions:
* old_hash()
* set_hash_before_overlay()
* save_old_hash()
We now have 100% line coverage on the extracted
code.
The only caller for this function was settings_config,
so we put it there.
For the stream_edit test we no longer mock the function.
(The reason we mocked the function was more about avoiding
the heavy settings_notifications import than the function
itself.) This gives some incidental coverage, but then I
also add some more real coverage on it.
We extract compose_fade_users and compose_fade_helper.
This is a pretty verbatim extraction of code, apart from adding a few
exports and changing the callers.
This change makes the buddy_data module no longer sit "above" these
files in the dependency graph (at least not via compose_fade):
* jquery
* lodash (not a big deal)
* compose_state
* floating_recipient_bar
* message_viewport
* rows
The new moules have dependencies that buddy_data already
had directly for other reasons:
* people
* util
And then buddy_data still depends on stream_data indirectly through
the compose-fade logic for stream_data. Even without compose-fade, it
would depend indirectly on stream_data via hash_util.
Note that we could have lifted the calls to compose_fade out of
buddy_data to move some dependencies around, but it's useful to have
buddy_data fully encapsulate what goes into the buddy list without
spreading responsibilities to things like activity.js and
buddy_list.js. We can now unit-test the logic at the level of
buddy_data, which is a lot easier than trying to do it via modules
that delegate drawing or do drawing (such as activity.js and
buddy_list.js).
Note that we still don't have 100% line coverage on the
compose_fade.js module, but all the code that we extracted now is
covered, mostly via buddy_data tests.
Previously, it was tedious to create actual message
objects in message_store for use in node tests.
This was mainly because, `add_message_metadata`
in message_store has many dependencies and
validation checks. Since it was difficult to create
actual message objects, many tests just mocked
the `message_store.get()` method to return the desired
message.
This commit adds a new helper method (`create_mock_message`)
to message_store, for use in node tests. This just stores
the object passed to it in the `stores_messages` map,
without any validation. We do not add any
default fields to the message object before saving
it from this helper, because doing so would decrease
the utility of this helper, and, if a test
depends on some field having a particular value,
then it would be better to just pass the field: value
pair from the test itself, for readability, rather
than relying on the helper to add the field for us.
This helper allows us to write deeper tests.
This commit also replaces some instances of mocking
`message_store.get()` to use this new helper method.