This is a purely lexical move (apart from changing
a closure variable to an argument), which is
simply designed to make less indentation for the
reader and to de-clutter `handle_human_form`.
When editing a bot, there are only two fields
that are similar to humans--full name and
email--which are trivial.
Before this commit we used a single codepath
to build the human form and the bot form.
Now we have two simple codepaths.
The tricky nature of the code had already led
to ugly things for the bot codepath that
fortunately weren't user facing, but which
were distracting:
- For bots we would needlessly set things
like is_admin, is_guest in the template
data.
- For bots we would needlessly try to update
custom profile fields.
The code that differs between bots and humans
is nontrivial, and the code was both hard to read
and hard to improve:
- Humans don't have bot owners.
- Bots don't have custom profile fields.
The bot-owner code is nontrivial for performance
reasons. In a big realm there are tens of thousands
of potential bot owners. We avoid the most egregious
performance problems (i.e we don't have multiple
copies of the dropdown), but we may still want
to refine that (at least adding a spinner).
The custom-profile-fields code is nontrivial due
to the dynamic nature of custom profile fields,
which can bring in specialized widgets like
pill fields.
Now each form corresponds to a single endpoint:
* human -> /json/users
* bot -> /json/bots
Before we had a lot of conditional logic in
the template, the code to build to views, and
the code to submit the data. Now everything is
much flatter.
The human code is still a bit messy (more work
coming on that), but the bot code is fairly
pristine. All three components of the bot code
fit on a page, and there are no conditionals:
- admin_bot_form.hbs
- open_bot_form
- handle_bot_form
We may want to grow out the bot code a bit
to allow admins to do more things, such as
adding services, and this will be easier now.
It would also be easier for us now to share
widgets with the per-user bot settings.
Note that the form for editing human data will
continue to be invoked from two panels:
- Users
- Deactivated users
There are some minor differences between
users and deactivated users, but the shape of
the data is the same for both, so that's still
all one codepath.
We eliminate `reset_edit_user` here, since
it was never used.
One nice thing about these forms was that they
had very little custom CSS attached to them
(at form-level specificity), and it turned out
all the custom CSS was for the human-specific
form.
This is purely refactoring.
The new call tree is:
on_load_success
populate_users
handle_deactivation
handle_reactivation
handle_user_form
handle_bot_owner_profile
handle_bot_deactivation
The actual sequence of operations should be
identical to before.
When reading the calling code, it's helpful to know
that we're really just passing in a selector. The
calls to open_modal/close_modal are nicer now to
reconcile with surrounding code, and you don't have
to guess whether the parameter is some kind of
"key" value--it really just refers directly to a DOM
element.
There is nothing user-visible about this change, but
the blueslip info messages now include the hash:
open modal: open #change_email_modal
Since production testing of `message_retention_days` is finished, we can
enable this feature in the organization settings page. We already had this
setting in frontend but it was bit rotten and not rendered in templates.
Here we replaced our past text-input based setting with a
dropdown-with-text-input setting approach which is more consistent with our
existing UI.
Along with frontend changes, we also incorporated a backend change to
handle making retention period forever. This change introduces a new
convertor `to_positive_or_allowed_int` which only allows positive integers
and an allowed value for settings like `message_retention_days` which can
be a positive integer or has the value `Realm.RETAIN_MESSAGE_FOREVER` when
we change the setting to retain message forever.
This change made `to_not_negative_int_or_none` redundant so removed it as
well.
Fixes: #14854
It's a preliminary step to enable message_retention_setting in org settings
UI, which is a non-limited plan only feature. So we require a page_param
property that tells us the limited-plan state of the Zulip realm.
This change makes `.get_input_element_value()` return a `undefined` instead
of `null` when `input_type` is not defined. Which also make sense
logically, as
> null: absence of value for a variable;
> undefined: absence of variable itself;
Source: https://stackoverflow.com/q/5076944/7418550
In our recent navbar changes, we made it so that the
Esc key auto-closed the navbar. Unfortunately,
that code would break other typeaheads with a traceback.
One user-facing symptom was that if you drafted a PM
and started a typeahead on a recipient, then hitting
the Esc key wouldn't close the typeahead.
Now we use an `on_escape` mechanism that is specific
to the navbar typeahead, so that it's both generic and
harder to break for widgets that don't opt in to it.
See bbdc66a214 for
more details on the commit that introduced this
regression.
Note that I only call `tab_bar.exit_search` now.
I don't check the class name of the input element,
since I know that the Esc key is happening in the
context of search. And I don't blur the input,
since it's going to be hidden.
We were creating errors for task keys that were
from older versions of the widget. We don't migrate
data for the widgets yet (they're all still considered
to be somewhat beta); instead, we just drop bad data
on the floor.
Rohitt and I re-tested the widget on czo pretty
extensively to verify that these errors don't show
up for newly created widgets.
The click handler for closing stream settings in click_handlers.js
is removed as overlays.js contains common logic for closing all
overlays.
'exports.close' in subs.js is removed and 'hashchange.exit_overlay'
is used in 'overlays.open_overlay' call.
This completes the implementation of support for moving a topic to
another stream by adding a basic UI for it.
Fixes#6427, which was previously the most-upvoted issue request in
Zulip.
There are likely to be a bunch of follow-up UI improvements on top of
this change to fully flesh out the feature.
For privacy-minded folks who don't want to leak the
information of whether they're online, this adds an
option to disable sending presence updates to other
users.
The new settings lies in the "Other notification
settings" section of the "Notification settings"
page, under a "Presence" subheading.
Closes#14798.
This adds a way to keep track of max_message_id of a
stream and fetch it using the method get_max_message_id().
This will be useful for sorting streams by most recent
activity which will be implemented in the upcoming commit.
Essentially rewritten by tabbott to have a coherent tracking system,
and provide documentation.
Part of #10794.
Member of the org can able see list of invitations sent by him/her.
given permission for the member to revoke and resend the invitations
sent by him/her and added tests for test member can revoke and resend
the invitations only sent by him/her.
Fixes#14007.
This does not rely on the desktop app being able to register for the
zulip:// scheme (which is problematic with, for example, the AppImage
format).
It also is a better interface for managing changes to the system,
since the implementation exists almost entirely in the server/webapp
project.
This provides a smoother user experience, where the user doesn't need
to do the paste step, when combined with
https://github.com/zulip/zulip-desktop/pull/943.
Fixes#13613.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
Previously, a spinner was created and this spinner element passed to
do_settings_change function, which also created a spinner, making the
first spinner creation useless. This commit removes the spinner creation
logic and just passes the element where the spinner is to be rendered.
Prior to this change, there were reports of 500s in
production due to `export.extra_data` being a
Nonetype. This was reproducible using the s3
backend in development when a row was created in
the `RealmAuditLog` table, but the export failed in
the `DeferredWorker`. This left an entry lying
about that was never updated with an `extra_data`
field.
To fix this, we catch any exceptions in the
`DeferredWorker`, and then update `extra_data` to
encode the failure. We also fix the fact that we
never updated the export UI table with pending exports.
These changes also negated the use for the somewhat
hacky `clear_success_banner` logic.
This removes the weird edit-bot sidebar, replacing it with a modal,
matching our edit-user widget (and various similar ones).
Fixes#13644 by removing the buggy code.
When switching from Private Messages narrow to
All messages narrow, stream list max-height was not
correctly updated. Stream list max-height was calculated
before new height were updated by browser for
All message narrow.
Inshort:
Stream list max-height was being updated before the browser could
render height for `#global_filters`. Calling resize after narrow
completes removes this issue.
This will eventually let us delete a bit of annoying compatibility
code from the desktop app’s injected JavaScript.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
Running the close handler won’t break anything; it’s safe to delete
from a Map while iterating through it.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This exists in all versions of the desktop app that we still support,
and will eventually let us delete a bit of annoying compatibility code
from the desktop app’s injected JavaScript.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
The condition was removed because in either case we
want to have the stream_row and not the sub/unsub
button, so we can always get the stream_row directly.
We had a user have problems with the user
profile menus that you get when you click
on either sender avatars or mention pills.
If a deactivated user had a long enough email
that we would normally want to un-hide the clipboard
icon for them, we would crash inside of
`init_email_clipboard`, because the icon isn't
there for them. If the user didn't have the
console open to see the crash, the symptom
became that you would get multiple cards
visible and kind of "stuck".
I chose to fix this by just making the code
defensive with respect to the absence of the
icon, instead of short-circuiting it for
deactivated users.
It's a bit odd that we still have an element
matching `.user_email_popover` in the profile
card for deactivated users, since that element
doesn't actually include an email, but it instead
says "(This user has been deactivated)". I
considered removing the class, but the CSS
that we use for emails kind of applies here
too.
Testing this is a kind of a pain, as you want
either long emails or to just temporarily hack
this condition to true:
if (this.clientWidth < this.scrollWidth) {
// ...
}
And then test with a deactivated user, of course.
Fixes#14473
Previously, the message and event APIs represented the user differently
for the same reaction data. To make this more consistent, I added a
user_id field to the reaction dict for both messages and events. I
updated the front end to use the user_id field rather than the user
dict. Lastly, I updated front end and back end tests that used user
info.
I primarily tested this by running my local Zulip build and
adding/removing reactions from messages.
Fixes#12049.
The check here was too late, and it should
have given a blueslip error. We obviously
don't expect these errors at runtime; this
is a convenience for developers creating
new widgets.
When clicking on the tick to subscribe to a stream,
an error occurred while trying to find the spinner
location because there are two DOM elements with the
same class, sub_unsub_button, and this made the
selector get the subscribe/unsubscribe button instead
the correct stream_row, where the tick is.
We now check whether the tick or the subscribe/unsubscribe
button was clicked, and if it was the last one we make
sure the stream_row and not the button is being passed
to the sub_or_unsub function.
1. Replaced the deactivate and reactivate buttons with icons.
2. Added (you) near the current user name to denote his/her account in
the entire user list.
Tweaked by tabbott to reuse the (you) formatting from the right
sidebar here for readability and consistency.
Fixes#6313.
This commit:
- Switches margin for padding on the search closed icon, to ensure we
cover the region to the right of icon as clickable area.
- Applies the click handler that initiates the search to the second
last element of the navbar:
- This will most commonly be the narrow_description element, but may
also be the entire navbar eg in the case of "ALL" or "starred".
Applying this change to user names in "group-pm-with: ..." based
narrows is a little questionable, but there are no other triggers
on these names so this change makes sense for now.
- The narrow_description may also contain links, which need to be
handled correctly so that the behave like links should. We work
around the onClick on the narrow_description, by applying a
handler to <a> tags and invoking stopPropagation.
- We also add CSS to change the cursor to a pointer to make the
search icon change color on hover over the clickable area to
indicate that the search box can be opened with a single click.
- However, since <a> tags are handled differently, we add a hover
listener which makes sure it behaves appropriately. We also increase
the vertical padding of the <a> tags so they cover the entire
vertical navbar region.
This is a finicky change; we need to adapt around bootstrap internals
to first steal focus from the list, and then if the user uses arrow
keys, send that key to the list letting bootstrap focus on the list
elements.
The reverse: stealing abck focus to the input from the list, is not
possible without changing third/bootstrap.js because it's concept of
currently selected item depends on the item being focused. We retain
the pre-commit behavior for this, where the user can SHIFT+TAB to get
back to the input and type.
Ideally, a user will now interact with this widget like this:
1. Click the button to open the widget. The input is in focus.
2. Type a query to filter the results.
3. Seemlessly start using arrow keys to select an option.
4. Press "enter" to select the option.
We shouldn't add redundant data to page_params. Since we already have
page_params.realm_notifications_stream_id, we can use that value instead
of creating page_params.notifications_stream.
We, however, still need the name of the notifications stream to render
it in templates. Thus we create stream_data.get_notifications_stream().
This commit removes most of the duplicate logic for the stream selection
dropdowns for the settings: `realm_signup_notifications_stream_id` and
`realm_notifications_stream_id`.
We also make minot changes to DropdownListWidget to accomodate the stream
rendering of the format: `#stream_name`.
We finally switch to using stream_ids instead of stream_name everywhere
which makes reading data from page_params simpler.
'get_active_message_people` function is added which returns active
users who have sent the messages that are currently showing up in
the feed.
typeahead fetches the users from 'get_active_message_people` instead
of `get_message_people` and thus shows only active users in the
mention typeahead and excludes deactivated users.
Fixes#14310
It is more semantically accurate to remove these elements instead of
just hiding them. We were previously using a .empty().append() chain
during creation/display of these forms, hence, we clearly don't desire
to preserve the element anyway (neither are there any worthwhile
benefits of trying to).
Message_edit.js had a bug where if the inline topic_edit failed, it
would not show an error because it attempted to make a look up for
the message_id as though it were a message row edit, which would not
work. That was changed in a refactor, which made it apparent that
there was no error being rendered at all. This commit corrects it by
rendering the error, it also adds some styling to ensure the error
message is displayed inline and it makes a change to the template so
the error is rendered before the spinner.
This commit cleans up the dirty if/else structure of
handle_edit_keydown by switching to switch case statements, and also
separates the handler for inline_topic_edits and that for message
row edits.
This commit makes it so that inline (recipient bar) topic edits follow
a different path from full message row edits in `message_edit.js`.
This commit:
- deletes `.save()` endpoint and replaces all calls to it with
`.save_message_row_edit()` and `.save_inline_topic_edit()`
- deletes `.end()` endpoint and replaces all calls to it with calls to
either ".end_message_row_edit()" and ".end_inline_topic_edit()".
As long as the current narrow isn't already a search narrow or empty,
we add a single space at the end of the current filter so that the
user can just press the right arrow key and begin typing their search
term, instead of having to add a space themselves.
The set_up_muted_topics_ui and templates have been
refactored to use list_render.
This is done to support filtering and sorting of
the muted stream topics.
This also includes the addition of a new Date muted header.
This commit makes sure that we replace the text in the search box
every time a user calls `exit_search()` eg via the escape hotkey or by
clicking the `x` icon, so that the search box discards any input and
always starts at the current narrow.
The div containing options for filtering streams was placed in the
centre. Aligned it towards the right. Had to pass a special check
variable in subs.js:540 to add the specific class for this purpose.
This was a specific scenario where this sort of CSS was to be added,
hence had to make a specific case.
Also, fixed the bottom border color of the search streams bar for night
mode.
Previously, we would always pick up the stream and topic name from
compose_state. This would work for message edits as well when the
composebox was open.
Now, if we are in a message edit, we get the stream and topic of the
message being edited before falling back on trying to populate using
the composebox state.
Fixes#14545.
This commit changes the code to show user according to emails based
on email_address_visibilty_values and the type of user.
1. email_address_visibility = admins,members and guests
Typeaheads are shown according to original emails.
2. email_address_visibility = admins only
Typeaheads are shown according to original email to admins which
were previously shown according to system-generated email of
form "user10@zulipdev.com".
For non-admins, typeaheads are not shown according to emails as
they are not visible in the typeahead itself to non-admins.
3. email_address_visibility = nobody
Typeaheads are not shown according to emails for all type of users.
Previously, when email_address_visibility was set to admins only, the
non-admin users were not shown emails in typeaheads, while admins were
shown emails of the form 'user11@zulipdev.com'.
This commit corrects it to show the original emails in typeaheads and
input box of adding subscribers to admins and the behaviour is same
for non-admins.
This commit moves the get_visible_email function to people.js
as this function will be used in other places and people.js seems
relevant file for this.
Tests are added to get full coverage.
This change adds a toggle widget to the "add streams" page that
lets the user change the sort order of the streams list. So far,
this supports sorting by stream name, by number of subscribers,
or by estimated weekly traffic.
Previously, in narrow viewports, the "filter"
option would disappear, which was very confusing.
This commit moves the filter streams input to the
next line, making it visible at all viewport widths.
@showell modified the commit message and got Casper
tests passing.
Fixes#12898.
This removes the messy click-or-drag detection algorithm originally
added in fe8f63c389, which fixed a messy
bug in an earlier algorithm from ~2013, whose sole purpose as to check
whether we're doing a selection and if so, not trigger the
click-on-message-body click handler.
The right fix is of course to do that check correctly.
We can use getSelection to distinguish between clicks and drags while
accessing the body of a saved draft. Previously, the draft would be
restored when trying to select draft text to copy/paste.
Fixes#14447.
Before this change, on clicking a checkbox to toggle subscription to a
stream no UI feedback was shown and users could toggle the checkbox
multiple times to send multiple requests causing bugs. This commit
initializes a spinner on clicking the checkbox, to provide a UI feedback
to the user. This commit also disables the checkbox once a request for
subscription has been sent and re-enables the checkbox only after a
response.
This change has been accomplished by introducing a div to display the
spinner in subscription.hbs. The corresponding styles for the spinner
have been added in subscriptions.scss. The ajaxSubscribe &
ajaxUnsubscribe functions in subs.js have been updated to show & hide
the spinners for the time the request is in process. An additional
parameter, the concerned stream object is passed to these functions(
through the sub_or_unsub function) to get the location where the spinner
is to be displayed. Finally, the checkbox click handler is updated to
support these changes.
The testing for this has been done by adding a wait of 2 secs in
actions.py for the response. This gives sufficient time to test the
working manually. Also, for error cases an error has been sent from
action.py and the behaviour has been manually observed.
Fixes#14481.
Some uploads can be rejected in the frontend, like when the file
size is too big, without sending the file to the server. Remove the
'Uploading file...' message from the compose box in such cases.
Now, the system uses word='' and an editing=True for rendering an
form for addition of alert words. This is a very vulnerable
way to implement said feature and this commit fixes that.
The addition form has been moved to alert_word_settings.hbs
thereby rendering it only once but always. Now, we do not have
to manually add an empty word and editing for the form to be
rendered.
As part of refactoring, the editing parameter has also been
removed as there is no purpose left.
This updates the logged-in top navbar to display the stream/message
name, number of users, and description. It also replaces the search
bar with a search icon that expands into a full-width search bar.
Co-authored-by: Max Nussenbaum <max@maxnuss.com>
Fixes: #164.
Fixes: #5198.
In ee0d4541b4, we renamed the topic_date
-> stream_topic_history, and in the process renamed some local object
properties from .name => .topic_name, and accidentally change the
type for the data from the server as well.
The test fixtures were incorrectly migrated in the same way, so we fix
that as well.
The disabled property actually prevented text selection, so it seems
better to use CSS through the `readonly="readonly"` property.
For this, swapped .prop() with .attr() since .prop() was setting it as
`readonly=""`.
`stream_topic_history` is a more appropriate name as this
module will contain information about last message of a
stream in upcoming commits. Function and variable names
are changed accordingly like:
* topic_history() -> per_stream_history()
* get_recent_names() -> get_recent_topic_names()
* name -> topic_name
If a file cannot be added for upload because of restrictions in frontend
we call cancelAll immediately in 'info-visible' callback. This would
prevent files that are already added to be cancelled but does not cancel
files that are yet to be added. So we use break to prevent any more files
from being added.
Calling uppy.cancelAll() when a batch of uploads is completed
result in the cancelation of any other batch of uploads that is
in progress. This case happens when a user uploads some files
and then tries to upload another bunch of files before the existing
upload is completed.
The form for entering alert words has been moved above the list
of words.
The list of words will be presented alphabetically rather than
time of addition.
This refactors add_default_stream in zerver/views/streams.py to
take in stream_id as parameter instead of stream_name.
Minor changes have been made to test_subs.py and settings_streams.js
accordingly.
Added UI support for uploding the new profile picture by
clicking on the avatar rather than a button.
Added new spinner for loading indication while uploading
a new avatar over the avatar area.
Fixes#10255
The original commit here was sorting bot owners by
id, which is of course meaningless to users:
444ce74a8e
It was also returning 1/-1 in cases where the bot
owner on both sides of a comparison were missing,
which is a big no-no for sorting algorithms.
We want to avoid creating jQuery objects that just
get turned right back into strings by the list
widget, so we now have our template just include
`last_active_date` instead of kludging it in
after the fact, and we return the template
string in `modifier` rather than wrapping it.
To deal with plain HTML we switch to using
`render_now`.
Calling `render_now` leads to a more simple
codepath than `render_date`, beyond just dealing
with text.
The `render_date` function has special-case logic
that only applies to our time dividers in our
message view, which is why we were passing the
strange `undefined` parameter to it before this
fix.
The `render_date` function was also putting
the dates into `update_list` for once-a-day
updates, which is overkill for an admin screen.
We don't use this logic for drafts or attachments
either. I'm not sure how well tested that logic
is, and it's prone to slow leaks.
This commit sets us up to simplify the list
widget not to have bit-rot-prone code related
to jQuery objects.
We now:
- Skip the broken "Never" case. (The way
we were distinguishing "Unknown" from
"Never" was based on brittle checks that
were just wrong due to bitrot--see Steve
Shank on czo as an example. If we want
to make this distinction rigorous in the
future, we should have a clear mechanism.
If somebody's never actually been active,
we probably want to treat that more like
a dead-on-arrival login, anyway, and make
it easy to clean them up.)
- Use the `presence.last_active_date` instead
of reaching into private data structures.
- Avoid the unnecessary intermediate constants
of LAST_ACTIVE_NEVER and LAST_ACTIVE_UNKOWN.
- Avoid setting `last_active` in `populate_users`.
This commit was modified by @showell:
- I cleaned up the commit message.
- I simplified the diff a bit to avoid
some renaming and lexical moves.
We already know which list widget a `<th>`
tag is associated with when we set up the
event handler, so it's silly to read data
from the DOM to find that widget again
when the handler runs.
This commit eliminates a whole class of possible
errors and busy work.
For some widgets we now avoid duplicate redraw
events from this old pattern:
widget = list_render.create(..., {
}).init();
widget.sort(...);
The above code was wasteful and possibly
flicker-y due to the fact that `init` and
`sort` both render.
Now we do this:
widget = list_render.create(..., {
init_sort: [...],
});
For other widgets we just clean up the need
to call `init()` right after `create()`.
We also allow widgets to pass in `sort_fields`
during initialization (since you may want to
have `init_sort` use a custom sort before the
first render.)
Finally, we make the second and third calls
eliminate the prior updates from the previous
widget. This can prevent strange bugs with
double-reversing columns (although that's
been prevented in a better way with a recent
commit), as well as avoiding double work
with sorting.
This code has always been kind of convoluted
and buggy, starting with the first
sorting-related commit, which put filtering
before sorting for some reason:
3706e2c6ba
This should fix bugs like the fact that
changing filter text would not respect
reversed sorts.
Now the scheme is simple:
- external UI actions set `meta` values like
filter_value, reverse_mode, and
sorting_function, as needed, through
simple setters
- use `hard_redraw` to do a redraw and
trigger external actions
- all filtering/sorting/reverse logic on
the *data* happens in a single, simple
function called `filter_and_sort`
We don't use this anywhere. You can do
`git grep -A 40 list_render.create` to verify
this (with a little bit of noise in the grep).
A better strategy for generalizing
this code is to extract the useful logic
into a function that callers can use in their
own custom event handlers, which I'll do
in an upcoming commit.
We put this in `scroll_util` to make it more likely
we will eventually unify this with other scrolling
logic. (A big piece to move is ui.get_scroll_element,
but that's for another PR.)
And then the other tactical advantage is that we get
100% line coverage on it.
I changed the warning to an error, since I don't
think we ever expect scrolling at the `body` level,
and I don't bother with the preview node.
We extract a general purpose widget to create dropdown lists with
search. This widget is used for default code block language, but can
be easily extended to cover notifications_stream and similar options.
The current usage is:
```js
const widget = DropdownListWidget({
setting_name: 'realm_alpha_beta',
data: [{name: 'hello', value: 'world'}, {...}, ...],
subsection: 'msg-editing',
default_text: 'Nothing is selected',
});
```
and
```handlebars
{{> dropdown_list_widget
setting_name="realm_alpha_beta"
list_placeholder=(t 'Filter the data')
reset_button_text=(t '[Unset]')
label=admin_settings_label.realm_alpha_beta }}
```
This can further be refined by shifting more variables from handlebars
to javascript in the future.
By taking these functions out of exports.build_page, we can
reuse them for handling other widgets. We also declare
default_code_language_widget after the helper functions to
avoid the linter complaining.
I pushed this risk commit to the end of
a PR that had a bunch of harmless prep
commits at the front, and I didn't make
it clear enough that the last commit (this
one) hadn't been tested thoroughly.
For the list_render widget, we can simplify
the intialization pretty easily (avoid
extra sorts, for example), but the cache aspects
are still tricky on subsequent calls.
Changes .data() Jquery methods to .attr() to prevent unnecessary data
type conversions of the emoji name.
Tested the fix manually and verified the test-js-with-node test suite.
Fixes: #14377
For some widgets we now avoid duplicate redraw
events from this old pattern:
widget = list_render.create(..., {
}).init();
widget.sort(...);
The above code was wasteful and possibly
flicker-y due to the fact that `init` and
`sort` both render.
Now we do this:
widget = list_render.create(..., {
init_sort: [...],
});
For other widgets we just clean up the need
to call `init()` right after `create()`.
We also allow widgets to pass in `sort_fields`
during initialization (since you may want to
have `init_sort` use a custom sort before the
first render.)
The get() logic here was broken, because
when you enter the settings panel for invites
on the 2nd or 3rd time, the text filter
would not work.
This commit doesn't intend to fix the problem; it
just simplifies the code for a later commit
that fixes this holistically.
The way that we update `list_render` objects
is janky with respect to events, so we can end
up double-sorting lists (which puts them back
to normal) and strange things like that.
This is all cosmetic.
Instead of:
const.widget = {
foo: function () = {
},
bar: function () {
},
};
We have:
const widget = {};
widget.foo = function () = {
};
widget.bar = function () {
};
Before this fix, we'd get a traceback if you looked
at invites in the settings (and if one of them was
a multi-user invite link). This commit fixes
that problem by adding a custom sort.
We also rename the "Email" column to "Invitee",
since it's often the case the invitee isn't an
actually an email, but it's instead a multi-use
link.
Note that the invites UI only works the first time you
enter settings. Many of the controls break the second
time you enter it. You can't sort by column header
or use the text filter.
I'll fix that in a subsequent commit.
Giving these functions a name and moving them to
the top-level scope has a couple tactical advantages:
- names show in tracebacks
- code is less indented
- setup code is less cluttered
- will be easier to add unit tests
- will make some upcoming diffs nicer
These are technically more `compare_foo` than `sort_foo`,
but we already had a naming convention that was sort of
in place.
We had a bug where if your peer mentioned you in
message, but then edited the message not to mention
you, the latter wouldn't reset your unread counts
for "Mentions". And the same problem would happen
vice versa.
The fix basically extracts `update_message_for_mention`
and makes sure it handles all combinations of
unread/mentioned flags, instead of assuming
any invariants about which directions of change
are possible.
And then we call that new function from
`message_events.js` whenever we get message
edit events.
Fixes#14544
Earlier, the non-editable text-boxes(on clicking view source/edit
topic) were not so apparent due to absence of `disabled` attribute.
Adding the `disabled` attribute makes them consistent with the approach
for non-editable text-boxes and text-areas in organization settings
(for non-admins).
Fixes: #14375
The `send_message_ajax` function was a relic
of us having an alternative way to send messages
(web sockets) to the server, but now the indirection
is more confusing than helpful.
This also fixes trying to cancel a resend of a
local message.
The problem were was type confusion between
strings and ints.
The function in `rows.js` may feel like overkill,
but I really want to enforce type safety here,
as we usually treat message ids as floats, but
for the local-echo case we're gonna get
strings. I put it in `rows` because we mostly
do a good job of encapsulating the "zid" role
in the DOM there.
By going directly to the DOM here, we avoid
parsing a string to a float and then converting
it right back to a string, which always make
me queasy about float rounding, so one less
moving part.
Due to type confusion, we were silently failing
to delete local_id values for messages that were
being acked by the server.
This used to work when we kept values in our
old Dict data structure, since client_message.id
and message.local_id are really the same value,
just the former is a float and the latter's a
string, and Dict never cared.
We can avoid all this confusion, though, by just
consistently using `local_id`, which I extract
to a local var.
The function message_send_error was messing up
on calls to message.get when we were passing in
string versions of `local_id`. Now we pass in
float ids.
This fixes a traceback where we tried to set
`.failed_request` on to an `undefined` value
that we had instead expected to be a locally
echoed message from our message store.
This will allow us access to the float version of the
message's id in an upcoming commit, without us having
to do possibly brittle string-to-float translations.
Option is added to video_chat_provider settings for disabling
video calls.
Video call icon is hidden in two cases-
1. video_chat_provider is set to disabled.
2. video_chat_provider is set to Jitsi and settings.JITSI_SERVER_URL
is none.
Relevant tests are added and modified.
Fixes#14483
This adds a new realm setting: default_code_block_language.
This PR also adds a new widget to specify a language, which
behaves somewhat differently from other widgets of the same
kind; instead of exposing methods to the whole module, we
just create a single IIFE that handles all the interactions
with the DOM for the widget.
We also move the code for remapping languages to format_code
function since we want to preserve the original language to
decide if we override it using default_code_clock_language.
Fixes#14404.
The filter-linkifier input box was disabled which prevented users from
filtering through the linkifiers list. Removed the part of code which
caused the input box to be disabled. This allows users to edit the input
and so filter linkifiers.
With EMAIL_ADDRESS_VISIBILITY_NOBODY (or as a non-admin with
EMAIL_ADDRESS_VISIBILITY_HIDDEN), we were incorrectly generating
zuliprc files containing the shareable email address, which naturally
didn't work.
Most failures result from invalid emoji names, so this makes it easier
to recover without re-uploading a file.
Previously, this model would have been problematic, but now that we
have the visual preview, this is clearly better behavior.
This adds a preview of the uploaded emoji image while uploading custom
emoji right below the upload form.
Modified upload_widget.build_widget() to take in the preview
span text and image. In case a parameter isn't passed
for preview text, it defaults to null and the snippets in
build_widgets() related to preview don't run.
Fixes#9229.
Styling tweaked by tabbott.