snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
<div id="account-settings" class="settings-section" data-name="account-and-privacy">
<div class="alert" id="dev-account-settings-status"></div>
<div class="account-settings-form">
<div id="user_details_section">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Account" }}</h3>
<div class="alert-notification account-alert-notification" id="account-settings-status"></div>
</div>
<form class="grid">
{{#if user_has_email_set}}
<div class="input-group">
<label class="settings-field-label {{#unless user_can_change_email}}cursor-text{{/unless}}" for="change_email_button">{{t "Email" }}</label>
<div class="change-email">
<div id="email_field_container" class="inline-block {{#unless user_can_change_email}}disabled_setting_tooltip{{/unless}}">
<input type="email" value="{{current_user.delivery_email}}" class="settings_text_input" disabled="disabled" />
</div>
{{> ../components/icon_button
id="change_email_button"
icon="edit"
intent="neutral"
custom_classes="tippy-zulip-delayed-tooltip"
hidden=(not user_can_change_email)
aria-label=(t "Change your email")
data-tippy-content=(t "Change your email")
}}
</div>
<div id="email-change-status"></div>
</div>
{{else}}
{{! Demo organizations before the owner has configured an email address. }}
<div class="input-group">
<p>
{{#tr}}
Add your email to <z-link-invite-users-help>invite other users</z-link-invite-users-help>
or <z-link-convert-demo-organization-help>convert to a permanent Zulip organization</z-link-convert-demo-organization-help>.
{{#*inline "z-link-invite-users-help"}}<a href="/help/invite-new-users" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{#*inline "z-link-convert-demo-organization-help"}}<a href="/help/demo-organizations#convert-a-demo-organization-to-a-permanent-organization" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
{{> ../components/action_button
id="demo_organization_add_email_button"
label=(t "Add email")
variant="subtle"
intent="brand"
}}
</div>
{{/if}}
</form>
{{#if page_params.two_fa_enabled }}
<p for="two_factor_auth" class="inline-block title">
{{t "Two factor authentication" }}: {{#if page_params.two_fa_enabled_user }}{{t "Enabled" }}{{else}}{{t "Disabled" }}{{/if}}
<a target="_blank" rel="noopener noreferrer" id="two_factor_auth" href="/account/two_factor/" title="{{t 'Set up two factor authentication' }}">[{{t "Setup" }}]</a>
</p>
{{/if}}
<form class="password-change-form grid">
{{#if user_can_change_password}}
<div>
<label class="settings-field-label" for="change_password">{{t "Password" }}</label>
<div class="input-group">
{{> ../components/action_button
label=(t "Change your password")
variant="subtle"
intent="neutral"
id="change_password"
}}
</div>
</div>
{{/if}}
</form>
<form class="user-self-role-change-form grid">
<div class="input-group">
<label for="user-self-role-select" class="settings-field-label">
{{t 'Role' }}
{{> ../help_link_widget link="/help/user-roles" }}
</label>
<select name="user-self-role-select"
class="prop-element settings_select bootstrap-focus-style"
id="user-self-role-select"
data-setting-widget-type="number"
>
{{> dropdown_options_widget option_values=(object_values user_role_values)}}
</select>
</div>
</form>
<div class="input-group deactivate-buttons-group">
<div id="deactivate_account_container" class="inline-block {{#if user_is_only_organization_owner}}disabled_setting_tooltip{{/if}}">
{{> ../components/action_button
label=(t "Deactivate account")
variant="subtle"
intent="danger"
id="user_deactivate_account_button"
disabled=user_is_only_organization_owner
}}
</div>
{{#if owner_is_only_user_in_organization}}
{{> ../components/action_button
label=(t "Deactivate organization")
variant="subtle"
intent="danger"
custom_classes="deactivate_realm_button"
}}
{{/if}}
</div>
</div>
{{> privacy_settings . for_realm_settings=false prefix="user_" read_receipts_help_icon_tooltip_text=send_read_receipts_tooltip hide_read_receipts_tooltip=realm.realm_enable_read_receipts}}
<div id="api_key_button_box">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "API key" }}</h3>
</div>
<div class="input-group">
<p class="api-key-note">
{{#tr}}
An API key can be used to programmatically access a Zulip account.
Anyone with access to your API key has the ability to read your messages, send
messages on your behalf, and otherwise impersonate you on Zulip, so you should
guard your API key as carefully as you guard your password. <br />
We recommend creating bots and using the bots' accounts and API keys to access
the Zulip API, unless the task requires access to your account.
{{/tr}}
</p>
<div id="api_key_button_container" class="inline-block {{#unless user_has_email_set}}disabled_setting_tooltip{{/unless}}">
{{> ../components/action_button
label=(t "Manage your API key")
variant="subtle"
intent="neutral"
id="api_key_button"
disabled=(not user_has_email_set)
}}
</div>
</div>
</div>
<!-- Render /settings/api_key_modal.hbs after #api_key_button is clicked
to avoid password being inserted by password manager too aggressively. -->
</div>
</div>

View File

@@ -0,0 +1,38 @@
<div id="admin-active-users-list" class="user-settings-section user-or-bot-settings-section" data-user-settings-section="active">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Users"}}</h3>
<div class="alert-notification" id="user-field-status"></div>
<div class="user_filters">
{{> ../dropdown_widget widget_name=active_user_list_dropdown_widget_name}}
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter users')}}
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="settings-email-column" data-sort="email">{{t "Email" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="user_role" data-sort="role">{{t "Role" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="last_active" data-sort="last_active">{{t "Last active" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
{{#if is_admin}}
<th class="actions">{{t "Actions" }}</th>
{{/if}}
</tr>
</thead>
<tbody id="admin_users_table" class="admin_user_table"
data-empty="{{t 'No users match your filters.' }}"></tbody>
</table>
</div>
<div id="admin_page_users_loading_indicator"></div>
</div>

View File

@@ -0,0 +1,4 @@
<form class="modal-form" id="add-alert-word-form">
<label for="add-alert-word-name" class="modal-field-label">{{t "Alert word" }}</label>
<input type="text" name="alert-word-name" id="add-alert-word-name" class="required modal_text_input" maxlength=100 placeholder="{{t 'Alert word' }}" value="" />
</form>

View File

@@ -0,0 +1,3 @@
<table class="default_stream_choices_table">
<tbody id="default-stream-choices"></tbody>
</table>

View File

@@ -0,0 +1,28 @@
<form class="modal-form" id="add-custom-emoji-form">
<div>
<input type="file" name="emoji_file_input" class="notvisible"
id="emoji_file_input" value="{{t 'Upload image or GIF' }}"/>
{{> ../components/action_button
label=(t "Clear image")
variant="subtle"
intent="danger"
id="emoji_image_clear_button"
hidden=true
}}
{{> ../components/action_button
label=(t "Upload image or GIF")
variant="subtle"
intent="brand"
id="emoji_upload_button"
}}
<div style="display: none;" id="emoji_preview_text">
{{t "Preview:" }} <i id="emoji_placeholder_icon" class="fa fa-file-image-o" aria-hidden="true"></i><img class="emoji" id="emoji_preview_image" src=""/>
</div>
<div id="emoji-file-name"></div>
</div>
<div id="emoji_file_input_error" class="text-error"></div>
<div class="emoji_name_input">
<label for="emoji_name" class="modal-field-label">{{t "Emoji name" }}</label>
<input type="text" name="name" id="emoji_name" class="modal_text_input" autocomplete="off" placeholder="{{t 'leafy green vegetable' }}" />
</div>
</form>

View File

@@ -0,0 +1,88 @@
<form class="modal-form" id="create_bot_form">
{{#unless user_has_email_set}}
<div class="demo-organization-add-email-banner banner-wrapper"></div>
{{/unless}}
<div class="new-bot-form">
<div class="input-group">
<label for="create_bot_type" class="modal-field-label">
{{t "Bot type" }}
{{> ../help_link_widget link="/help/bots-overview#bot-type" }}
</label>
<select name="bot_type" id="create_bot_type" class="modal_select bootstrap-focus-style">
{{#each bot_types}}
<option value="{{this.type_id}}">{{this.name}}</option>
{{/each}}
</select>
</div>
<div class="input-group" id="service_name_list">
<label for="select_service_name" class="modal-field-label">{{t "Bot"}}</label>
<select name="service_name" id="select_service_name" class="modal_select bootstrap-focus-style">
{{#each realm_embedded_bots}}
<option value="{{this.name}}">{{this.name}}</option>
{{/each}}
</select>
</div>
<div class="input-group">
<label for="create_bot_name" class="modal-field-label">{{t "Name" }}</label>
<input type="text" name="bot_name" id="create_bot_name" class="required modal_text_input"
maxlength=100 placeholder="{{t 'Cookie Bot' }}" value="" />
<div><label for="create_bot_name" generated="true" class="text-error"></label></div>
</div>
<div class="input-group">
<label for="create_bot_short_name" class="modal-field-label">{{t "Bot email (a-z, 0-9, and dashes only)" }}</label>
<input type="text" name="bot_short_name" id="create_bot_short_name" class="required bot_local_part modal_text_input"
placeholder="{{t 'cookie' }}" value="" />
-bot@{{ realm_bot_domain }}
<div>
<label for="create_bot_short_name" generated="true" class="text-error"></label>
</div>
</div>
<div id="payload_url_inputbox">
<div class="input-group">
<label for="create_payload_url" class="modal-field-label">{{t "Endpoint URL" }}</label>
<input type="text" name="payload_url" id="create_payload_url" class="modal_text_input"
maxlength=2083 placeholder="https://hostname.example.com" value="" />
<div><label for="create_payload_url" generated="true" class="text-error"></label></div>
</div>
<div class="input-group">
<label for="interface_type" class="modal-field-label">{{t "Webhook format" }}</label>
<select name="interface_type" id="create_interface_type" class="modal_select bootstrap-focus-style">
<option value="1">Zulip</option>
<option value="2">{{t "Slack-compatible" }}</option>
</select>
<div><label for="create_interface_type" generated="true" class="text-error"></label></div>
</div>
</div>
<div id="config_inputbox">
{{#each realm_embedded_bots}}
{{#each (object_entries config) as |entry|}}
{{> ../embedded_bot_config_item botname=../name key=entry.[0] value=entry.[1]}}
{{/each}}
{{/each}}
</div>
<div class="input-group">
<label for="bot_avatar_file_input" class="modal-field-label">{{t "Avatar" }}</label>
<div id="bot_avatar_file"></div>
<input type="file" name="bot_avatar_file_input" class="notvisible" id="bot_avatar_file_input" value="{{t 'Upload avatar' }}" />
<div id="add_bot_preview_text">
<img id="add_bot_preview_image" />
</div>
{{> ../components/action_button
label=(t "Clear avatar")
variant="subtle"
intent="danger"
id="bot_avatar_clear_button"
hidden=true
}}
{{> ../components/action_button
label=(t "Upload avatar")
variant="subtle"
intent="neutral"
id="bot_avatar_upload_button"
custom_classes="inline-block"
}}
({{t "Optional" }})
</div>
<p id="bot_avatar_file_input_error" class="text-error"></p>
</div>
</form>

View File

@@ -0,0 +1,66 @@
<form class="admin-profile-field-form modal-form" id="add-new-custom-profile-field-form">
<div class="new-profile-field-form wrapper">
<div class="input-group">
<label for="profile_field_type" class="modal-field-label">{{t "Type" }}</label>
<select id="profile_field_type" name="field_type" class="modal_select bootstrap-focus-style">
{{#each custom_profile_field_types}}
<option value='{{this.id}}'>{{this.name}}</option>
{{/each}}
</select>
</div>
<div class="input-group" id="profile_field_external_accounts">
{{> ../dropdown_widget_with_label widget_name="external_accounts_type" label=(t "External accounts")}}
</div>
<div class="input-group">
<label for="profile_field_name" class="modal-field-label">{{t "Label" }}</label>
<input type="text" id="profile_field_name" class="modal_text_input" name="name" autocomplete="off" maxlength="40" />
</div>
<div class="input-group">
<label for="profile_field_hint" class="modal-field-label">{{t "Hint (up to 80 characters)" }}</label>
<input type="text" id="profile_field_hint" class="modal_text_input" name="hint" autocomplete="off" maxlength="80" />
<div class="alert" id="admin-profile-field-hint-status"></div>
</div>
<div class="input-group profile-field-choices-wrapper" id="profile_field_choices_row">
<label for="profile_field_choices" class="modal-field-label">{{t "Field choices" }}</label>
<table class="profile_field_choices_table">
<tbody id="profile_field_choices" class="profile-field-choices"></tbody>
</table>
{{> ../components/action_button
label=(t "Alphabetize choices")
custom_classes="alphabetize-choices-button"
intent="neutral"
variant="subtle"
}}
</div>
<div class="input-group" id="custom_external_account_url_pattern">
<label for="custom_field_url_pattern" class="modal-field-label">{{t "URL pattern" }}</label>
<input type="url" id="custom_field_url_pattern" class="modal_url_input" name="url_pattern" autocomplete="off" maxlength="1024" placeholder="https://example.com/path/%(username)s"/>
</div>
<div class="input-group">
<label class="checkbox profile_field_display_label" for="profile_field_display_in_profile_summary">
<input type="checkbox" id="profile_field_display_in_profile_summary" name="display_in_profile_summary"/>
<span class="rendered-checkbox"></span>
{{t 'Display on user card' }}
</label>
</div>
<div class="input-group">
<label class="checkbox" for="profile-field-required">
<input type="checkbox" id="profile-field-required" name="required"/>
<span class="rendered-checkbox"></span>
{{t 'Required field' }}
</label>
</div>
{{> settings_checkbox
prefix="profile_field_"
setting_name="editable_by_user"
is_checked=true
label=(t "Users can edit this field for their own account")
}}
{{> settings_checkbox
prefix="profile_field_"
setting_name="use_for_user_matching"
is_checked=false
label=(t "Use in @-mention suggestions")
}}
</div>
</form>

View File

@@ -0,0 +1,10 @@
<div class="method_row" data-method="{{method}}">
{{> settings_checkbox
setting_name="realm_authentication_methods"
prefix=prefix
is_checked=enabled
label=method
is_disabled=disable_configure_auth_method
help_icon_tooltip_text=unavailable_reason
skip_prop_element=true}}
</div>

View File

@@ -0,0 +1,40 @@
<tr class="channel-folder-row movable-row" data-channel-folder-id="{{id}}">
<td>
{{#if is_admin}}
<span class="move-handle">
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</span>
{{/if}}
<span class="channel-folder-name">{{folder_name}}</span>
</td>
<td>
<span class="channel-folder-description rendered-markdown">{{rendered_markdown rendered_description}}</span>
</td>
{{#if is_admin}}
<td class="actions">
{{> ../components/icon_button
icon="folder-cog"
intent="neutral"
custom_classes="tippy-zulip-delayed-tooltip edit-channel-folder-button"
data-tippy-content=(t "Manage folder")
}}
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="tippy-zulip-delayed-tooltip archive-channel-folder-button"
data-tippy-content=(t "Delete")
aria-label=(t "Delete")
}}
</td>
{{else}}
<td class="actions">
{{> ../components/icon_button
icon="preview"
intent="neutral"
custom_classes="tippy-zulip-delayed-tooltip edit-channel-folder-button"
data-tippy-content=(t "View details")
}}
</td>
{{/if}}
</tr>

View File

@@ -0,0 +1,26 @@
<div id="channel-folder-settings" class="settings-section" data-name="channel-folders">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Channel folders"}}</h3>
<div class="alert-notification" id="admin-channel-folder-status"></div>
{{#if is_admin}}
{{> ../components/action_button
custom_classes="add-channel-folder-button"
label=(t "Add a new channel folder")
variant="subtle"
intent="brand"
}}
{{/if}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped admin_channel_folders_table">
<thead>
<tr>
<th>{{t "Name" }}</th>
<th>{{t "Description" }}</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="admin_channel_folders_table" data-empty="{{t 'No channel folders configured.' }}"></tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,26 @@
{{#with stream}}
<tr class="default_stream_row hidden-remove-button-row" data-stream-id="{{stream_id}}">
<td>
<span class="pill-container display_only_pill">
<span class="pill" data-stream-id="{{stream_id}}" tabindex="0">
<span class="pill-label">
<span class="pill-value">
{{> ../decorated_channel_name stream=this}}
</span>
</span>
</span>
</span>
</td>
{{#if ../can_modify}}
<td class="actions">
{{> ../components/icon_button
icon="close"
intent="danger"
custom_classes="remove-default-stream tippy-zulip-delayed-tooltip hidden-remove-button"
aria-label=(t "Remove from default")
data-tippy-content=(t "Remove from default")
}}
</td>
{{/if}}
</tr>
{{/with}}

View File

@@ -0,0 +1,35 @@
{{#with emoji}}
<tr class="emoji_row" id="emoji_{{name}}" data-emoji-name="{{name}}">
<td>
<span class="emoji_name">{{display_name}}</span>
{{#if is_overriding_default}}
<i class="zulip-icon zulip-icon-exclamation-circle tippy-zulip-tooltip emoji-override-warning" data-tippy-content="{{t 'This custom emoji overrides a default emoji with the same name.' }}"></i>
{{/if}}
</td>
<td>
<span class="emoji_image">
<a href="{{source_url}}" target="_blank" rel="noopener noreferrer">
<img class="emoji" src="{{source_url}}" alt="{{display_name}}" />
</a>
</span>
</td>
<td>
{{#if author}}
{{#with author}}
<span class="emoji_author panel_user_list">{{> ../user_display_only_pill . display_value=full_name img_src=avatar_url}}</span>
{{/with}}
{{else}}
<span class="emoji_author">{{t "Unknown author" }}</span>
{{/if}}
</td>
<td>
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="tippy-zulip-delayed-tooltip delete"
disabled=(not can_delete_emoji)
data-tippy-content=(t "Deactivate")
}}
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,10 @@
{{#with export_consent}}
<tr>
<td class="user_name panel_user_list">
{{> ../user_display_only_pill display_value=full_name user_id=user_id img_src=img_src is_active=true}}
</td>
<td>
<span>{{consent}}</span>
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,37 @@
{{#with realm_export}}
<tr class="export_row" id="export_{{id}}" data-export-id="{{id}}">
<td>
<span class="acting_user">{{acting_user}}</span>
</td>
<td>
<span>{{export_type_description}}</span>
</td>
<td>
<span class="export_time">{{event_time}}</span>
</td>
<td>
{{#if url}}
<span class="export_url"><a href="{{url}}" download>{{t 'Complete' }}</a></span>
{{else if time_failed}}
<span class="export_status">{{t 'Failed' }}: {{time_failed}}</span>
{{else if pending}}
<div class="export_url_spinner"></div>
{{else if time_deleted}}
<span class="export_status">{{t 'Deleted' }}: {{time_deleted}}</span>
{{else if export_from_prior_server}}
<span class="export_status">{{t 'Export from a prior server' }}</span>
{{/if}}
</td>
<td class="actions">
{{#if url}}
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="tippy-zulip-delayed-tooltip delete"
data-tippy-content=(t "Delete")
aria-label=(t "Delete")
}}
{{/if}}
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,40 @@
<div id="edit-user-form" data-user-id="{{user_id}}">
<form class="name-setting">
<div id="edit-user-form-error" class="banner-wrapper"></div>
<input type="hidden" name="is_full_name" value="true" />
<div class="input-group name_change_container">
<label for="edit_user_full_name" class="modal-field-label">{{t "Name" }}</label>
<input type="text" autocomplete="off" name="full_name" id="edit_user_full_name" class="modal_text_input" value="{{ full_name }}" maxlength="{{max_user_name_length}}" />
</div>
{{#if email}}
<div class="input-group email_change_container">
<label for="email" class="modal-field-label">{{t "Email" }}</label>
<input type="text" autocomplete="off" name="email" class="modal_text_input" value="{{ email }}" readonly/>
</div>
{{/if}}
<div class="input-group user_id_container">
<label for="user_id" class="modal-field-label">{{t "User ID" }}</label>
<input type="text" autocomplete="off" name="user_id" class="modal_text_input" value="{{ user_id }}" readonly/>
</div>
<div class="input-group">
<label for="user-role-select" class="modal-field-label">{{t 'User role' }}
{{> ../help_link_widget link="/help/user-roles" }}
</label>
<select name="user-role-select" class="bootstrap-focus-style modal_select" id="user-role-select" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values user_role_values)}}
</select>
</div>
<div class="custom-profile-field-form"></div>
</form>
<div class="input-group {{#if hide_deactivate_button}}hide{{/if}}">
<div class="deactivate-user-container {{#if user_is_only_organization_owner}}disabled_setting_tooltip{{/if}}">
{{#if is_active}}
{{> ../components/action_button custom_classes="deactivate-user-button" variant="subtle" intent="danger" label=(t "Deactivate user") aria-label=(t "Deactivate user") disabled=user_is_only_organization_owner }}
{{else}}
{{#unless is_deleted}}
{{> ../components/action_button custom_classes="reactivate-user-button" variant="subtle" intent="success" label=(t "Reactivate user") aria-label=(t "Reactivate user") }}
{{/unless}}
{{/if}}
</div>
</div>
</div>

View File

@@ -0,0 +1,59 @@
{{#with invite}}
<tr class="invite_row" data-invite-id="{{id}}" data-is-multiuse="{{#unless is_multiuse}}false{{else}}true{{/unless}}">
<td>
{{#if is_multiuse}}
<span class="email">
<a href="{{link_url}}" target="_blank" rel="noopener noreferrer">
{{t 'Invite link'}}
</a>
</span>
{{else}}
<span class="email">{{email}}</span>
{{/if}}
</td>
{{#if is_admin}}
<td>
<span class="referred_by panel_user_list">
{{> ../user_display_only_pill display_value=referrer_name user_id=invited_by_user_id is_active=true}}
</span>
</td>
{{/if}}
<td>
<span class="invited_at">{{invited_absolute_time}}</span>
</td>
<td>
{{#if expiry_date_absolute_time}}
<span class="expires_at">{{expiry_date_absolute_time}}</span>
{{else}}
<span class="expires_at">{{t "Never expires"}}</span>
{{/if}}
</td>
<td>
<span>{{invited_as_text}}</span>
</td>
<td class="actions">
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="revoke tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Revoke")
disabled=disable_buttons
}}
{{#unless is_multiuse}}
{{> ../components/icon_button
icon="check"
intent="success"
custom_classes="check hide"
disabled=true
}}
{{> ../components/icon_button
icon="send-dm"
intent="neutral"
custom_classes="resend tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Resend")
disabled=disable_buttons
}}
{{/unless}}
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,26 @@
<div id="add-linkifier-form">
<p>
{{t "For instance, you can add a linkifier that automatically turns #2468 into a link to the GitHub issue in the Zulip repository with:" }}
</p>
<ul>
<li>
{{t "Example text to linkify" }}: <span class="rendered_markdown"><code>#2468</code></span>
</li>
<li>
{{t "Pattern" }}: <span class="rendered_markdown"><code>#(?P&lt;id&gt;[0-9]+)</code></span>
</li>
<li>
{{t "URL template" }}: <span class="rendered_markdown"><code>https://github.com/zulip/zulip/issues/{id}</code></span>
</li>
<li>
{{t "Auto-convert pasted URLs matching the template to" }}: <span class="rendered_markdown"><code>#{id}</code></span>
</li>
<li>
{{t "Alternative URL templates for auto-conversion" }}: <span class="rendered_markdown"><code>https://github.com/zulip/zulip/pull/{id}</code></span>
</li>
</ul>
<form class="linkifier-add-form modal-form" id="add-linkifier-form-modal">
<div class="alert" id="add-linkifier-status"></div>
{{> linkifier_form_fields . }}
</form>
</div>

View File

@@ -0,0 +1,5 @@
<div id="edit-linkifier-form">
<form class="linkifier-edit-form modal-form">
{{> linkifier_form_fields . }}
</form>
</div>

View File

@@ -0,0 +1,45 @@
{{#with linkifier}}
<tr class="linkifier_row{{#if (and ../can_modify ../can_drag)}} movable-row{{/if}}" data-linkifier-id="{{id}}">
<td>
{{#if (and ../can_modify ../can_drag)}}
<span class="move-handle">
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</span>
{{/if}}
<span class="linkifier_example_input rendered_markdown">{{{rendered_example_input_html}}}</span>
</td>
<td>
<span class="linkifier_pattern">{{pattern}}</span>
</td>
<td>
<span class="linkifier_url_template">{{url_template}}</span>
</td>
<td class="convert-cell">
<span {{#if ../can_modify}}class="tippy-zulip-delayed-tooltip" data-tippy-content="{{t 'Edit the linkifier to modify' }}"{{/if}}>
<label class="checkbox">
<input type="checkbox" class="linkifier_convert_pasted_urls" {{#if reverse_template}}checked{{/if}} disabled />
<span class="rendered-checkbox"></span>
</label>
</span>
</td>
{{#if ../can_modify}}
<td class="no-select actions">
{{> ../components/icon_button
icon="edit"
intent="neutral"
custom_classes="tippy-zulip-delayed-tooltip edit"
data-tippy-content=(t "Edit")
aria-label=(t "Edit")
}}
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="tippy-zulip-delayed-tooltip delete"
data-tippy-content=(t "Delete")
aria-label=(t "Delete")
}}
</td>
{{/if}}
</tr>
{{/with}}

View File

@@ -0,0 +1,24 @@
{{#with playground}}
<tr class="playground_row" data-playground-id="{{id}}">
<td>
<span class="playground_pygments_language">{{pygments_language}}</span>
</td>
<td>
<span class="playground_name">{{playground_name}}</span>
</td>
<td>
<span class="playground_url_template">{{url_template}}</span>
</td>
{{#if ../can_modify}}
<td class="no-select actions">
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="delete-code-playground delete"
data-tippy-content=(t "Delete")
aria-label=(t "Delete")
}}
</td>
{{/if}}
</tr>
{{/with}}

View File

@@ -0,0 +1,54 @@
{{#with profile_field}}
<tr class="profile-field-row movable-row" data-profile-field-id="{{id}}">
<td class="profile_field_name">
{{#if ../can_modify}}
<span class="move-handle">
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</span>
{{/if}}
<span class="profile_field_name">{{name}}</span>
</td>
<td class="profile_field_hint">
<span class="profile_field_hint">{{hint}}</span>
</td>
<td>
<span class="profile_field_type">{{type}}</span>
</td>
<td class="display_in_profile_summary_cell">
{{#if valid_to_display_in_summary}}
<span class="profile_field_display_in_profile_summary">
<label class="checkbox display_in_profile_summary_{{#if display_in_profile_summary}}true{{else}}false{{/if}}" for="profile_field_display_in_profile_summary_{{id}}">
<input class="display_in_profile_summary display_in_profile_summary_checkbox_{{#if display_in_profile_summary}}true{{else}}false{{/if}}" type="checkbox" id="profile_field_display_in_profile_summary_{{id}}" {{#if display_in_profile_summary}} checked="checked" {{/if}} data-profile-field-id="{{id}}"/>
<span class="rendered-checkbox"></span>
</label>
</span>
{{/if}}
</td>
<td class="required-cell">
<span class="profile-field-required">
<label class="checkbox" for="profile-field-required-{{id}}">
<input class="required-field-toggle required-checkbox-{{#if required}}true{{else}}false{{/if}}" type="checkbox" id="profile-field-required-{{id}}" {{#if required}} checked="checked" {{/if}} data-profile-field-id="{{id}}"/>
<span class="rendered-checkbox"></span>
</label>
</span>
</td>
{{#if ../can_modify}}
<td class="actions">
{{> ../components/icon_button
icon="edit"
intent="neutral"
custom_classes="tippy-zulip-delayed-tooltip open-edit-form-modal"
data-tippy-content=(t "Edit")
}}
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="tippy-zulip-delayed-tooltip delete"
data-tippy-content=(t "Delete")
aria-label=(t "Delete")
}}
</td>
{{/if}}
</tr>
{{/with}}

View File

@@ -0,0 +1,20 @@
{{#with realm_domain}}
<tr>
<td class="domain">{{domain}}</td>
<td>
<label class="checkbox">
<input type="checkbox" class="allow-subdomains"
{{#if allow_subdomains}} checked="checked" {{/if}} />
<span class="rendered-checkbox"></span>
</label>
</td>
<td>
{{> ../components/action_button
label=(t "Remove")
custom_classes="delete_realm_domain"
variant="subtle"
intent="danger"
}}
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,2 @@
<div id="user-info-form-modal-container"></div>
<div id="linkifier-edit-form-modal-container"></div>

View File

@@ -0,0 +1,32 @@
<div class="alert" id="organization-status"></div>
<div id="revoke_invite_modal_holder"></div>
{{> admin_settings_modals}}
{{> organization_profile_admin . }}
{{> organization_settings_admin . }}
{{> organization_permissions_admin . }}
{{> organization_user_settings_defaults . }}
{{> emoji_settings_admin . }}
{{> user_list_admin . }}
{{> bot_list_admin . prefix="admin" }}
{{> admin_channel_folders .}}
{{> default_streams_list_admin . }}
{{> auth_methods_settings_admin . }}
{{> linkifier_settings_admin . }}
{{> playground_settings_admin . }}
{{> profile_field_settings_admin . }}
{{> data_exports_admin . }}

View File

@@ -0,0 +1,32 @@
<div id="alert-word-settings" class="settings-section" data-name="alert-words">
<form id="alert_word_info_box">
<p class="alert-word-settings-note">
{{t "Alert words allow you to be notified as if you were @-mentioned when certain words or phrases are used in Zulip. Alert words are not case sensitive."}}
</p>
</form>
{{> ../components/action_button
label=(t "Add alert word")
variant="subtle"
intent="brand"
id="open-add-alert-word-modal"
}}
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Alert words"}}</h3>
</div>
<div class="banner-wrapper" id="alert_word_status"></div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th data-sort="alphabetic" data-sort-prop="word">{{t "Word" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="alert-words-table" class="alert-words-table"
data-empty="{{t 'There are no current alert words.' }}"></tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,18 @@
{{! Alert word in the settings page that can be removed }}
{{#with alert_word}}
<tr class="alert-word-item" data-word='{{word}}'>
<td>
<div class="alert_word_listing">
<span class="value">{{word}}</span>
</div>
</td>
<td>
{{> ../components/icon_button
icon="trash"
intent="danger"
custom_classes="delete remove-alert-word tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Delete")
}}
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,55 @@
<div class="micromodal" id="api_key_modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1">
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="api_key_modal_label">
<header class="modal__header">
<div class="modal__header-content">
<h1 class="modal__title" id="api_key_modal_label">
{{t "Your API key" }}
</h1>
</div>
{{> ../components/icon_button icon="close" intent="neutral" custom_classes="modal__close" aria-label=(t 'Close modal') data-micromodal-close=true }}
</header>
<main class="modal__content">
<div id="password_confirmation">
<span class="alert-notification" id="api_key_status"></span>
<div id="api_key_form">
<p>{{t "Please re-enter your password to confirm your identity." }}</p>
<div class="settings-password-div">
<label for="get_api_key_password" class="modal-field-label">{{t "Your password" }}</label>
<div class="password-input-row">
<input type="password" autocomplete="off" name="password" id="get_api_key_password" class=" modal_password_input" value="" />
<i class="zulip-icon zulip-icon-hide password_visibility_toggle tippy-zulip-tooltip" role="button" tabindex="0"></i>
</div>
</div>
<p class="small">
{{#tr}}If you don't know your password, you can <z-link>reset it</z-link>.
{{#*inline "z-link"}}<a href="/accounts/password/reset/" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
</div>
</div>
<div id="show_api_key">
<div class="api-key-container">
<b class="highlighted-element api-key-value-box"><span id="api_key_value"></span></b>
<span role="button" tabindex="0" class="copy-button tippy-zulip-tooltip" data-tippy-content="{{t 'Copy API key' }}" data-tippy-placement="right" aria-label="{{t 'Copy API key' }}">
<i class="zulip-icon zulip-icon-copy" aria-hidden="true"></i>
</span>
</div>
<div id="user_api_key_error" class="text-error"></div>
<p class="small">
{{t "Generating a new API key will immediately log you out of this account on all mobile devices." }}
</p>
</div>
</main>
<footer class="modal__footer">
<button type="submit" name="view_api_key" id="get_api_key_button" class="modal__button dialog_submit_button">
{{t 'Get API key' }}
</button>
<div id="api_key_buttons">
<button class="modal__button dialog_submit_button" id="regenerate_api_key" aria-label="{{t 'Generate new API key' }}">{{t "Generate new API key" }}</button>
<a class="modal__button dialog_submit_button" id="download_zuliprc" download="zuliprc" tabindex="0">{{t "Download zuliprc" }}</a>
</div>
</footer>
</div>
</div>
</div>

View File

@@ -0,0 +1,32 @@
<div id="attachments-settings" class="settings-section" data-name="uploaded-files">
<div id="attachment-stats-holder" class="banner-wrapper"></div>
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Your uploads"}}</h3>
{{> filter_text_input id="upload_file_search" placeholder=(t 'Filter') aria_label=(t 'Filter uploads')}}
</div>
<div class="clear-float"></div>
<div class="alert" id="delete-upload-status"></div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th data-sort="alphabetic" data-sort-prop="name" class="upload-file-name">{{t "File" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="active upload-date" data-sort="numeric" data-sort-prop="create_time">{{t "Date uploaded" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="upload-mentioned-in" data-sort="mentioned_in">{{t "Mentioned in" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="upload-size" data-sort="numeric" data-sort-prop="size">{{t "Size" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="upload-actions actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody data-empty="{{t 'You have not uploaded any files.' }}" data-search-results-empty="{{t 'No uploaded files match your current filter.' }}" id="uploaded_files_table"></tbody>
</table>
</div>
<div id="attachments_loading_indicator"></div>
</div>

View File

@@ -0,0 +1,26 @@
<div id="organization-auth-settings" class="settings-section" data-name="auth-methods">
{{#unless is_owner}}
<div class="banner-wrapper">
{{> ../components/banner
label=(t "Only organization owners can edit these settings.")
intent="info"
custom_classes="admin-permissions-banner"
}}
</div>
{{/unless}}
<form class="admin-realm-form org-authentications-form">
<div id="org-auth_settings" class="settings-subsection-parent">
<div class ="subsection-header">
<h3 class="settings-subsection-title">{{t "Authentication methods" }}</h3>
{{> settings_save_discard_widget section_name="auth_settings" show_save_discard_buttons=true }}
</div>
<div>
<p>{{t "Configure the authentication methods for your organization."}}</p>
<div id="id_realm_authentication_methods" class="prop-element" data-setting-widget-type="auth-methods">
{{! Empty div is intentional, it will get populated by a dedicated template }}
</div>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,28 @@
<div class="bot-api-key-container" data-api-key="{{api_key}}" data-user-id="{{bot_id}}">
<div class="input-group">
<label for="api-key" class="modal-field-label">{{t "API key"}}</label>
<div class="api-key-details-container">
<input type="text" autocomplete="off" name="api-key" class="modal_text_input api-key inline-block" value="{{ api_key }}" readonly/>
<div class="buttons-container">
<span data-user-id="{{bot_id}}">
{{> ../components/icon_button
icon="refresh-cw"
intent="brand"
custom_classes="bot-modal-regenerate-bot-api-key tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Generate new API key")
}}
</span>
<span>
{{> ../components/icon_button
icon="copy"
intent="success"
id="copy-api-key-button"
custom_classes="copy-api-key tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Copy API key")
}}
</span>
</div>
</div>
<div class="bot-modal-api-key-error text-error"></div>
</div>
</div>

View File

@@ -0,0 +1,36 @@
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{section_title}}</h3>
<div class="alert-notification"></div>
<div class="bot-filters">
{{> ../dropdown_widget widget_name=dropdown_widget_name}}
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter bots')}}
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table bot-list-table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="settings-email-column" data-sort="email">{{t "Email" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="user_role" data-sort="role">{{t "Role" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="bot_owner">{{t "Owner" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="alphabetic" data-sort-prop="bot_type" class="bot_type">{{t "Bot type" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="{{prefix}}_{{section_name}}_table" class="bot-table"
data-empty="{{#if (eq section_name 'all_bots')}}{{t 'There are no active bots in this organization.' }}{{else}}{{t 'You have no active bots'}}{{/if}}" data-search-results-empty="{{#if (eq section_name 'all_bots')}}{{t 'No bots match your current filter.' }}{{else}}{{t 'None of your bots match your current filter.' }}{{/if}}"></tbody>
</table>
</div>
<div id="{{prefix}}_page_{{section_name}}_loading_indicator" class="loading-indicator"></div>

View File

@@ -0,0 +1,44 @@
<div id="{{prefix}}-bot-list" class="settings-section" data-name="bots">
<div class="bot-settings-tip banner-wrapper" id="{{prefix}}-bot-settings-tip">
</div>
<div class="clear-float"></div>
<div>
{{> ../components/action_button
label=(t "Add a new bot")
variant="subtle"
intent="brand"
custom_classes="add-a-new-bot"
hidden=(not can_create_new_bots)
}}
</div>
<div class="tab-container"></div>
<div id="{{prefix}}-all-bots-list" class="bot-settings-section user-or-bot-settings-section" data-bot-settings-section="all-bots">
<div class="bot-list-error banner-wrapper"></div>
{{> bot_list
section_name="all_bots"
section_title=(t "All bots")
dropdown_widget_name=all_bots_list_dropdown_widget_name
prefix=prefix
}}
</div>
<div id="{{prefix}}-your-bots-list" class="bot-settings-section user-or-bot-settings-section" data-bot-settings-section="your-bots">
<div class="bot-list-error banner-wrapper"></div>
<div class="config-download-text">
<span>{{t 'Download config of all active outgoing webhook bots in Zulip Botserver format.' }}</span>
<a type="submit" download="botserverrc" class="hidden-botserverrc-download" hidden></a>
{{> ../components/icon_button
icon="download"
intent="brand"
custom_classes="download-botserverrc-file tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Download botserverrc")
}}
</div>
{{> bot_list
section_name="your_bots"
section_title=(t "Your bots")
dropdown_widget_name=your_bots_list_dropdown_widget_name
prefix=prefix
}}
</div>
</div>

View File

@@ -0,0 +1,15 @@
{{#unless can_create_any_bots}}
{{#if can_create_incoming_webhooks}}
{{> ../components/banner
label=(t "You can create bots that can only send messages.")
intent="info"
custom_classes="admin-permissions-banner"
}}
{{else}}
{{> ../components/banner
label=(t "You do not have permission to create bots.")
intent="info"
custom_classes="admin-permissions-banner"
}}
{{/if}}
{{/unless}}

View File

@@ -0,0 +1,9 @@
<p>{{t "User configurations for this setting will be reset to the organization default." }}</p>
<div class="input-group">
<label for="users_to_reset_configuration">{{t "Users whose configuration should be changed"}}</label>
<select name="users_to_reset_configuration" class="modal_select bootstrap-focus-style" id="users_to_reset_configuration" data-setting-widget-type="string">
<option value="everyone">{{t "Everyone"}}</option>
<option value="skip_edited">{{t "Users who have not personally configured this setting"}}</option>
</select>
</div>

View File

@@ -0,0 +1,15 @@
<div id="convert-demo-organization-form">
{{#unless user_has_email_set}}
<div class="demo-organization-add-email-banner banner-wrapper"></div>
{{/unless}}
<p>{{t "Everyone will need to log in again at the new URL for your organization." }}</p>
<form class="subdomain-setting modal-form">
<div class="input-group">
<label for="string_id" class="inline-block modal-field-label">{{t "Organization URL" }}</label>
<div id="subdomain_input_container">
<input id="new_subdomain" type="text" class="modal_text_input" autocomplete="off" name="string_id" placeholder="{{t 'acme' }}"/>
<label for="string_id" class="domain_label">.{{ realm_domain }}</label>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,34 @@
<div class="custom_user_field" name="{{ field.name }}" data-field-id="{{ field.id }}">
<span class="custom-user-field-label-wrapper {{#if field.required}}required-field-wrapper{{/if}}">
<label class="settings-field-label inline-block" for="id_custom_profile_field_input_{{ field.id }}">{{ field.name }}</label>
<span class="required-symbol {{#unless is_empty_required_field}}hidden{{/unless}}"> *</span>
</span>
<div class="alert-notification custom-field-status"></div>
<div class="settings-profile-user-field-hint">{{ field.hint }}</div>
<div class="settings-profile-user-field {{#if is_empty_required_field}}empty-required-field{{/if}} {{#unless editable_by_user}}not-editable-by-user-input-wrapper{{/unless}}{{#if (and is_date_field editable_by_user)}}editable-date-field{{/if}}">
{{#if is_long_text_field}}
<textarea id="id_custom_profile_field_input_{{ field.id }}" maxlength="500" class="custom_user_field_value {{#if for_manage_user_modal}}modal-textarea{{else}}settings-textarea{{/if}}" name="{{ field.id }}" {{#unless editable_by_user}}disabled{{/unless}}>{{ field_value.value }}</textarea>
{{else if is_dropdown_field}}
<select id="id_custom_profile_field_input_{{ field.id }}" class="custom_user_field_value {{#if for_manage_user_modal}}modal_select{{else}}settings_select{{/if}} bootstrap-focus-style" name="{{ field.id }}" {{#unless editable_by_user}}disabled{{/unless}}>
<option value=""></option>
{{#each field_choices}}
<option value="{{ this.value }}" {{#if this.selected}}selected{{/if}}>{{ this.text }}</option>
{{/each}}
</select>
{{else if is_user_field }}
<div class="pill-container person_picker {{#unless editable_by_user}}not-editable-by-user disabled{{/unless}}" name="{{ field.id }}">
<div class="input" {{#if editable_by_user}}contenteditable="true"{{/if}}></div>
</div>
{{else if is_date_field }}
<input class="custom_user_field_value datepicker {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" data-field-id="{{ field.id }}" type="text"
value="{{ field_value.value }}" {{#unless editable_by_user}}disabled{{/unless}}/>
{{#if editable_by_user}}<span class="remove_date"><i class="zulip-icon zulip-icon-close" aria-hidden="true"></i></span>{{/if}}
{{else if is_url_field }}
<input id="id_custom_profile_field_input_{{ field.id }}" class="custom_user_field_value {{#if for_manage_user_modal}}modal_url_input{{else}}settings_url_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="2048" {{#unless editable_by_user}}disabled{{/unless}}/>
{{else if is_pronouns_field}}
<input id="id_custom_profile_field_input_{{ field.id }}" class="custom_user_field_value pronouns_type_field {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="50" {{#unless editable_by_user}}disabled{{/unless}}/>
{{else}}
<input id="id_custom_profile_field_input_{{ field.id }}" class="custom_user_field_value {{#if for_manage_user_modal}}modal_text_input{{else}}settings_text_input{{/if}}" name="{{ field.id }}" type="{{ field_type }}" value="{{ field_value.value }}" maxlength="50" {{#unless editable_by_user}}disabled{{/unless}}/>
{{/if}}
</div>
</div>

View File

@@ -0,0 +1,86 @@
<div id="data-exports" class="settings-section" data-name="data-exports-admin">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Export organization" }}
{{> ../help_link_widget link="/help/export-your-organization" }}
</h3>
</div>
<p>
{{t 'Your organization’s data will be exported in a format designed for imports into Zulip Cloud or a self-hosted installation of Zulip.' }}
{{t 'You will be able to export all public data, and (optionally) private data from users who have given their permission.' }}
{{#tr}}
<z-link>Learn more</z-link> about other data export options.
{{#*inline "z-link"}}<a href="/help/export-your-organization" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<p>
{{t 'Depending on the size of your organization, an export can take anywhere from seconds to an hour.' }}
</p>
{{#if is_admin}}
<div class="alert" id="export_status" role="alert">
<span class="export_status_text"></span>
</div>
<form>
{{> ../components/action_button
label=(t "Start export")
id="start-export-button"
variant="subtle"
intent="brand"
type="submit"
}}
</form>
{{/if}}
<hr/>
<div class="tab-container"></div>
<div class="export_section" data-export-section="data-exports">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Data exports"}}</h3>
<input type="hidden" class="search" placeholder="{{t 'Filter exports' }}"
aria-label="{{t 'Filter exports' }}"/>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_exports_table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="user">{{t "Requesting user" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th>{{t "Type"}}</th>
<th data-sort="numeric" data-sort-prop="export_time">{{t "Time" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th>{{t "Status" }}</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="admin_exports_table" data-empty="{{t 'There are no exports.' }}"></tbody>
</table>
</div>
</div>
<div class="export_section" data-export-section="export-permissions">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Export permissions"}}</h3>
<div class="user_filters">
{{> ../dropdown_widget widget_name="filter_by_consent"}}
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter users')}}
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="full_name">{{t "Name" }}</th>
<th>{{t "Export permission"}}</th>
</tr>
</thead>
<tbody id="admin_export_consents_table"></tbody>
</table>
</div>
</div>
</div>

View File

@@ -0,0 +1,42 @@
<div id="admin-deactivated-users-list" class="user-settings-section user-or-bot-settings-section" data-user-settings-section="deactivated">
<div class="clear-float"></div>
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Deactivated users" }}
{{> ../help_link_widget link="/help/deactivate-or-reactivate-a-user" }}
</h3>
<div class="alert-notification" id="deactivated-user-field-status"></div>
<div class="user_filters">
{{> ../dropdown_widget widget_name=deactivated_user_list_dropdown_widget_name}}
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter deactivated users')}}
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="settings-email-column" {{#if allow_sorting_deactivated_users_list_by_email}}data-sort="email"{{/if}}>{{t "Email" }}
{{#if allow_sorting_deactivated_users_list_by_email}}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
{{/if}}
</th>
<th class="user_role" data-sort="role">{{t "Role" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
{{#if is_admin}}
<th class="actions">{{t "Actions" }}</th>
{{/if}}
</tr>
</thead>
<tbody id="admin_deactivated_users_table" class="admin_user_table"
data-empty="{{t 'There are no deactivated users.' }}"
data-search-results-empty="{{t 'No deactivated users match your filters.' }}">
</tbody>
</table>
</div>
<div id="admin_page_deactivated_users_loading_indicator"></div>
</div>

View File

@@ -0,0 +1,4 @@
<div class="choice-row" data-value="{{value}}">
{{> ../dropdown_widget widget_name=stream_dropdown_widget_name default_text=(t 'Select channel')}}
{{> ../components/icon_button intent="danger" custom_classes="delete-choice tippy-zulip-delayed-tooltip" icon="trash" data-tippy-content=(t "Delete") aria-label=(t "Delete") }}
</div>

View File

@@ -0,0 +1,35 @@
<div id="admin-default-channels-list" class="settings-section" data-name="default-channels-list">
<p>{{t "Configure the default channels new users are subscribed to when joining your organization." }}</p>
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Default channels"}}</h3>
<div class="add_default_streams_button_container">
{{> ../components/action_button
id="show-add-default-streams-modal"
label=(t "Add channel")
variant="subtle"
intent="brand"
type="submit"
hidden=(not is_admin)
}}
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter default channels')}}
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="actions{{#unless is_admin}} hide{{/unless}}"></th>
</tr>
</thead>
<tbody data-empty="{{t 'There are no default channels.' }}" data-search-results-empty="{{t 'No default channels match your current filter.' }}"
id="admin_default_streams_table" class="admin_default_stream_table"></tbody>
</table>
</div>
<div id="admin_page_default_streams_loading_indicator"></div>
</div>

View File

@@ -0,0 +1,3 @@
{{#if is_demo_organization }}
<div class="demo-organization-warning banner-wrapper"></div>
{{/if}}

View File

@@ -0,0 +1 @@
In the development environment, outgoing emails are logged to <a href="/emails" class="banner-link">/emails</a>.

View File

@@ -0,0 +1,3 @@
{{#each option_values}}
<option value='{{this.code}}'>{{this.description}}</option>
{{/each}}

View File

@@ -0,0 +1,131 @@
<div id="bot-edit-form" data-user-id="{{user_id}}" data-email="{{email}}">
<form class="edit_bot_form name-setting modal-form">
<div id="bot-edit-form-error" class="banner-wrapper"></div>
<div class="input-group name_change_container">
<label for="edit_bot_full_name" class="modal-field-label">{{t "Name" }}</label>
<input type="text" autocomplete="off" name="full_name" id="edit_bot_full_name" class="modal_text_input" value="{{ full_name }}" maxlength="{{max_bot_name_length}}" />
</div>
<input type="hidden" name="is_full_name" value="true" />
<div class="input-group email_change_container">
<label for="edit_bot_short_name" class="modal-field-label">
{{t "Bot email (a-z, 0-9, and dashes only)" }}
{{> ../help_link_widget link="/help/bots-overview" }}
</label>
<input type="text" autocomplete="off" name="bot_short_name" id="edit_bot_short_name"
class="modal_text_input"
value="{{ short_name }}" placeholder="{{t 'cookie' }}" maxlength="100" />
-bot@{{ realm_bot_domain }}
<div class="settings-field-hint">
{{t "Integrations will need to be updated to use the new email address." }}
</div>
</div>
<div class="input-group user_id_container">
<label for="user_id" class="modal-field-label">{{t "User ID" }}</label>
<input type="text" autocomplete="off" name="user_id" class="modal_text_input" value="{{ user_id }}" readonly/>
</div>
<div class="input-group">
<label for="bot-role-select" class="modal-field-label">{{t 'Role' }}
{{> ../help_link_widget link="/help/user-roles" }}
</label>
<select name="bot-role-select" id="bot-role-select" class="modal_select bootstrap-focus-style" data-setting-widget-type="number" {{#if disable_role_dropdown}}disabled{{/if}}>
{{> dropdown_options_widget option_values=(object_values user_role_values)}}
</select>
</div>
<div class="input-group">
<label for="bot-type" class="modal-field-label">{{t "Bot type"}}</label>
<input type="text" autocomplete="off" name="bot-type" class="modal_text_input" value="{{ bot_type }}" readonly/>
</div>
{{> ../dropdown_widget_with_label
widget_name="edit_bot_owner"
label=(t 'Owner')}}
<div id="service_data">
</div>
<div class="input-group edit-avatar-section">
<label class="modal-field-label">{{t "Avatar" }}</label>
{{!-- Shows the current avatar --}}
<img src="{{bot_avatar_url}}" id="current_bot_avatar_image" />
<input type="file" name="bot_avatar_file_input" class="notvisible edit_bot_avatar_file_input" value="{{t 'Upload profile picture' }}" />
<div class="edit_bot_avatar_file"></div>
<div class="edit_bot_avatar_preview_text">
<img class="edit_bot_avatar_preview_image" />
</div>
{{> ../components/action_button
label=(t "Change avatar")
variant="subtle"
intent="neutral"
custom_classes="edit_bot_avatar_upload_button"
}}
{{> ../components/action_button
label=(t "Clear profile picture")
variant="subtle"
intent="danger"
custom_classes="edit_bot_avatar_clear_button"
hidden=true
}}
<div><label for="edit_bot_avatar_file" generated="true" class="edit_bot_avatar_error text-error"></label></div>
</div>
</form>
{{#if is_incoming_webhook_bot}}
<div class="input-group">
{{> ../components/action_button
label=(t "Generate URL for an integration")
variant="subtle"
intent="neutral"
custom_classes="generate_url_for_integration"
}}
</div>
{{/if}}
{{#if (and is_active is_bot_owner_current_user)}}
<div id="zuliprc-section" class="input-group">
<div class="zuliprc-container">
<label class="modal-field-label">{{t "Zuliprc configuration" }} {{> ../help_link_widget link="/api/api-keys" }}</label>
<div class="buttons-container">
<span>
<a type="submit" download="zuliprc" data-email="{{email}}" data-user-id="{{user_id}}" class="hidden-zuliprc-download" hidden></a>
{{> ../components/icon_button
custom_classes="download-bot-zuliprc tippy-zulip-delayed-tooltip"
icon="download"
intent="brand"
data-tippy-content=(t 'Download zuliprc')
}}
</span>
{{> ../components/icon_button
icon="copy"
intent="success"
id="copy-zuliprc-config"
custom_classes="copy-zuliprc tippy-zulip-delayed-tooltip"
data-tippy-content=(t "Copy zuliprc")
}}
</div>
</div>
</div>
<div class="input-group">
{{> ../components/action_button
label=(t "API key")
variant="subtle"
intent="neutral"
custom_classes="show-api-key"
}}
</div>
{{/if}}
<div class="input-group">
{{#if is_active}}
{{> ../components/action_button
label=(t "Deactivate bot")
variant="subtle"
intent="danger"
custom_classes="deactivate-bot-button"
}}
{{else}}
<span>
{{> ../components/action_button
label=(t "Reactivate bot")
variant="subtle"
intent="success"
custom_classes="reactivate-user-button"
}}
</span>
{{/if}}
</div>
</div>

View File

@@ -0,0 +1,76 @@
{{#with profile_field_info}}
<form class="name-setting profile-field-form modal-form" id="edit-custom-profile-field-form-{{id}}" data-profile-field-id="{{id}}">
<div class="input-group">
<label for="id-custom-profile-field-name" class="modal-field-label">{{t "Label" }}</label>
<input type="text" name="name" id="id-custom-profile-field-name" class="modal_text_input prop-element" value="{{ name }}" maxlength="40" data-setting-widget-type="string" />
</div>
<div class="input-group hint_change_container">
<label for="id-custom-profile-field-hint" class="modal-field-label">{{t "Hint" }}</label>
<input type="text" name="hint" id="id-custom-profile-field-hint" class="modal_text_input prop-element" value="{{ hint }}" maxlength="80" data-setting-widget-type="string" />
</div>
{{#if is_dropdown_field }}
<div class="input-group prop-element profile-field-choices-wrapper" id="id-custom-profile-field-field-data" data-setting-widget-type="field-data-setting">
<label for="profile_field_choices_edit" class="modal-field-label">{{t "Field choices" }}</label>
<div class="profile-field-choices" name="profile_field_choices_edit">
<div class="edit_profile_field_choices_container">
{{#each choices}}
{{> profile_field_choice . }}
{{/each}}
</div>
</div>
{{> ../components/action_button
label=(t "Alphabetize choices")
custom_classes="alphabetize-choices-button"
intent="neutral"
variant="subtle"
}}
</div>
{{else if is_external_account_field}}
<div class="prop-element" id="id-custom-profile-field-field-data" data-setting-widget-type="field-data-setting">
<div class="input-group profile_field_external_accounts_edit" >
<label for="external_acc_field_type" class="modal-field-label">{{t "External account type" }}</label>
<select name="external_acc_field_type" class="modal_select" disabled>
{{#each (object_entries ../realm_default_external_accounts) as |entry|}}
<option value='{{entry.[0]}}'>{{entry.[1].text}}</option>
{{/each}}
<option value="custom">{{t 'Custom' }}</option>
</select>
</div>
<div class="input-group custom_external_account_detail">
<label for="url_pattern" class="modal-field-label">{{t "URL pattern" }}</label>
<input type="url" class="modal_url_input" name="url_pattern" autocomplete="off" maxlength="80" />
</div>
</div>
{{/if}}
{{#if valid_to_display_in_summary}}
<div class="input-group">
<label class="checkbox edit_profile_field_display_label" for="id-custom-profile-field-display-in-profile-summary">
<input class="edit_display_in_profile_summary prop-element" data-setting-widget-type="boolean" type="checkbox" id="id-custom-profile-field-display-in-profile-summary" name="display_in_profile_summary" data-setting-widget-type="boolean" {{#if display_in_profile_summary}} checked="checked" {{/if}}/>
<span class="rendered-checkbox"></span>
{{t 'Display on user card' }}
</label>
</div>
{{/if}}
<div class="input-group">
<label class="checkbox" for="id-custom-profile-field-required">
<input class="edit-required prop-element" type="checkbox" id="id-custom-profile-field-required" name="required" data-setting-widget-type="boolean" {{#if required}} checked="checked" {{/if}}/>
<span class="rendered-checkbox"></span>
{{t 'Required field' }}
</label>
</div>
{{> settings_checkbox
prefix="id-custom-profile-field-"
setting_name="editable-by-user"
is_checked= editable_by_user
label=(t "Users can edit this field for their own account")
}}
{{#if valid_to_use_for_user_matching}}
{{> settings_checkbox
prefix="id-custom-profile-field-"
setting_name="use_for_user_matching"
is_checked= use_for_user_matching
label=(t "Use in @-mention suggestions")
}}
{{/if}}
</form>
{{/with}}

View File

@@ -0,0 +1,13 @@
{{#if service}}
{{#if service.config_data}}
<div id="config_edit_inputbox">
{{#each (object_entries service.config_data) as |entry|}}
<div class="input-group">
<label for="embedded_bot_{{entry.[0]}}_edit" class="modal-field-label">{{entry.[0]}}</label>
<input type="text" name="{{entry.[0]}}" id="embedded_bot_{{entry.[0]}}_edit" class="modal_text_input"
maxlength=1000 value="{{entry.[1]}}" />
</div>
{{/each}}
</div>
{{/if}}
{{/if}}

View File

@@ -0,0 +1,12 @@
<div class="input-group">
<label for="edit_service_base_url">{{t "Endpoint URL" }}</label>
<input id="edit_service_base_url" type="text" name="service_payload_url" class="edit_service_base_url required modal_text_input"value="{{service.base_url}}" maxlength=2083 />
<div><label for="edit_service_base_url" generated="true" class="text-error"></label></div>
</div>
<div class="input-group">
<label for="edit_service_interface">{{t "Webhook format" }}</label>
<select id="edit_service_interface" class="modal_select bootstrap-focus-style" name="service_interface">
<option value="1">Zulip</option>
<option value="2">{{t "Slack-compatible" }}</option>
</select>
</div>

View File

@@ -0,0 +1,37 @@
<div id="emoji-settings" data-name="emoji-settings" class="settings-section">
<div class="emoji-settings-tip-container {{#if can_add_emojis}}hide{{/if}}">
<div class="tip">{{t "You do not have permission to add custom emoji."}}</div>
</div>
<p class="add-emoji-text {{#unless can_add_emojis}}hide{{/unless}}">
{{t "Add extra emoji for members of the {realm_name} organization." }}
</p>
{{> ../components/action_button
id="add-custom-emoji-button"
variant="subtle"
intent="brand"
label=(t "Add a new emoji")
hidden=(not can_add_emojis)
}}
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Custom emoji"}}</h3>
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter emoji')}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_emoji_table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="image">{{t "Image" }}</th>
<th class="image" data-sort="author_full_name">{{t "Author" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="admin_emoji_table" data-empty="{{t 'There are no custom emoji.' }}" data-search-results-empty="{{t 'No custom emojis match your current filter.' }}"></tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="search-container">
<input type="text" {{#if id}}id="{{id}}"{{/if}} class="search filter_text_input" placeholder="{{placeholder}}" aria-label="{{aria_label}}"/>
<button type="button" class="clear-filter">
<i class="zulip-icon zulip-icon-close"></i>
</button>
</div>

View File

@@ -0,0 +1,7 @@
<div class="input-group" id="integration-url-{{key}}-container">
<label class="checkbox">
<input type="checkbox" id="integration-url-{{key}}-checkbox" class="integration-url-parameter" />
<span class="rendered-checkbox"></span>
</label>
<label class="inline" for="integration-url-{{key}}-checkbox">{{label}}</label>
</div>

View File

@@ -0,0 +1,4 @@
<div class="input-group" id="integration-url-{{key}}-container">
<label for="integration-url-{{key}}-text" class="modal-label-field">{{label}}</label>
<input type="text" id="integration-url-{{key}}-text" class="modal_text_input integration-url-parameter" value=""/>
</div>

View File

@@ -0,0 +1,17 @@
<div class="input-group" id="integration-url-branches-parameter">
<label class="checkbox">
<input type="checkbox" id="integration-url-all-branches" class="integration-url-parameter" checked/>
<span class="rendered-checkbox"></span>
</label>
<label class="inline" for="integration-url-all-branches">
{{t "Send notifications for all branches"}}
</label>
</div>
<div class="input-group hide" id="integration-url-filter-branches">
<label for="integration-url-branches-text" class="modal-label-field">
{{t "Which branches should notifications be sent for?"}}
</label>
<div class="pill-container">
<div id="integration-url-branches-text" class="input" contenteditable="true"></div>
</div>
</div>

View File

@@ -0,0 +1,62 @@
<div class="input-group">
<div class="integration-url-name-wrapper integration-url-parameter">
{{> ../dropdown_widget_with_label
widget_name="integration-name"
label=(t "Integration")}}
</div>
</div>
<div class="input-group">
<div class="integration-url-stream-wrapper integration-url-parameter">
{{> ../dropdown_widget_with_label
widget_name="integration-url-stream"
label=(t "Where to send notifications")}}
</div>
</div>
<div class="input-group control-label-disabled">
<label class="checkbox">
<input type="checkbox" id="integration-url-override-topic" class="integration-url-parameter" disabled/>
<span class="rendered-checkbox"></span>
</label>
<label class="inline" for="integration-url-override-topic">
{{t "Send all notifications to a single topic"}}
</label>
</div>
<div class="input-group">
<div class="topic-to-use-wrapper integration-url-parameter">
{{> ../dropdown_widget_with_label
widget_name="slack-topics-dropdown"
label=(t "Topics to use")}}
</div>
</div>
<div class="input-group hide integration-url-topic">
<label for="integration-url-topic-input" class="modal-label-field">{{t "Topic"}}</label>
<input type="text" id="integration-url-topic-input" class="modal_text_input integration-url-parameter" maxlength="{{ max_topic_length }}" />
<span id="integration-url-topic-placeholder" class="placeholder">
{{> ../topic_not_mandatory_placeholder_text empty_string_topic_display_name=empty_string_topic_display_name}}
</span>
</div>
<div id="integration-url-config-options-container">
<!-- Dynamic Config Options will be rendered here -->
</div>
<div id="integration-events-parameter" class="input-group hide">
<label class="checkbox">
<input type="checkbox" id="show-integration-events"/>
<span class="rendered-checkbox"></span>
</label>
<label class="inline" for="show-integration-events">
{{t "Filter events that will trigger notifications?"}}
</label>
</div>
<div class="input-group hide" id="integrations-event-container">
<label for="integrations-event-options">{{t "Events to include:"}}</label>
<div class="integration-all-events-buttons">
{{> ../components/action_button variant="subtle" intent="neutral" id="add-all-integration-events" label=(t "Check all") }}
{{> ../components/action_button variant="subtle" intent="neutral" id="remove-all-integration-events" label=(t "Uncheck all") }}
</div>
<div id="integrations-event-options"></div>
</div>
<hr />
<p class="integration-url-header">{{t "URL for your integration"}}</p>
<div class="integration-url">
{{default_url_message}}
</div>

View File

@@ -0,0 +1,17 @@
<div class="input-group {{setting_name}}_container">
{{!-- We are using snake case for one of the classes since setting_name
is always in snake case and it would be weird to have the resultant id
be a mix of two types of cases. --}}
<label class="group-setting-label {{setting_name}}_label">
{{label}}
{{#if label_parens_text}}(<i>{{label_parens_text}}</i>){{/if}}
{{#if help_link}}
{{> ../help_link_widget link=help_link }}
{{/if}}
</label>
<div class="pill-container person_picker prop-element" id="{{#if prefix}}{{prefix}}{{else}}id_{{/if}}{{setting_name}}" data-setting-widget-type="group-setting-type">
<div class="input" contenteditable="true" data-placeholder="{{t 'Add roles, groups or users' }}">
{{~! Squash whitespace so that placeholder is displayed when empty. ~}}
</div>
</div>
</div>

View File

@@ -0,0 +1,29 @@
<div id="{{widget}}-upload-widget" class="inline-block image_upload_widget">
{{#if disabled_text}}
<div class="image-disabled {{#if is_editable_by_current_user}}hide{{/if}}">
<div class="image-hover-background"></div>
<span class="image-disabled-text flex" aria-label="{{ disabled_text }}" role="button" tabindex="0">
{{ disabled_text }}
</span>
</div>
{{/if}}
<div class="image_upload_button {{#unless is_editable_by_current_user}}hide{{/unless}}">
<div class="image-hover-background"></div>
<button class="image-delete-button" aria-label="{{ delete_text }}" role="button" tabindex="0">
&times;
</button>
<span class="image-delete-text" aria-label="{{ delete_text }}" tabindex="0">
{{ delete_text }}
</span>
<span class="image-upload-text" aria-label="{{ upload_text }}" role="button" tabindex="0">
{{ upload_text }}
</span>
<span class="upload-spinner-background">
<img class="image_upload_spinner" src="../../images/loading/tail-spin.svg" alt="" />
</span>
</div>
<img class="image-block" src="{{ image }}"/>
<input type="file" name="file_input" class="notvisible image_file_input" value="{{ upload_text }}" />
</div>
<div id="{{widget}}-upload-widget-error" class="image_file_input_error text-error"></div>

View File

@@ -0,0 +1,35 @@
<div id="admin-imported-users-list" class="user-settings-section user-or-bot-settings-section" data-user-settings-section="imported">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Imported users"}}</h3>
<div class="alert-notification" id="user-field-status"></div>
<div class="user_filters">
{{> ../dropdown_widget widget_name=imported_user_list_dropdown_widget_name}}
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter users')}}
</div>
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="full_name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="settings-email-column" data-sort="email">{{t "Email" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="user_role" data-sort="role">{{t "Role" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
{{#if is_admin}}
<th class="actions">{{t "Actions" }}</th>
{{/if}}
</tr>
</thead>
<tbody id="admin_imported_users_table"
data-empty="{{t 'No users match your filters.' }}"></tbody>
</table>
</div>
<div id="admin_page_imported_users_loading_indicator"></div>
</div>

View File

@@ -0,0 +1,30 @@
<div class="button-group" data-property="{{property}}">
{{#if for_settings_ui}}
<div class="info-density-button-container">
<button class="info-density-button default-button" aria-label="{{#if (eq property "web_font_size_px")}}{{t 'Set font size to default'}}{{else}}{{t 'Set line spacing to default' }}{{/if}}">
<i class="zulip-icon {{default_icon_class}}" aria-hidden="true"></i>
</button>
</div>
{{/if}}
{{#if for_settings_ui}}
<span class="display-value">{{display_value}}</span>
{{/if}}
<input class="current-value prop-element" id="{{prefix}}{{property}}" data-setting-widget-type="info-density-setting" type="hidden" value="{{property_value}}" />
<div class="info-density-button-container">
<button class="info-density-button decrease-button" aria-label="{{#if (eq property "web_font_size_px")}}{{t 'Decrease font size'}}{{else}}{{t 'Decrease line spacing' }}{{/if}}">
<i class="zulip-icon zulip-icon-minus" aria-hidden="true"></i>
</button>
</div>
{{#unless for_settings_ui}}
<div class="info-density-button-container">
<button class="info-density-button default-button" aria-label="{{#if (eq property "web_font_size_px")}}{{t 'Set font size to default'}}{{else}}{{t 'Set line spacing to default' }}{{/if}}">
<i class="zulip-icon {{default_icon_class}}" aria-hidden="true"></i>
</button>
</div>
{{/unless}}
<div class="info-density-button-container">
<button class="info-density-button increase-button" aria-label="{{#if (eq property "web_font_size_px")}}{{t 'Increase font size'}}{{else}}{{t 'Increase line spacing' }}{{/if}}">
<i class="zulip-icon zulip-icon-plus" aria-hidden="true"></i>
</button>
</div>
</div>

View File

@@ -0,0 +1,12 @@
{{#each events }}
<div class="integration-event-wrapper">
<label class="checkbox">
<input type="checkbox" class="integration-event" id="{{this.event_id}}" checked=true
value="{{this.event}}" />
<span class="rendered-checkbox"></span>
</label>
<label for="{{this.event_id}}" class="inline integration-event-name">
{{this.event}}
</label>
</div>
{{/each}}

View File

@@ -0,0 +1,58 @@
<div id="admin-invites-list" class="user-settings-section" data-user-settings-section="invitations">
<div class="invite-user-settings-banner banner-wrapper">
{{> ../components/banner
label=(t "You do not have permission to send invite emails in this organization.")
intent="info"
custom_classes="admin-permissions-banner"
}}
</div>
{{#unless is_admin }}
<div class="banner-wrapper">
{{> ../components/banner
label=(t "You can only view or manage invitations that you sent.")
intent="info"
custom_classes="admin-permissions-banner"
}}
</div>
{{/unless}}
{{> ../components/action_button
label=(t 'Invite users to organization')
variant="subtle"
intent="brand"
custom_classes="user-settings-invite-user-label invite-user-link"
}}
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Invitations "}}</h3>
<div class="alert-notification" id="invites-field-status"></div>
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter invitations')}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="invitee">{{t "Invitee" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
{{#if is_admin }}
<th data-sort="alphabetic" data-sort-prop="referrer_name">{{t "Invited by" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
{{/if}}
<th data-sort="numeric" data-sort-prop="invited">{{t "Invited at" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="numeric" data-sort-prop="expiry_date">{{t "Expires at" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="numeric" data-sort-prop="invited_as">{{t "Invited as" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="admin_invites_table" class="admin_invites_table" data-empty="{{t 'There are no invitations.' }}" data-search-results-empty="{{t 'No invitations match your current filter.' }}"></tbody>
</table>
</div>
<div id="admin_page_invites_loading_indicator"></div>
</div>

View File

@@ -0,0 +1,4 @@
<div class="alternative-url-template-row">
<input type="text" class="modal_text_input" {{#if show_placeholder}}placeholder="https://github.com/zulip/zulip/pull/{id}" {{/if}}value="{{value}}" />
{{> ../components/icon_button intent="danger" custom_classes="delete-alternative-url-template tippy-zulip-tooltip" icon="trash" data-tippy-content=(t "Delete") aria-label=(t "Delete") }}
</div>

View File

@@ -0,0 +1,25 @@
<div class="input-group name_change_container">
<label for="linkifier-example-input" class="modal-field-label">{{t "Example text to linkify" }}</label>
<input type="text" autocomplete="off" id="linkifier-example-input" class="modal_text_input" name="example_input" placeholder="#2468" value="{{example_input}}" />
<div class="alert" id="linkifier-example-status"></div>
</div>
<div class="input-group name_change_container">
<label for="linkifier-pattern" class="modal-field-label">{{t "Pattern" }}</label>
<input type="text" autocomplete="off" id="linkifier-pattern" class="modal_text_input" name="pattern" placeholder="#(?P<id>[0-9]+)" value="{{pattern}}" />
<div class="alert" id="linkifier-pattern-status"></div>
</div>
<div class="input-group name_change_container">
<label for="linkifier-url-template" class="modal-field-label">{{t "URL template" }}</label>
<input type="text" autocomplete="off" id="linkifier-url-template" class="modal_text_input" name="url_template" placeholder="https://github.com/zulip/zulip/issues/{id}" value="{{url_template}}" />
<div class="alert" id="linkifier-template-status"></div>
</div>
<div class="input-group name_change_container">
<label for="linkifier-reverse-template" class="modal-field-label">{{t "Auto-convert pasted URLs matching the template to" }}</label>
<input type="text" autocomplete="off" id="linkifier-reverse-template" class="modal_text_input" name="reverse_template" placeholder="#{id}" value="{{reverse_template}}" />
<div class="alert" id="linkifier-reverse-status"></div>
</div>
<div class="input-group name_change_container">
<label class="modal-field-label">{{t "Alternative URL templates for auto-conversion" }}</label>
<div id="linkifier-alternative-url-templates"></div>
<div class="alert" id="linkifier-alternative-url-templates-status"></div>
</div>

View File

@@ -0,0 +1,51 @@
<div id="linkifier-settings" class="settings-section" data-name="linkifier-settings">
<p>
{{t "Configure regular expression patterns that will be used to
automatically transform any matching text in Zulip messages
and topics into links." }}
</p>
<p>
{{t "Linkifiers make it easy to refer to issues or tickets in
third party issue trackers, like GitHub, Salesforce, Zendesk,
and others." }}
</p>
<p>
{{#tr}}
For more examples, see the <z-link>help center documentation</z-link>
on adding linkifiers.
{{#*inline "z-link"}}<a href="/help/add-a-custom-linkifier" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
{{#if is_admin}}
{{> ../components/action_button
id="add-linkifier-button"
label=(t 'Add linkifier')
variant="subtle"
intent="brand"
}}
{{/if}}
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Linkifiers"}}</h3>
<div class="alert-notification edit-linkifier-status" id="linkifier-field-status"></div>
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter linkifiers')}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_linkifiers_table">
<thead class="table-sticky-headers">
<tr>
<th>{{t "Example" }}</th>
<th>{{t "Pattern" }}</th>
<th>{{t "URL template" }}</th>
<th class="convert-url-heading">{{t "Convert" }}<i class="zulip-icon zulip-icon-link" aria-hidden="true"></i></th>
{{#if is_admin}}
<th class="actions">{{t "Actions" }}</th>
{{/if}}
</tr>
</thead>
<tbody id="admin_linkifiers_table" data-empty="{{t 'No linkifiers configured.' }}" data-search-results-empty="{{t 'No linkifiers match your current filter.' }}"></tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,22 @@
<div id="muted-user-settings" class="settings-section" data-name="muted-users">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Muted users"}}</h3>
{{> filter_text_input id="muted_users_search" placeholder=(t 'Filter') aria_label=(t 'Filter muted users')}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th data-sort="alphabetic" data-sort-prop="user_name">{{t "User" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="numeric" data-sort-prop="date_muted">{{t "Date muted" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th class="actions">{{t "Actions" }}</th>
</tr>
</thead>
<tbody id="muted_users_table" data-empty="{{t 'You have not muted any users yet.'}}" data-search-results-empty="{{t 'No users match your current filter.' }}"></tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,304 @@
<form class="notification-settings-form">
<div class="general_notifications {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Notification triggers" }}</h3>
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
{{> settings_save_discard_widget section_name="general-notify-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<p>{{t "Configure how Zulip notifies you about new messages." }}</p>
<table class="notification-table table table-bordered wrapped-table">
<thead>
<tr>
<th rowspan="2" width="30%"></th>
<th colspan="2" width="28%">{{t "Desktop"}}</th>
<th rowspan="2" width="14%">
<span {{#if (not realm_push_notifications_enabled) }}class="control-label-disabled tippy-zulip-tooltip" data-tooltip-template-id="mobile-push-notification-tooltip-template"{{/if}}>
{{t "Mobile"}}
</span>
{{> ../help_link_widget link="/help/mobile-notifications#enabling-push-notifications-for-self-hosted-servers" }}
</th>
<th rowspan="2" width="14%">{{t "Email"}}</th>
<th rowspan="2" width="14%">@all
<i class="fa fa-question-circle settings-info-icon tippy-zulip-tooltip" data-tippy-content="{{t 'Whether wildcard mentions like @all are treated as mentions for the purpose of notifications.' }}"></i>
</th>
</tr>
<tr>
<th>{{t "Visual"}}</th>
<th>{{t "Audible"}}</th>
</tr>
</thead>
<tbody>
{{#each general_settings}}
<tr>
<td>
{{ this.label }}
{{#if this.help_link}}
{{> ../help_link_widget link=this.help_link }}
{{/if}}
</td>
{{#each this.notification_settings}}
{{> notification_settings_checkboxes
setting_name=this.setting_name
is_checked=this.is_checked
is_disabled=this.is_disabled
is_mobile_checkbox=this.is_mobile_checkbox
push_notifications_disabled=this.push_notifications_disabled
prefix=../../prefix }}
{{/each}}
</tr>
{{/each}}
</tbody>
{{#unless for_realm_settings}}
<tbody id="stream-specific-notify-table">
</tbody>
<tbody id="customizable_stream_notifications_table">
<tr>
<td>
{{> ../dropdown_widget widget_name="customize_stream_notifications" custom_classes="decorated-stream-name-dropdown-widget"}}
</td>
{{#each custom_stream_specific_notification_settings}}
{{> notification_settings_checkboxes
setting_name=this.setting_name
is_checked=this.is_checked
is_mobile_checkbox=this.is_mobile_checkbox
is_disabled=this.is_disabled
push_notifications_disabled=this.push_notifications_disabled
prefix="customize_stream_" }}
{{/each}}
</tr>
</tbody>
{{/unless}}
</table>
</div>
<div class="topic_notifications m-10 {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Topic notifications" }}
{{> ../help_link_widget link="/help/topic-notifications" }}
</h3>
{{> settings_save_discard_widget section_name="topic-notifications-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<p>
{{#tr}}
You will automatically follow topics that you have configured to both <z-follow>follow</z-follow> and <z-unmute>unmute</z-unmute>.
{{#*inline "z-follow"}}<a href="/help/follow-a-topic" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{#*inline "z-unmute"}}<a href="/help/mute-a-topic" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<div class="input-group">
<label for="{{prefix}}automatically_follow_topics_policy" class="settings-field-label">
{{ settings_label.automatically_follow_topics_policy }}
{{> ../help_link_widget link="/help/follow-a-topic" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="automatically_follow_topics_policy" class="setting_automatically_follow_topics_policy prop-element settings_select bootstrap-focus-style"
id="{{prefix}}automatically_follow_topics_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values automatically_follow_topics_policy_values)}}
</select>
</div>
{{> settings_checkbox
setting_name="automatically_follow_topics_where_mentioned"
is_checked=(lookup settings_object "automatically_follow_topics_where_mentioned")
label=(lookup settings_label "automatically_follow_topics_where_mentioned")
prefix=prefix
show_reset_button=for_realm_settings}}
<div class="input-group">
<label for="{{prefix}}automatically_unmute_topics_in_muted_streams_policy" class="settings-field-label">
{{ settings_label.automatically_unmute_topics_in_muted_streams_policy }}
{{> ../help_link_widget link="/help/mute-a-topic" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="automatically_unmute_topics_in_muted_streams_policy" class="setting_automatically_unmute_topics_in_muted_streams_policy prop-element settings_select bootstrap-focus-style"
id="{{prefix}}automatically_unmute_topics_in_muted_streams_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values automatically_unmute_topics_in_muted_streams_policy_values)}}
</select>
</div>
<div class="input-group">
<label for="{{prefix}}resolved_topic_notice_auto_read_policy" class="settings-field-label">
{{t "Automatically mark resolved topic notices as read" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="resolved_topic_notice_auto_read_policy" class="setting_resolved_topic_notice_auto_read_policy prop-element settings_select bootstrap-focus-style" id="{{prefix}}resolved_topic_notice_auto_read_policy" data-setting-widget-type="string">
{{> dropdown_options_widget option_values=(object_values resolved_topic_notice_auto_read_policy_values)}}
</select>
</div>
</div>
<div class="desktop_notifications m-10 {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Desktop message notifications" }}
{{> ../help_link_widget link="/help/desktop-notifications" }}
</h3>
{{> settings_save_discard_widget section_name="desktop-message-settings" show_save_discard_buttons=for_realm_settings }}
</div>
{{#if (eq prefix "user_")}}
<div class="desktop-notification-settings-banners banner-wrapper"></div>
{{/if}}
{{#unless for_realm_settings}}
{{> ../components/action_button
label=(t "Send a test notification")
variant="subtle"
intent="neutral"
custom_classes="send_test_notification"
}}
{{/unless}}
{{#each notification_settings.desktop_notification_settings}}
{{> settings_checkbox
setting_name=this
is_checked=(lookup ../settings_object this)
label=(lookup ../settings_label this)
prefix=../prefix
show_reset_button=../for_realm_settings}}
{{/each}}
<div class="input-group">
<label for="{{prefix}}notification_sound" class="settings-field-label">
{{t "Notification sound" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<div class="input-element-with-control {{#unless enable_sound_select}}control-label-disabled{{/unless}}">
<select name="notification_sound" class="setting_notification_sound prop-element settings_select bootstrap-focus-style" id="{{prefix}}notification_sound" data-setting-widget-type="string"
{{#unless enable_sound_select}}
disabled
{{/unless}}>
<option value="none">{{t "None" }}</option>
{{#each settings_object.available_notification_sounds}}
<option value="{{ this }}">{{ this }}</option>
{{/each}}
</select>
<span class="play_notification_sound">
<i class="notification-sound-icon fa fa-play-circle" aria-label="{{t 'Play sound' }}"></i>
</span>
</div>
</div>
<div class="input-group">
<label for="{{prefix}}desktop_icon_count_display" class="settings-field-label">
{{ settings_label.desktop_icon_count_display }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="desktop_icon_count_display" class="setting_desktop_icon_count_display prop-element settings_select bootstrap-focus-style" id="{{prefix}}desktop_icon_count_display" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values desktop_icon_count_display_values)}}
</select>
</div>
</div>
<div class="mobile_notifications m-10 {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Mobile message notifications" }}
{{> ../help_link_widget link="/help/mobile-notifications" }}
</h3>
{{> settings_save_discard_widget section_name="mobile-message-settings" show_save_discard_buttons=for_realm_settings }}
</div>
{{#unless realm_push_notifications_enabled}}
<div class="mobile-push-notifications-banner-container banner-wrapper">
</div>
{{/unless}}
{{#each notification_settings.mobile_notification_settings}}
{{> settings_checkbox
setting_name=this
is_checked=(lookup ../settings_object this)
is_disabled=(lookup ../disabled_notification_settings this)
label=(lookup ../settings_label this)
prefix=../prefix
show_reset_button=../for_realm_settings}}
{{/each}}
</div>
<div class="email_message_notifications m-10 {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Email message notifications" }}
{{> ../help_link_widget link="/help/email-notifications" }}
</h3>
{{> settings_save_discard_widget section_name="email-message-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<div class="input-group time-limit-setting">
<label for="{{prefix}}email_notifications_batching_period_seconds" class="settings-field-label">
{{t "Delay before sending message notification emails" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="email_notifications_batching_period_seconds" class="setting_email_notifications_batching_period_seconds prop-element settings_select bootstrap-focus-style" id="{{prefix}}email_notifications_batching_period_seconds" data-setting-widget-type="time-limit">
{{#each email_notifications_batching_period_values}}
<option value="{{ this.value }}">{{ this.description }}</option>
{{/each}}
</select>
<div class="dependent-settings-block">
<label for="{{prefix}}email_notification_batching_period_edit_minutes" class="inline-block">
{{t 'Delay period (minutes)' }}:
</label>
<input type="text"
name="email_notification_batching_period_edit_minutes"
class="email_notification_batching_period_edit_minutes time-limit-custom-input"
data-setting-widget-type="time-limit"
autocomplete="off"
id="{{prefix}}email_notification_batching_period_edit_minutes"/>
</div>
</div>
<div class="input-group">
<label for="{{prefix}}realm_name_in_email_notifications_policy" class="settings-field-label">
{{ settings_label.realm_name_in_email_notifications_policy }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="realm_name_in_email_notifications_policy" class="setting_realm_name_in_email_notifications_policy prop-element settings_select bootstrap-focus-style" id="{{prefix}}realm_name_in_email_notifications_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values realm_name_in_email_notifications_policy_values)}}
</select>
</div>
{{#each notification_settings.email_message_notification_settings}}
{{> settings_checkbox
setting_name=this
is_checked=(lookup ../settings_object this)
label=(lookup ../settings_label this)
is_disabled=(lookup ../disabled_notification_settings this)
prefix=../prefix
show_reset_button=../for_realm_settings}}
{{/each}}
</div>
<div class="other_email_notifications m-10 {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Other emails" }}</h3>
{{> settings_save_discard_widget section_name="other-emails-settings" show_save_discard_buttons=for_realm_settings }}
</div>
{{#each notification_settings.other_email_settings}}
{{> settings_checkbox
setting_name=this
is_checked=(lookup ../settings_object this)
label=(lookup ../settings_label this)
prefix=../prefix
show_reset_button=../for_realm_settings}}
{{/each}}
</div>
</form>

View File

@@ -0,0 +1,11 @@
<td>
<span {{#if (and is_mobile_checkbox push_notifications_disabled)}} class="tippy-zulip-tooltip" data-tooltip-template-id="mobile-push-notification-tooltip-template"{{/if}}>
<label class="checkbox">
<input type="checkbox" name="{{setting_name}}" id="{{prefix}}{{setting_name}}"
{{#if is_disabled}} disabled {{/if}}
{{#if is_checked}}checked="checked"{{/if}} data-setting-widget-type="boolean"
class="{{setting_name}}{{#unless is_disabled}} prop-element{{/unless}}"/>
<span class="rendered-checkbox"></span>
</label>
</span>
</td>

View File

@@ -0,0 +1,384 @@
<div id="organization-permissions" data-name="organization-permissions" class="settings-section">
<form class="admin-realm-form org-permissions-form">
<div id="org-join-settings" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">
{{t "Joining the organization" }}
<i class="fa fa-info-circle settings-info-icon tippy-zulip-tooltip" aria-hidden="true" data-tippy-content="{{t 'Only owners can change these settings.' }}"></i>
</h3>
{{> settings_save_discard_widget section_name="join-settings" show_save_discard_buttons=true }}
</div>
<div id="realm_invite_required_container" {{#unless user_has_email_set}}class="disabled_setting_tooltip"{{/unless}}>
{{> settings_checkbox
setting_name="realm_invite_required"
prefix="id_"
is_checked=realm_invite_required
is_disabled=(not user_has_email_set)
label=admin_settings_label.realm_invite_required}}
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_invite_users_group"
label=group_setting_labels.can_invite_users_group}}
{{> group_setting_value_pill_input
setting_name="realm_create_multiuse_invite_group"
label=group_setting_labels.create_multiuse_invite_group}}
<div class="input-group">
<label for="id_realm_org_join_restrictions" class="settings-field-label">{{t "Restrict email domains of new users" }}</label>
<select name="realm_org_join_restrictions" id="id_realm_org_join_restrictions" class="prop-element settings_select bootstrap-focus-style" data-setting-widget-type="string">
<option value="no_restriction">{{t "No restrictions" }}</option>
<option value="no_disposable_email">{{t "Don’t allow disposable email addresses" }}</option>
<option value="only_selected_domain">{{t "Restrict to a list of domains" }}</option>
</select>
<div class="dependent-settings-block">
<p id="allowed_domains_label" class="inline-block"></p>
{{#if is_owner }}
<a id="show_realm_domains_modal" role="button">{{t "[Configure]" }}</a>
{{/if}}
</div>
</div>
<div class="input-group time-limit-setting">
<label for="id_realm_waiting_period_threshold" class="settings-field-label">
{{t "Waiting period before new members turn into full members" }}
{{> ../help_link_widget link="/help/restrict-permissions-of-new-members" }}
</label>
<select name="realm_waiting_period_threshold" id="id_realm_waiting_period_threshold" class="prop-element settings_select bootstrap-focus-style" data-setting-widget-type="time-limit">
{{> dropdown_options_widget option_values=waiting_period_threshold_dropdown_values}}
</select>
{{!-- This setting is hidden unless `custom_period` --}}
<div class="dependent-settings-block">
<label for="id_realm_waiting_period_threshold_custom_input" class="inline-block">{{t "Waiting period (days)" }}:</label>
<input type="text" id="id_realm_waiting_period_threshold_custom_input"
name="realm_waiting_period_threshold_custom_input"
class="time-limit-custom-input"
value="{{ realm_waiting_period_threshold }}"/>
</div>
</div>
</div>
<div id="org-stream-permissions" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Channel permissions" }}
{{> ../help_link_widget link="/help/channel-permissions" }}
</h3>
{{> settings_save_discard_widget section_name="stream-permissions" show_save_discard_buttons=true }}
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_create_public_channel_group"
label=group_setting_labels.can_create_public_channel_group}}
{{> upgrade_tip_widget . }}
{{> settings_checkbox
setting_name="realm_enable_spectator_access"
prefix="id_"
is_checked=realm_enable_spectator_access
label=admin_settings_label.realm_enable_spectator_access
is_disabled=disable_enable_spectator_access_setting
help_link="/help/public-access-option"}}
{{> ../dropdown_widget_with_label
widget_name="realm_can_create_web_public_channel_group"
label=group_setting_labels.can_create_web_public_channel_group
value_type="number"}}
{{> group_setting_value_pill_input
setting_name="realm_can_create_private_channel_group"
label=group_setting_labels.can_create_private_channel_group}}
{{> group_setting_value_pill_input
setting_name="realm_can_add_subscribers_group"
label=group_setting_labels.can_add_subscribers_group}}
{{> group_setting_value_pill_input
setting_name="realm_can_mention_many_users_group"
label=group_setting_labels.can_mention_many_users_group
help_link="/help/restrict-wildcard-mentions"}}
{{> group_setting_value_pill_input
setting_name="realm_can_set_topics_policy_group"
label=group_setting_labels.can_set_topics_policy_group
help_link="/help/require-topics"}}
</div>
<div id="org-group-permissions" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Group permissions" }}
{{> ../help_link_widget link="/help/manage-user-groups" }}
</h3>
{{> settings_save_discard_widget section_name="group-permissions" show_save_discard_buttons=true }}
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_manage_all_groups"
label=group_setting_labels.can_manage_all_groups}}
{{> upgrade_tip_widget . }}
{{> group_setting_value_pill_input
setting_name="realm_can_create_groups"
label=group_setting_labels.can_create_groups}}
</div>
<div id="org-direct-message-permissions" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Direct message permissions" }}
{{> ../help_link_widget link="/help/restrict-direct-messages" }}
</h3>
{{> settings_save_discard_widget section_name="direct-message-permissions" show_save_discard_buttons=true }}
</div>
{{> group_setting_value_pill_input
setting_name="realm_direct_message_permission_group"
label=group_setting_labels.direct_message_permission_group}}
{{> group_setting_value_pill_input
setting_name="realm_direct_message_initiator_group"
label=group_setting_labels.direct_message_initiator_group}}
</div>
<div id="org-msg-editing" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Message editing" }}
{{> ../help_link_widget link="/help/restrict-message-editing-and-deletion" }}
</h3>
{{> settings_save_discard_widget section_name="msg-editing" show_save_discard_buttons=true }}
</div>
{{> settings_checkbox
setting_name="realm_allow_message_editing"
prefix="id_"
is_checked=realm_allow_message_editing
label=admin_settings_label.realm_allow_message_editing}}
<div class="input-group">
<label for="id_realm_message_edit_history_visibility_policy" class="settings-field-label">{{t "Allow viewing the history of a message?"}}</label>
<select name="realm_message_edit_history_visibility_policy" id="id_realm_message_edit_history_visibility_policy" class="prop-element settings_select bootstrap-focus-style" data-setting-widget-type="string">
{{> dropdown_options_widget option_values=(object_values message_edit_history_visibility_policy_values)}}
</select>
</div>
<div class="input-group time-limit-setting">
<label for="id_realm_message_content_edit_limit_seconds" class="settings-field-label">{{t "Time limit for editing messages" }}</label>
<select name="realm_message_content_edit_limit_seconds" id="id_realm_message_content_edit_limit_seconds" class="prop-element settings_select bootstrap-focus-style" {{#unless realm_allow_message_editing}}disabled{{/unless}} data-setting-widget-type="time-limit">
{{#each msg_edit_limit_dropdown_values}}
<option value="{{value}}">{{text}}</option>
{{/each}}
</select>
<div class="dependent-settings-block">
<label for="id_realm_message_content_edit_limit_minutes" class="inline-block realm-time-limit-label">
{{t 'Time limit'}}:&nbsp;
</label>
<input type="text" id="id_realm_message_content_edit_limit_minutes"
name="realm_message_content_edit_limit_minutes"
class="time-limit-custom-input"
autocomplete="off"
value="{{ realm_message_content_edit_limit_minutes }}"
{{#unless realm_allow_message_editing}}disabled{{/unless}}/>&nbsp;
<span class="time-unit-text">
{{t "{realm_message_content_edit_limit_minutes, plural, one {minute} other {minutes}}"}}
</span>
</div>
</div>
</div>
<div id="org-moving-msgs" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Moving messages" }}
{{> ../help_link_widget link="/help/restrict-moving-messages" }}
</h3>
{{> settings_save_discard_widget section_name="moving-msgs" show_save_discard_buttons=true }}
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_move_messages_between_topics_group"
label=group_setting_labels.can_move_messages_between_topics_group}}
<div class="input-group time-limit-setting">
<label for="id_realm_move_messages_within_stream_limit_seconds" class="settings-field-label">{{t "Time limit for editing topics" }} <i>({{t "does not apply to moderators and administrators" }})</i></label>
<select name="realm_move_messages_within_stream_limit_seconds" id="id_realm_move_messages_within_stream_limit_seconds" class="prop-element settings_select" data-setting-widget-type="time-limit">
{{#each msg_move_limit_dropdown_values}}
<option value="{{value}}">{{text}}</option>
{{/each}}
</select>
<div class="dependent-settings-block">
<label for="id_realm_move_messages_within_stream_limit_minutes" class="inline-block realm-time-limit-label">
{{t 'Time limit'}}:&nbsp;
</label>
<input type="text" id="id_realm_move_messages_within_stream_limit_minutes"
name="realm_move_messages_within_stream_limit_minutes"
class="time-limit-custom-input"
autocomplete="off"/>&nbsp;
<span class="time-unit-text">
{{t "{realm_move_messages_within_stream_limit_minutes, plural, one {minute} other {minutes}}"}}
</span>
</div>
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_move_messages_between_channels_group"
label=group_setting_labels.can_move_messages_between_channels_group}}
<div class="input-group time-limit-setting">
<label for="id_realm_move_messages_between_streams_limit_seconds" class="settings-field-label">{{t "Time limit for moving messages between channels" }} <i>({{t "does not apply to moderators and administrators" }})</i></label>
<select name="realm_move_messages_between_streams_limit_seconds" id="id_realm_move_messages_between_streams_limit_seconds" class="prop-element bootstrap-focus-style settings_select" data-setting-widget-type="time-limit">
{{#each msg_move_limit_dropdown_values}}
<option value="{{value}}">{{text}}</option>
{{/each}}
</select>
<div class="dependent-settings-block">
<label for="id_realm_move_messages_between_streams_limit_minutes" class="inline-block realm-time-limit-label">
{{t 'Time limit'}}:&nbsp;
</label>
<input type="text" id="id_realm_move_messages_between_streams_limit_minutes"
name="realm_move_messages_between_streams_limit_minutes"
class="time-limit-custom-input"
autocomplete="off"/>&nbsp;
<span class="time-unit-text">
{{t "{realm_move_messages_between_streams_limit_minutes, plural, one {minute} other {minutes}}"}}
</span>
</div>
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_resolve_topics_group"
label=group_setting_labels.can_resolve_topics_group}}
</div>
<div id="org-msg-deletion" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Message deletion" }}
{{> ../help_link_widget link="/help/delete-a-message" }}
</h3>
{{> settings_save_discard_widget section_name="msg-deletion" show_save_discard_buttons=true }}
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_delete_any_message_group"
label=group_setting_labels.can_delete_any_message_group}}
{{> group_setting_value_pill_input
setting_name="realm_can_delete_own_message_group"
label=group_setting_labels.can_delete_own_message_group}}
<div class="input-group time-limit-setting">
<label for="id_realm_message_content_delete_limit_seconds" class="settings-field-label">
{{t "Time limit for deleting messages" }} <i>({{t "does not apply to users who can delete any message" }})</i>
</label>
<select name="realm_message_content_delete_limit_seconds" id="id_realm_message_content_delete_limit_seconds" class="prop-element bootstrap-focus-style settings_select" data-setting-widget-type="time-limit">
{{#each msg_delete_limit_dropdown_values}}
<option value="{{value}}">{{text}}</option>
{{/each}}
</select>
<div class="dependent-settings-block">
<label for="id_realm_message_content_delete_limit_minutes" class="inline-block realm-time-limit-label">
{{t "Time limit" }}:&nbsp;
</label>
<input type="text" id="id_realm_message_content_delete_limit_minutes"
name="realm_message_content_delete_limit_minutes"
class="time-limit-custom-input"
autocomplete="off"
value="{{ realm_message_content_delete_limit_minutes }}"/>&nbsp;
<span class="time-unit-text">{{t "{realm_message_content_delete_limit_minutes, plural, one {minute} other {minutes}}"}}</span>
</div>
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_set_delete_message_policy_group"
label=group_setting_labels.can_set_delete_message_policy_group}}
</div>
<div id="org-user-identity" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "User identity" }}
{{> ../help_link_widget link="/help/restrict-name-and-email-changes" }}
</h3>
{{> settings_save_discard_widget section_name="user-identity" show_save_discard_buttons=true }}
</div>
{{> settings_checkbox
setting_name="realm_require_unique_names"
prefix="id_"
is_checked=realm_require_unique_names
label=admin_settings_label.realm_require_unique_names}}
{{> settings_checkbox
setting_name="realm_name_changes_disabled"
prefix="id_"
is_checked=(or realm_name_changes_disabled server_name_changes_disabled)
label=admin_settings_label.realm_name_changes_disabled
is_disabled=server_name_changes_disabled}}
{{> settings_checkbox
setting_name="realm_email_changes_disabled"
prefix="id_"
is_checked=realm_email_changes_disabled
label=admin_settings_label.realm_email_changes_disabled}}
{{> settings_checkbox
setting_name="realm_avatar_changes_disabled"
prefix="id_"
is_checked=(or realm_avatar_changes_disabled server_avatar_changes_disabled)
label=admin_settings_label.realm_avatar_changes_disabled
is_disabled=server_avatar_changes_disabled}}
</div>
<div id="org-guest-settings" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Guests" }}</h3>
{{> settings_save_discard_widget section_name="guest-settings" show_save_discard_buttons=true }}
</div>
{{> settings_checkbox
setting_name="realm_enable_guest_user_indicator"
prefix="id_"
is_checked=realm_enable_guest_user_indicator
label=admin_settings_label.realm_enable_guest_user_indicator}}
{{> settings_checkbox
setting_name="realm_enable_guest_user_dm_warning"
prefix="id_"
is_checked=realm_enable_guest_user_dm_warning
label=admin_settings_label.realm_enable_guest_user_dm_warning}}
{{> ../dropdown_widget_with_label
widget_name="realm_can_access_all_users_group"
label=group_setting_labels.can_access_all_users_group
value_type="number"
help_link="/help/guest-users#configure-whether-guests-can-see-all-other-users"}}
</div>
<div id="org-other-permissions" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Other permissions" }}</h3>
{{> settings_save_discard_widget section_name="other-permissions" show_save_discard_buttons=true }}
</div>
<div class="disabled-unfinished-feature"
{{#unless server_can_summarize_topics}}style="display: none"{{/unless}}>
{{#unless server_can_summarize_topics}}
<div class="tip">
{{#if is_plan_self_hosted}}
{{t "AI summaries are not enabled on this server."}}
{{else}}
{{t "AI summaries are not available on Zulip Cloud yet."}}
{{/if}}
</div>
{{/unless}}
{{> group_setting_value_pill_input
setting_name="realm_can_summarize_topics_group"
label=group_setting_labels.can_summarize_topics_group}}
</div>
{{> group_setting_value_pill_input
setting_name="realm_can_create_write_only_bots_group"
label=group_setting_labels.can_create_write_only_bots_group}}
{{> group_setting_value_pill_input
setting_name="realm_can_create_bots_group"
label=group_setting_labels.can_create_bots_group}}
{{> group_setting_value_pill_input
setting_name="realm_can_add_custom_emoji_group"
label=group_setting_labels.can_add_custom_emoji_group}}
</div>
</form>
</div>

View File

@@ -0,0 +1,101 @@
<div id="organization-profile" data-name="organization-profile" class="settings-section">
<form class="admin-realm-form org-profile-form">
<div class="alert" id="admin-realm-deactivation-status"></div>
<div id="org-org-profile" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Organization profile" }}
{{> ../help_link_widget link="/help/create-your-organization-profile" }}
</h3>
{{> settings_save_discard_widget section_name="org-profile" show_save_discard_buttons=true }}
</div>
<div class="input-group admin-realm">
<label for="id_realm_name" class="settings-field-label">{{t "Organization name" }}</label>
<input type="text" id="id_realm_name" name="realm_name" class="admin-realm-name setting-widget prop-element settings_text_input"
autocomplete="off" data-setting-widget-type="string"
value="{{ realm_name }}" maxlength="40" />
</div>
<div class="input-group admin-realm">
<label for="id_realm_org_type" class="settings-field-label">{{t "Organization type" }}
{{> ../help_link_widget link="/help/organization-type" }}
</label>
<select name="realm_org_type" class="setting-widget prop-element settings_select bootstrap-focus-style" id="id_realm_org_type" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values realm_org_type_values)}}
</select>
</div>
{{> settings_checkbox
setting_name="realm_want_advertise_in_communities_directory"
prefix="id_"
is_checked=realm_want_advertise_in_communities_directory
is_disabled=disable_want_advertise_in_communities_directory
label=admin_settings_label.realm_want_advertise_in_communities_directory
help_link="/help/communities-directory"}}
{{> realm_description . }}
</div>
<div>{{t "Organization profile picture" }}</div>
<div class="realm-icon-section">
{{> image_upload_widget
widget = "realm-icon"
upload_text = (t "Upload icon")
delete_text = (t "Delete icon")
is_editable_by_current_user = is_admin
image = realm_icon_url }}
</div>
{{> ../components/action_button
label=(t "Preview organization profile")
custom_classes="block"
id="id_org_profile_preview"
icon="external-link"
variant="subtle"
intent="brand"
}}
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Organization logo" }}
{{> ../help_link_widget link="/help/create-your-organization-profile#add-a-wide-logo" }}
</h3>
</div>
{{> upgrade_tip_widget . }}
<p>{{t "A wide logo for the upper left corner of the app (at least 200×25 pixels recommended)." }}</p>
<div class="realm-logo-group">
<div class="realm-logo-block realm-logo-section">
<h5 class="realm-logo-title">{{t "Light theme logo" }}</h5>
{{> image_upload_widget
widget = "realm-day-logo"
upload_text = (t "Upload logo")
delete_text = (t "Delete logo")
is_editable_by_current_user = user_can_change_logo
image = realm_logo_url }}
</div>
<div class="realm-logo-block realm-logo-section">
<h5 class="realm-logo-title">{{t "Dark theme logo" }}</h5>
{{> image_upload_widget
widget = "realm-night-logo"
upload_text = (t "Upload logo")
delete_text = (t "Delete logo")
is_editable_by_current_user = user_can_change_logo
image = realm_night_logo_url }}
</div>
</div>
<div class="deactivate-realm-section">
<div class="subsection-header">
<h3 class="settings-subsection-title">
{{t "Deactivate organization" }}
{{> ../help_link_widget link="/help/deactivate-your-organization" }}
</h3>
</div>
<div class="input-group">
<div id="deactivate_realm_button_container" class="inline-block">
{{> ../components/action_button
label=(t "Deactivate organization")
variant="subtle"
intent="danger"
custom_classes="deactivate_realm_button"
}}
</div>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,323 @@
<div id="organization-settings" data-name="organization-settings" class="settings-section">
<form class="admin-realm-form org-settings-form">
<div id="org-billing" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Billing" }}</h3>
{{> settings_save_discard_widget section_name="onboarding" show_save_discard_buttons=true }}
</div>
{{#if show_two_tier_billing_settings}}
{{> settings_checkbox
setting_name="realm_enable_two_tier_billing"
prefix="id_"
is_checked=realm_enable_two_tier_billing
label=admin_settings_label.realm_enable_two_tier_billing
skip_prop_element=true}}
{{> group_setting_value_pill_input
setting_name="realm_workplace_users_group"
label=group_setting_labels.workplace_users_group}}
{{/if}}
{{#if is_plan_self_hosted}}
{{> group_setting_value_pill_input
setting_name="realm_can_manage_billing_group"
label=group_setting_labels.can_manage_billing_group
help_link="https://zulip.com//help/self-hosted-billing"
}}
{{else}}
{{> group_setting_value_pill_input
setting_name="realm_can_manage_billing_group"
label=group_setting_labels.can_manage_billing_group
help_link="/help/zulip-cloud-billing"
}}
{{/if}}
</div>
<div id="org-notifications" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Automated messages and emails" }}</h3>
{{> settings_save_discard_widget section_name="notifications" show_save_discard_buttons=true }}
</div>
{{> ../dropdown_widget_with_label
widget_name="realm_default_language"
label=admin_settings_label.realm_default_language
value_type="string"
help_link="/help/configure-organization-language"}}
{{> ../dropdown_widget_with_label
widget_name="realm_moderation_request_channel_id"
label=admin_settings_label.realm_moderation_request_channel
value_type="number"
help_link="/help/enable-moderation-requests"
}}
{{> ../dropdown_widget_with_label
widget_name="realm_new_stream_announcements_stream_id"
label=admin_settings_label.realm_new_stream_announcements_stream
value_type="number"
custom_classes="decorated-stream-name-dropdown-widget"}}
{{> ../dropdown_widget_with_label
widget_name="realm_signup_announcements_stream_id"
label=admin_settings_label.realm_signup_announcements_stream
value_type="number"
custom_classes="decorated-stream-name-dropdown-widget"}}
{{> ../dropdown_widget_with_label
widget_name="realm_zulip_update_announcements_stream_id"
label=admin_settings_label.realm_zulip_update_announcements_stream
value_type="number"
custom_classes="decorated-stream-name-dropdown-widget"}}
{{> settings_checkbox
setting_name="realm_send_channel_events_messages"
prefix="id_"
is_checked=realm_send_channel_events_messages
label=admin_settings_label.realm_send_channel_events_messages
help_link="/help/configure-automated-notices#notices-about-channels"}}
{{#if settings_send_digest_emails }}
{{> settings_checkbox
setting_name="realm_digest_emails_enabled"
prefix="id_"
is_checked=realm_digest_emails_enabled
label=admin_settings_label.realm_digest_emails_enabled}}
{{/if}}
<div class="input-group">
<label for="id_realm_digest_weekday" class="settings-field-label">{{t "Day of the week to send digests" }}</label>
<select name="realm_digest_weekday"
id="id_realm_digest_weekday"
class="setting-widget prop-element settings_select bootstrap-focus-style"
data-setting-widget-type="number">
<option value="0">{{t "Monday" }}</option>
<option value="1">{{t "Tuesday" }}</option>
<option value="2">{{t "Wednesday" }}</option>
<option value="3">{{t "Thursday" }}</option>
<option value="4">{{t "Friday" }}</option>
<option value="5">{{t "Saturday" }}</option>
<option value="6">{{t "Sunday" }}</option>
</select>
</div>
</div>
<div id="org-onboarding" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Onboarding" }}</h3>
{{> settings_save_discard_widget section_name="onboarding" show_save_discard_buttons=true }}
</div>
<div class="input-group">
<label class="settings-field-label">
{{admin_settings_label.realm_default_avatar_source}}
{{> ../help_link_widget link="/help/configure-default-profile-pictures" }}
</label>
<div class="default_avatar_source_values settings-highlight-box prop-element" id="id_realm_default_avatar_source" data-setting-widget-type="radio-group" data-setting-choice-type="string">
{{#each (object_values default_avatar_source_values)}}
<label class="preferences-radio-choice-label">
<span class="radio-choice-controls">
<input type="radio" name="default_avatar_source" value="{{this.code}}"/>
<span class="preferences-radio-choice-text">{{this.description}}</span>
</span>
<span class="right">
{{#if (eq this.code "J") }}
<img class="avatar" src="/static/images/jdenticon-1.png" />
<img class="avatar" src="/static/images/jdenticon-2.png" />
<img class="avatar" src="/static/images/jdenticon-3.png" />
<img class="avatar" src="/static/images/jdenticon-4.png" />
{{else}}
<img class="avatar" src="/static/images/gravatar-1.png" />
<img class="avatar" src="/static/images/gravatar-2.png" />
<img class="avatar" src="/static/images/gravatar-3.png" />
<img class="avatar" src="/static/images/gravatar-4.png" />
{{/if}}
</span>
</label>
{{/each}}
</div>
</div>
{{> settings_checkbox
setting_name="realm_enable_welcome_message_custom_text"
prefix="id_"
is_checked=realm_enable_welcome_message_custom_text
label=admin_settings_label.realm_enable_welcome_message_custom_text
skip_prop_element=true}}
<div class="input-group" id="welcome_message_custom_text_container">
<label for="id_realm_welcome_message_custom_text" class="settings-field-label">
{{t "Message text" }}
</label>
<textarea id="id_realm_welcome_message_custom_text" name="welcome_message_custom_text"
class="admin-realm-welcome-message-custom-text setting-widget prop-element settings-textarea display-block" maxlength="8000"
data-setting-widget-type="string">{{ realm_welcome_message_custom_text }}</textarea>
<div id="welcome_message_custom_text_buttons_container">
{{> ../components/action_button variant="subtle" intent="neutral" label=(t "Send me a test message") id="send_test_welcome_bot_custom_message"}}
</div>
</div>
{{> settings_checkbox
setting_name="realm_send_welcome_emails"
prefix="id_"
is_checked=realm_send_welcome_emails
label=admin_settings_label.realm_send_welcome_emails}}
</div>
<div class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Notifications security" }}</h3>
{{> settings_save_discard_widget section_name="notifications-security" show_save_discard_buttons=true }}
</div>
{{> settings_checkbox
setting_name="realm_require_e2ee_push_notifications"
prefix="id_"
is_checked=realm_require_e2ee_push_notifications
label=admin_settings_label.realm_require_e2ee_push_notifications
help_link="/help/mobile-notifications"}}
{{> settings_checkbox
setting_name="realm_message_content_allowed_in_email_notifications"
prefix="id_"
is_checked=realm_message_content_allowed_in_email_notifications
label=admin_settings_label.realm_message_content_allowed_in_email_notifications}}
</div>
<div id="org-compose-settings" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Compose settings"}}</h3>
{{> settings_save_discard_widget section_name="compose-settings" show_save_discard_buttons=true }}
</div>
<div class="input-group">
<label for="id_realm_video_chat_provider" class="settings-field-label">
{{t 'Call provider' }}
{{> ../help_link_widget link="/help/configure-call-provider" }}
</label>
<select name="realm_video_chat_provider" class ="setting-widget prop-element settings_select bootstrap-focus-style" id="id_realm_video_chat_provider" data-setting-widget-type="number">
{{#each (object_values realm_available_video_chat_providers)}}
<option value='{{this.id}}'>{{this.name}}</option>
{{/each}}
</select>
<div class="dependent-settings-block" id="realm_jitsi_server_url_setting">
<div>
<label for="id_realm_jitsi_server_url" class="settings-field-label">
{{t "Jitsi server URL" }}
{{> ../help_link_widget link="/help/configure-call-provider#use-a-self-hosted-instance-of-jitsi-meet" }}
</label>
<select name="realm_jitsi_server_url" id="id_realm_jitsi_server_url" class="setting-widget prop-element settings_select bootstrap-focus-style" data-setting-widget-type="jitsi-server-url-setting">
{{#if server_jitsi_server_url}}
<option value="server_default">
{{#tr}}{server_jitsi_server_url} (default){{/tr}}
</option>
{{else}}
<option value="server_default">{{t 'Disabled' }}</option>
{{/if}}
<option value="custom">{{t 'Custom URL' }}</option>
</select>
</div>
<div>
<label for="id_realm_jitsi_server_url_custom_input" class="jitsi_server_url_custom_input_label">
{{t 'URL' }}
</label>
<input type="text" id="id_realm_jitsi_server_url_custom_input" autocomplete="off"
name="realm_jitsi_server_url_custom_input" class="realm_jitsi_server_url_custom_input settings_url_input" maxlength="200" />
</div>
</div>
</div>
<div class="input-group">
<label for="id_realm_gif_rating_policy" class="settings-field-label">
{{t 'GIF picker' }}
{{> ../help_link_widget link=gif_help_link }}
</label>
<select name="realm_gif_rating_policy" class ="setting-widget prop-element settings_select bootstrap-focus-style" id="id_realm_gif_rating_policy" data-setting-widget-type="number" {{#if gif_api_key_empty}}disabled{{/if}}>
{{#each (object_values gif_rating_policy_options)}}
<option value='{{this.id}}'>{{this.name}}</option>
{{/each}}
</select>
</div>
<div class="input-group">
<label for="id_realm_topics_policy" class="settings-field-label">{{> realm_topics_policy_label .}}</label>
<select name="realm_topics_policy" id="id_realm_topics_policy" class="prop-element settings_select bootstrap-focus-style" data-setting-widget-type="string">
{{> dropdown_options_widget option_values=(object_values realm_topics_policy_values)}}
</select>
</div>
</div>
<div id="org-msg-feed-settings" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Message feed settings"}}</h3>
{{> settings_save_discard_widget section_name="msg-feed-settings" show_save_discard_buttons=true }}
</div>
{{> ../dropdown_widget_with_label
widget_name="realm_default_code_block_language"
label=admin_settings_label.realm_default_code_block_language
value_type="string"}}
{{> settings_checkbox
setting_name="realm_enable_read_receipts"
prefix="id_"
is_checked=realm_enable_read_receipts
label=admin_settings_label.realm_enable_read_receipts
label_parens_text=admin_settings_label.realm_enable_read_receipts_parens_text}}
<div class="input-group">
<label for="id_realm_media_preview_size" class="settings-field-label">{{admin_settings_label.realm_media_preview_size}}</label>
<select name="realm_media_preview_size" id="id_realm_media_preview_size" class="prop-element settings_select bootstrap-focus-style" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=realm_media_preview_size_values}}
</select>
</div>
{{#if server_inline_image_preview}}
{{> settings_checkbox
setting_name="realm_inline_image_preview"
prefix="id_"
is_checked=realm_inline_image_preview
label=admin_settings_label.realm_inline_image_preview
help_link="/help/image-video-and-website-previews"}}
{{/if}}
{{#if server_inline_url_embed_preview}}
{{> settings_checkbox
setting_name="realm_inline_url_embed_preview"
prefix="id_"
is_checked=realm_inline_url_embed_preview
label=admin_settings_label.realm_inline_url_embed_preview
help_link="/help/image-video-and-website-previews"}}
{{/if}}
</div>
<div id="org-message-retention" class="settings-subsection-parent">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Message retention period" }}
{{> ../help_link_widget link="/help/message-retention-policy" }}
</h3>
{{> settings_save_discard_widget section_name="message-retention" show_save_discard_buttons=true }}
</div>
{{> upgrade_tip_widget . }}
<div class="input-group time-limit-setting">
<label for="id_realm_message_retention_days" class="settings-field-label">{{t "Message retention period" }}
</label>
<select name="realm_message_retention_days"
id="id_realm_message_retention_days" class="prop-element settings_select bootstrap-focus-style"
data-setting-widget-type="message-retention-setting"
{{#unless zulip_plan_is_not_limited}}disabled{{/unless}}>
<option value="unlimited">{{t 'Retain forever' }}</option>
<option value="custom_period">{{t 'Custom' }}</option>
</select>
<div class="dependent-settings-block">
<label for="id_realm_message_retention_custom_input" class="inline-block realm-time-limit-label">
{{t 'Retention period (days)' }}:
</label>
<input type="text" id="id_realm_message_retention_custom_input" autocomplete="off"
name="realm_message_retention_custom_input"
class="admin-realm-message-retention-days message-retention-setting-custom-input time-limit-custom-input"
data-setting-widget-type="number"
{{#unless zulip_plan_is_not_limited}}disabled{{/unless}}/>
</div>
</div>
</div>
</form>
</div>

View File

@@ -0,0 +1,9 @@
{{#unless is_admin}}
<div class="banner-wrapper">
{{> ../components/banner
label=(t "Only organization administrators can edit these settings.")
intent="info"
custom_classes="admin-permissions-banner"
}}
</div>
{{/unless}}

View File

@@ -0,0 +1,14 @@
<div id="realm-user-default-settings" class="settings-section" data-name="organization-level-user-defaults">
{{#if is_admin}}
<div>
{{#tr}}
Configure the <z-link>default personal preference settings</z-link>
for new users joining your organization.
{{#*inline "z-link"}}<a href="/help/configure-default-new-user-settings" target="_blank" rel="noopener noreferrer">{{> @partial-block }}</a>{{/inline}}
{{/tr}}
</div>
{{/if}}
{{> preferences . prefix="realm_" for_realm_settings=true full_name=full_name}}
{{> notification_settings . prefix="realm_" for_realm_settings=true}}
</div>

View File

@@ -0,0 +1,96 @@
<div id="playground-settings" class="settings-section" data-name="playground-settings">
<div>
<p>
{{#tr}}
Code playgrounds are interactive in-browser development environments,
that are designed to make
it convenient to edit and debug code. Zulip <z-link-code-blocks>code blocks</z-link-code-blocks>
that are tagged with a programming language will have a button visible on
hover that allows users to open the code block on the code playground site.
{{#*inline "z-link-code-blocks"}}<a href="/help/code-blocks" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<p>
{{t "For example, to configure a code playground for code blocks tagged as Rust,
you can set:" }}
</p>
<ul>
<li>
{{t "Language" }}: <span class="rendered_markdown"><code>Rust</code></span>
</li>
<li>
{{t "Name" }}: <span class="rendered_markdown"><code>Rust playground</code></span>
</li>
<li>
{{t "URL template" }}: <span class="rendered_markdown"><code>https://play.rust-lang.org/?code={code}</code></span>
</li>
</ul>
<p>
{{#tr}}
For more examples and technical details, see the <z-link>help center documentation</z-link>
on adding code playgrounds.
{{#*inline "z-link"}}<a href="/help/code-blocks#code-playgrounds" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
{{#if is_admin}}
<form class="admin-playground-form">
<div class="add-new-playground-box settings-highlight-box">
<div class="new-playground-form wrapper">
<div class="settings-section-title">
{{t "Add a new code playground" }}
{{> ../help_link_widget link="/help/code-blocks#code-playgrounds" }}
</div>
<div class="alert" id="admin-playground-status"></div>
<div class="input-group">
<label for="playground_pygments_language"> {{t "Language" }}</label>
<input type="text" id="playground_pygments_language" class="settings_text_input" name="pygments_language" autocomplete="off" placeholder="Rust" />
</div>
<div class="input-group">
<label for="playground_name"> {{t "Name" }}</label>
<input type="text" id="playground_name" class="settings_text_input" name="playground_name" autocomplete="off" placeholder="Rust playground" />
</div>
<div class="input-group">
<label for="playground_url_template"> {{t "URL template" }}</label>
<input type="text" id="playground_url_template" class="settings_text_input" name="url_template" placeholder="https://play.rust-lang.org/?code={code}" />
</div>
{{> ../components/action_button
id="submit_playground_button"
label=(t "Add code playground")
variant="subtle"
intent="brand"
type="submit"
}}
</div>
</div>
</form>
{{/if}}
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Code playgrounds"}}</h3>
{{> filter_text_input placeholder=(t 'Filter') aria_label=(t 'Filter code playgrounds')}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table admin_playgrounds_table">
<thead class="table-sticky-headers">
<tr>
<th class="active" data-sort="alphabetic" data-sort-prop="pygments_language">{{t "Language" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="alphabetic" data-sort-prop="name">{{t "Name" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="alphabetic" data-sort-prop="url_template">{{t "URL template" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
{{#if is_admin}}
<th class="actions">{{t "Actions" }}</th>
{{/if}}
</tr>
</thead>
<tbody id="admin_playgrounds_table" data-empty="{{t 'No playgrounds configured.' }}" data-search-results-empty="{{t 'No playgrounds match your current filter.' }}"></tbody>
</table>
</div>
</div>
</div>

View File

@@ -0,0 +1,13 @@
<form class="preferences-settings-form">
{{>preferences_general .}}
{{!-- user_has_email_set is passed as true here, because we don't disable the dropdown in organization panel also there's no need to show tooltip here. --}}
{{#if for_realm_settings}}{{> privacy_settings . prefix="realm_" read_receipts_help_icon_tooltip_text="" hide_read_receipts_tooltip=true user_has_email_set=true}}{{/if}}
{{>preferences_emoji .}}
{{>preferences_navigation .}}
{{>preferences_information .}}
{{>preferences_left_sidebar .}}
</form>

View File

@@ -0,0 +1,50 @@
<div class="emoji-preferences {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Emoji" }}</h3>
{{> settings_save_discard_widget section_name="emoji-preferences-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<div class="input-group">
<label class="settings-field-label">
{{t "Emoji theme" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<div class="emojiset_choices settings-highlight-box prop-element" id="{{prefix}}emojiset" data-setting-widget-type="radio-group" data-setting-choice-type="string">
{{#each settings_object.emojiset_choices}}
<label class="preferences-radio-choice-label">
<span class="radio-choice-controls">
<input type="radio" class="setting_emojiset_choice" name="emojiset" value="{{this.key}}"/>
<span class="preferences-radio-choice-text">{{this.text}}</span>
</span>
<span class="right">
{{#if (eq this.key "text") }}
<span class="emoji_alt_code">&nbsp;:relaxed:</span>
{{else}}
<img class="emoji" src="/static/generated/emoji/images-{{this.key}}-64/1f604.png" />
<img class="emoji" src="/static/generated/emoji/images-{{this.key}}-64/1f44d.png" />
<img class="emoji" src="/static/generated/emoji/images-{{this.key}}-64/1f680.png" />
<img class="emoji" src="/static/generated/emoji/images-{{this.key}}-64/1f389.png" />
{{/if}}
</span>
</label>
{{/each}}
</div>
</div>
{{> settings_checkbox
setting_name="translate_emoticons"
is_checked=settings_object.translate_emoticons
label=settings_label.translate_emoticons
help_link="/help/configure-emoticon-translations"
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="display_emoji_reaction_users"
is_checked=settings_object.display_emoji_reaction_users
label=settings_label.display_emoji_reaction_users
prefix=prefix
show_reset_button=for_realm_settings}}
</div>

View File

@@ -0,0 +1,94 @@
<div class="general-settings {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<!-- this is inline block so that the alert notification can sit beside
it. If there's not an alert, don't make it inline-block.-->
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "General" }}</h3>
{{> settings_save_discard_widget section_name="general-settings" show_save_discard_buttons=for_realm_settings }}
</div>
{{#unless for_realm_settings}}
{{> ../dropdown_widget_with_label
widget_name="default_language"
label=settings_label.default_language_settings_label
value_type="string"
help_link="/help/change-your-language"}}
{{/unless}}
<div class="input-group">
<label for="{{prefix}}twenty_four_hour_time" class="settings-field-label">
{{ settings_label.twenty_four_hour_time }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="twenty_four_hour_time" class="setting_twenty_four_hour_time prop-element settings_select bootstrap-focus-style" id="{{prefix}}twenty_four_hour_time" data-setting-widget-type="string">
{{#each (object_values twenty_four_hour_time_values)}}
<option value='{{#if this.value}}true{{else}}false{{/if}}'>{{ this.description }}</option>
{{/each}}
</select>
</div>
<div class="input-group">
<label for="{{prefix}}color_scheme" class="settings-field-label">
{{t "Theme" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<div id="{{prefix}}color_scheme" class="tab-picker prop-element" data-setting-widget-type="radio-group" data-setting-choice-type="number">
<input type="radio" id="{{prefix}}theme_select_automatic" class="tab-option setting_color_scheme" data-setting-widget-type="number" name="{{prefix}}theme_select" value="{{color_scheme_values.automatic.code}}" />
<label class="tab-option-content tippy-zulip-delayed-tooltip" for="{{prefix}}theme_select_automatic" aria-label="{{t 'Select automatic theme' }}" data-tooltip-template-id="automatic-theme-template" tabindex="0">
<i class="zulip-icon zulip-icon-monitor" aria-hidden="true"></i>
</label>
<input type="radio" id="{{prefix}}theme_select_light" class="tab-option setting_color_scheme" data-setting-widget-type="number" name="{{prefix}}theme_select" value="{{color_scheme_values.light.code}}" />
<label class="tab-option-content tippy-zulip-delayed-tooltip" for="{{prefix}}theme_select_light" aria-label="{{t 'Select light theme' }}" data-tippy-content="{{t 'Light theme' }}" tabindex="0">
<i class="zulip-icon zulip-icon-sun" aria-hidden="true"></i>
</label>
<input type="radio" id="{{prefix}}theme_select_dark" class="tab-option setting_color_scheme" data-setting-widget-type="number" name="{{prefix}}theme_select" value="{{color_scheme_values.dark.code}}" />
<label class="tab-option-content tippy-zulip-delayed-tooltip" for="{{prefix}}theme_select_dark" aria-label="{{t 'Select dark theme' }}" data-tippy-content="{{t 'Dark theme' }}" tabindex="0">
<i class="zulip-icon zulip-icon-moon" aria-hidden="true"></i>
</label>
<span class="slider"></span>
</div>
</div>
{{> settings_checkbox
setting_name="enter_sends"
is_checked=settings_object.enter_sends
label=settings_label.enter_sends
prefix=prefix
show_reset_button=for_realm_settings}}
<div class="information-density-settings">
<div class="font-size-setting info-density-controls">
<div class="title">
{{t "Font size"}}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</div>
{{> info_density_control_button_group
property="web_font_size_px"
default_icon_class="zulip-icon-type-big"
property_value=settings_object.web_font_size_px
display_value=settings_object.web_font_size_px
for_settings_ui=true
prefix=prefix
}}
</div>
<div class="line-height-setting info-density-controls">
<div class="title">
{{t "Line spacing"}}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</div>
{{> info_density_control_button_group
property="web_line_height_percent"
default_icon_class="zulip-icon-line-height-big"
property_value=settings_object.web_line_height_percent
display_value=web_line_height_percent_display_value
for_settings_ui=true
prefix=prefix
}}
</div>
</div>
</div>

View File

@@ -0,0 +1,109 @@
<div class="information-settings {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Information" }}</h3>
{{> settings_save_discard_widget section_name="information-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<div class="input-group">
<label class="settings-field-label">
{{t "User list style" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<div class="user_list_style_values settings-highlight-box prop-element" id="{{prefix}}user_list_style" data-setting-widget-type="radio-group" data-setting-choice-type="number">
{{#each (object_values user_list_style_values)}}
<label class="preferences-radio-choice-label">
<span class="radio-choice-controls">
<input type="radio" class="setting_user_list_style_choice" name="user_list_style" value="{{this.code}}"/>
<span class="preferences-radio-choice-text">{{this.description}}</span>
</span>
<span class="right preview">
{{#if (eq this.code 1)}}
<span class="user-name-and-status-emoji">
<span class="user-name">{{../full_name}}</span>
{{> ../status_emoji emoji_name="house" emoji_code="1f3e0"}}
</span>
{{/if}}
{{#if (eq this.code 2)}}
<span class="user-name-and-status-text">
<span class="user-name-and-status-emoji">
<span class="user-name">{{../full_name}}</span>
{{> ../status_emoji emoji_name="house" emoji_code="1f3e0"}}
</span>
<span class="status-text">{{t "Working remotely" }}</span>
</span>
{{/if}}
{{#if (eq this.code 3)}}
<span class="profile-with-avatar">
<span class="user-profile-picture">
<img src="{{../profile_picture}}"/>
</span>
<span class="user-name-and-status-wrapper">
<span class="user-name-and-status-emoji">
<span class="user-name">{{../full_name}}</span>
{{> ../status_emoji emoji_name="house" emoji_code="1f3e0"}}
</span>
<span class="status-text">{{t "Working remotely" }}</span>
</span>
</span>
{{/if}}
</span>
</label>
{{/each}}
</div>
</div>
<div class="input-group">
<label for="{{prefix}}web_animate_image_previews" class="settings-field-label">
{{t "Play animated images" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="web_animate_image_previews" class="setting_web_animate_image_previews prop-element settings_select bootstrap-focus-style" id="{{prefix}}web_animate_image_previews" data-setting-widget-type="string">
{{> dropdown_options_widget option_values=(object_values web_animate_image_previews_values)}}
</select>
</div>
{{> settings_checkbox
setting_name="receives_typing_notifications"
is_checked=settings_object.receives_typing_notifications
label=settings_label.receives_typing_notifications
render_only=settings_render_only.receives_typing_notifications
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="web_inbox_show_channel_folders"
is_checked=settings_object.web_inbox_show_channel_folders
label=settings_label.web_inbox_show_channel_folders
render_only=settings_render_only.web_inbox_show_channel_folders
help_link="/help/channel-folders"
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="hide_ai_features"
is_checked=settings_object.hide_ai_features
label=settings_label.hide_ai_features
render_only=settings_render_only.hide_ai_features
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="fluid_layout_width"
is_checked=settings_object.fluid_layout_width
label=settings_label.fluid_layout_width
render_only=settings_render_only.fluid_layout_width
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="high_contrast_mode"
is_checked=settings_object.high_contrast_mode
label=settings_label.high_contrast_mode
render_only=settings_render_only.high_contrast_mode
prefix=prefix
show_reset_button=for_realm_settings}}
</div>

View File

@@ -0,0 +1,55 @@
<div class="left-sidebar-settings {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Left sidebar" }}</h3>
{{> settings_save_discard_widget section_name="left-sidebar-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<div class="input-group">
<label for="{{prefix}}web_stream_unreads_count_display_policy" class="settings-field-label">
{{t "Show unread counts for" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="web_stream_unreads_count_display_policy" class="setting_web_stream_unreads_count_display_policy prop-element bootstrap-focus-style settings_select" id="{{prefix}}web_stream_unreads_count_display_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values web_stream_unreads_count_display_policy_values)}}
</select>
</div>
{{> settings_checkbox
setting_name="web_left_sidebar_unreads_count_summary"
is_checked=settings_object.web_left_sidebar_unreads_count_summary
label=settings_label.web_left_sidebar_unreads_count_summary
render_only=settings_render_only.web_left_sidebar_unreads_count_summary
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="starred_message_counts"
is_checked=settings_object.starred_message_counts
label=settings_label.starred_message_counts
render_only=settings_render_only.starred_message_counts
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="web_left_sidebar_show_channel_folders"
is_checked=settings_object.web_left_sidebar_show_channel_folders
label=settings_label.web_left_sidebar_show_channel_folders
render_only=settings_render_only.web_left_sidebar_show_channel_folders
help_link="/help/channel-folders"
prefix=prefix
show_reset_button=for_realm_settings}}
<div class="input-group">
<label for="{{prefix}}demote_inactive_streams" class="settings-field-label">{{t "Hide inactive channels" }}
{{> ../help_link_widget link="/help/manage-inactive-channels" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="demote_inactive_streams" class="setting_demote_inactive_streams prop-element settings_select bootstrap-focus-style" id="{{prefix}}demote_inactive_streams" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values demote_inactive_streams_values)}}
</select>
</div>
</div>

View File

@@ -0,0 +1,56 @@
<div class="navigation-settings {{#if for_realm_settings}}settings-subsection-parent{{else}}subsection-parent{{/if}}">
<div class="subsection-header">
<h3 class="settings-subsection-title">{{t "Navigation" }}</h3>
{{> settings_save_discard_widget section_name="navigation-settings" show_save_discard_buttons=for_realm_settings }}
</div>
<div class="input-group">
<label for="{{prefix}}web_home_view" class="settings-field-label">{{t "Home view" }}
{{> ../help_link_widget link="/help/configure-home-view" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="web_home_view" class="setting_web_home_view prop-element settings_select bootstrap-focus-style" id="{{prefix}}web_home_view" data-setting-widget-type="string">
{{> dropdown_options_widget option_values=(object_values web_home_view_values)}}
</select>
</div>
{{> settings_checkbox
setting_name="web_escape_navigates_to_home_view"
is_checked=settings_object.web_escape_navigates_to_home_view
label=settings_label.web_escape_navigates_to_home_view
prefix=prefix
show_reset_button=for_realm_settings}}
{{> settings_checkbox
setting_name="web_navigate_to_sent_message"
is_checked=settings_object.web_navigate_to_sent_message
label=settings_label.web_navigate_to_sent_message
prefix=prefix
show_reset_button=for_realm_settings}}
<div class="input-group">
<label for="{{prefix}}web_mark_read_on_scroll_policy" class="settings-field-label">{{t "Automatically mark messages as read" }}
{{> ../help_link_widget link="/help/marking-messages-as-read" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="web_mark_read_on_scroll_policy" class="setting_web_mark_read_on_scroll_policy prop-element settings_select bootstrap-focus-style" id="{{prefix}}web_mark_read_on_scroll_policy" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values web_mark_read_on_scroll_policy_values)}}
</select>
</div>
<div class="input-group">
<label for="{{prefix}}web_channel_default_view" class="settings-field-label">
{{t "Clicking on a channel in the left sidebar navigates to" }}
{{#if for_realm_settings}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
<select name="web_channel_default_view" class="setting_web_channel_default_view prop-element settings_select bootstrap-focus-style" id="{{prefix}}web_channel_default_view" data-setting-widget-type="number">
{{> dropdown_options_widget option_values=(object_values web_channel_default_view_values)}}
</select>
</div>
</div>

View File

@@ -0,0 +1,73 @@
<div {{#if for_realm_settings}}class="privacy_settings settings-subsection-parent" {{else}} id="privacy_settings_box"
{{/if}}>
<div class="subsection-header">
{{#if for_realm_settings}}
<h3 class="settings-subsection-title">{{t "Privacy settings"}}</h3>
{{> settings_save_discard_widget section_name="privacy-setting" show_save_discard_buttons=true }}
{{else}}
<h3 class="settings-subsection-title">{{t "Privacy"}}</h3>
{{> settings_save_discard_widget section_name="privacy-setting" }}
{{/if}}
</div>
{{> settings_checkbox
setting_name="send_private_typing_notifications"
is_checked=settings_object.send_private_typing_notifications
label=settings_label.send_private_typing_notifications
prefix=prefix
}}
{{> settings_checkbox
setting_name="send_stream_typing_notifications"
is_checked=settings_object.send_stream_typing_notifications
label=settings_label.send_stream_typing_notifications
prefix=prefix
}}
{{> settings_checkbox
setting_name="send_read_receipts"
is_checked=settings_object.send_read_receipts
label=settings_label.send_read_receipts
prefix=prefix
help_link="/help/read-receipts"
help_icon_tooltip_text=read_receipts_help_icon_tooltip_text
hide_tooltip=hide_read_receipts_tooltip
}}
{{> settings_checkbox
setting_name="presence_enabled"
is_checked=settings_object.presence_enabled
label=settings_label.presence_enabled
label_parens_text=settings_label.presence_enabled_parens_text
help_link="/help/status-and-availability"
prefix=prefix
}}
{{#unless for_realm_settings}}
{{> settings_checkbox
setting_name="allow_private_data_export"
is_checked=private_data_export_is_checked
is_disabled=private_data_export_is_disabled
tooltip_message=private_data_export_tooltip_text
label=settings_label.allow_private_data_export
help_link="/help/export-your-organization#export-your-organization"
}}
{{/unless}}
<div class="input-group">
<label for="{{prefix}}email_address_visibility" class="settings-field-label">
{{#if for_realm_settings}}
{{t "Who can access user's email address"}}
{{else}}
{{t "Who can access your email address"}}
{{/if}}
{{> ../help_link_widget link="/help/configure-email-visibility" }}
</label>
<div id="user_email_address_dropdown_container"
class="inline-block {{#unless user_has_email_set}}disabled_setting_tooltip{{/unless}}">
<select name="email_address_visibility"
class="email_address_visibility prop-element settings_select bootstrap-focus-style"
data-setting-widget-type="number"
id="{{prefix}}email_address_visibility"
{{#unless user_has_email_set}}disabled="disabled"{{/unless}}>
{{> dropdown_options_widget option_values=(object_values email_address_visibility_values)}}
</select>
</div>
</div>
</div>

View File

@@ -0,0 +1,11 @@
<div class='choice-row movable-row' data-value="{{value}}">
<span class="move-handle {{#if new_empty_choice_row}}invisible{{/if}}">
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</span>
<input type='text' class="modal_text_input" placeholder='{{t "New option" }}' value="{{ text }}" {{#if is_existing_choice}}disabled{{/if}} />
{{#if is_existing_choice}}
{{> ../components/icon_button intent="neutral" custom_classes="edit-choice tippy-zulip-tooltip" icon="edit" data-tippy-content=(t "Making changes to this choice will modify the profiles of the users who've selected it.") aria-label=(t "Edit choice") }}
{{/if}}
{{> ../components/icon_button intent="danger" custom_classes="delete-choice tippy-zulip-delayed-tooltip" hidden=new_empty_choice_row icon="trash" data-tippy-content=(t "Delete") aria-label=(t "Delete") }}
</div>

View File

@@ -0,0 +1,31 @@
<div id="profile-field-settings" class="settings-section" data-name="profile-field-settings">
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Custom profile fields"}}</h3>
<div class="alert-notification" id="admin-profile-field-status"></div>
{{#if is_admin}}
{{> ../components/action_button
id="add-custom-profile-field-button"
label=(t "Add a new profile field")
variant="subtle"
intent="brand"
}}
{{/if}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped admin_profile_fields_table">
<thead>
<tr>
<th>{{t "Label" }}</th>
<th>{{t "Hint" }}</th>
<th>{{t "Type" }}</th>
{{#if is_admin}}
<th class="display">{{t "Card"}}</th>
<th class="required">{{t "Required"}}</th>
<th class="actions">{{t "Actions" }}</th>
{{/if}}
</tr>
</thead>
<tbody id="admin_profile_fields_table" data-empty="{{t 'No custom profile fields configured.' }}"></tbody>
</table>
</div>
</div>

View File

@@ -0,0 +1,82 @@
<div id="profile-settings" class="settings-section" data-name="profile">
<div class="profile-settings-form">
<div class="profile-main-panel inline-block">
<div class="subsection-header">
<h3 id="user-profile-header" class="settings-subsection-title">{{t "Profile" }}</h3>
</div>
<div id="user_details_section">
<div class="full-name-change-container">
<div class="input-group inline-block grid user-name-parent">
<div class="user-name-section inline-block">
<label for="full_name" class="settings-field-label inline-block {{#unless user_can_change_name}}cursor-text{{/unless}}">{{t "Name" }}</label>
<div class="alert-notification full-name-status"></div>
<div class="settings-profile-user-field-hint">{{t "How your account is displayed in Zulip." }}</div>
<div id="full_name_input_container" {{#unless user_can_change_name}}class="disabled_setting_tooltip"{{/unless}}>
<input id="full_name" name="full_name" class="settings_text_input" type="text" value="{{ current_user.full_name }}" {{#unless user_can_change_name}}disabled="disabled"{{/unless}} maxlength="{{max_user_name_length}}" />
</div>
</div>
</div>
</div>
<form class="timezone-setting-form">
<div class="input-group grid">
<label for="user_timezone_widget" class="settings-field-label inline-block">{{t "Time zone" }}</label>
<div class="alert-notification timezone-setting-status"></div>
<div class="timezone-input">
{{> ../dropdown_widget_with_label
widget_name="user_timezone"
label=""
value_type="string"
value=settings_object.timezone
custom_classes="timezone-dropdown-widget"
}}
</div>
</div>
<div id="automatically_offer_update_time_zone_container">
{{> settings_checkbox
setting_name="automatically_offer_update_time_zone"
is_checked=settings_object.web_suggest_update_timezone
label=settings_label.web_suggest_update_timezone
}}
</div>
</form>
<form class="custom-profile-fields-form grid"></form>
</div>
</div>
<div class="profile-side-panel">
<div class="inline-block user-avatar-section">
{{> image_upload_widget
widget = "user-avatar"
upload_text = (t "Upload new profile picture")
delete_text = (t "Delete profile picture")
disabled_text = (t "Avatar changes are disabled in this organization.")
is_editable_by_current_user = user_can_change_avatar
image = current_user.avatar_url_medium}}
<div id="user-avatar-source">
<a href="https://en.gravatar.com/" target="_blank" rel="noopener noreferrer">{{t "Avatar from Gravatar" }}</a>
</div>
</div>
<div class="user-details">
<div id="user_role_details" class="input-group">
<span class="user-details-title">{{t "Role" }}:</span>
<span class="user-details-desc">{{user_role_text}}</span>
</div>
<div class="input-group">
<span class="user-details-title">{{t "Joined" }}: </span>
<span class="user-details-desc">{{date_joined_text}}</span>
</div>
</div>
{{> ../components/action_button
label=(t "Preview profile")
variant="subtle"
intent="brand"
id="show_my_user_profile_modal"
icon="external-link"
aria-hidden="true"
}}
</div>
</div>
</div>

View File

@@ -0,0 +1,14 @@
<div class="input-group admin-realm">
<label for="id_realm_description" class="settings-field-label">
{{t "Organization description" }}
</label>
{{#if is_admin}}
<textarea id="id_realm_description" name="realm_description"
class="admin-realm-description setting-widget prop-element settings-textarea"
maxlength="1000" data-setting-widget-type="string">{{ realm_description_text }}</textarea>
{{else}}
<div class="admin-realm-description settings-view-only-textarea rendered_markdown">
{{rendered_markdown realm_description_html}}
</div>
{{/if}}
</div>

View File

@@ -0,0 +1,31 @@
<table class="table table-stripped" id="realm_domains_table">
<thead>
<tr>
<th>{{t "Domain" }}</th>
<th>{{t "Allow subdomains"}}</th>
<th>{{t "Action" }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr id="add-realm-domain-widget">
<td><input type="text" class="new-realm-domain modal_text_input" placeholder="acme.com" /></td>
<td>
<label class="checkbox">
<input type="checkbox" class="new-realm-domain-allow-subdomains" />
<span class="rendered-checkbox"></span>
</label>
</td>
<td>
{{> ../components/action_button
label=(t "Add")
id="submit-add-realm-domain"
variant="subtle"
intent="brand"
}}
</td>
</tr>
</tfoot>
</table>
<div class="alert realm_domains_info"></div>

View File

@@ -0,0 +1,4 @@
{{#tr}}
Default <z-empty-string-topic-display-name></z-empty-string-topic-display-name> topic configuration for channels
{{#*inline "z-empty-string-topic-display-name"}}<span class="empty-topic-display">{{empty_string_topic_display_name}}</span>{{/inline}}
{{/tr}}

View File

@@ -0,0 +1,80 @@
<tr class="user_row{{#if is_active}} active-user{{else}} deactivated_user{{/if}}" data-user-id="{{user_id}}">
<td class="user_name panel_user_list">
{{> ../user_display_only_pill display_value=full_name user_id=user_id is_bot=true img_src=img_src is_active=is_active is_current_user=false}}
</td>
<td class="email settings-email-column">
<span class="email">{{display_email}}</span>
</td>
<td>
<span class="user_role">{{user_role_text}}</span>
</td>
<td>
<span class="owner panel_user_list">
{{#if no_owner}}
{{bot_owner_full_name}}
{{else}}
{{> ../user_display_only_pill display_value=bot_owner_full_name user_id=bot_owner_id img_src=owner_img_src is_active=is_bot_owner_active}}
{{/if}}
</span>
</td>
<td class="bot_type">
<span class="bot type">{{bot_type}}</span>
</td>
<td class="actions">
<span class="user-status-settings">
{{#if show_download_zuliprc_button}}
<a type="submit" download="zuliprc" data-user-id="{{user_id}}" class="hidden-zuliprc-download" hidden></a>
<span class="tippy-zulip-delayed-tooltip" data-tippy-content="{{t 'Download zuliprc'}}">
{{> ../components/icon_button
icon="download"
intent="neutral"
custom_classes="download-bot-zuliprc-button"
}}
</span>
{{/if}}
{{#if show_generate_integration_url_button}}
<span class="tippy-zulip-delayed-tooltip" data-tippy-content="{{t 'Generate URL for integration'}}">
{{> ../components/icon_button
icon="link-2"
intent="neutral"
custom_classes="generate-integration-url-button"
}}
</span>
{{/if}}
{{#if show_manage_buttons}}
<span class="{{#if cannot_edit}}tippy-zulip-tooltip{{else}}tippy-zulip-delayed-tooltip{{/if}}"
{{#if cannot_edit}}
data-tippy-content="{{t 'This bot cannot be managed.'}}"
{{else}}
data-tippy-content="{{t 'Manage bot'}}"
{{/if}}>
{{> ../components/icon_button
icon="user-cog"
intent="neutral"
custom_classes="open-user-form manage-user-button"
disabled=cannot_edit
}}
</span>
{{#if is_active}}
<span class="deactivate-bot-tooltip {{#if cannot_deactivate}}tippy-zulip-tooltip{{/if}}"
{{#if cannot_deactivate}}data-tippy-content="{{t 'This bot cannot be deactivated.'}}"{{/if}}>
{{> ../components/icon_button
icon="user-x"
intent="danger"
custom_classes="deactivate"
disabled=cannot_deactivate
}}
</span>
{{else}}
<span class="reactivate-bot-tooltip">
{{> ../components/icon_button
icon="user-plus"
intent="success"
custom_classes="reactivate"
}}
</span>
{{/if}}
{{/if}}
</span>
</td>
</tr>

View File

@@ -0,0 +1,24 @@
{{#unless (eq render_only false)}}
<div class="input-group settings-checkbox-wrapper {{#if is_disabled}}control-label-disabled{{/if}}{{#if tooltip_message}} tippy-zulip-tooltip{{/if}}"{{#if tooltip_message}} data-tippy-content="{{tooltip_message}}"{{/if}}>
<label class="checkbox">
<input type="checkbox" class="{{setting_name}} inline-block setting-widget {{#unless skip_prop_element}}prop-element{{/unless}}" name="{{setting_name}}" data-setting-widget-type="boolean"
id="{{#if prefix}}{{prefix}}{{/if}}{{setting_name}}" {{#if is_checked}}checked="checked"{{/if}} {{#if is_disabled}}disabled{{/if}} />
<span class="rendered-checkbox"></span>
</label>
<label for="{{#if prefix}}{{prefix}}{{/if}}{{setting_name}}" class="inline {{setting_name}}_label" id="{{#if prefix}}{{prefix}}{{/if}}{{setting_name}}_label">
{{label}}
{{#if label_parens_text}}
(<i>{{label_parens_text}}</i>)
{{/if}}
{{#if help_link}}
{{> ../help_link_widget link=help_link }}
{{/if}}
{{#if help_icon_tooltip_text}}
<i class="tippy-zulip-tooltip fa fa-info-circle settings-info-icon" {{#if hide_tooltip}}style="display: none;"{{/if}} data-tippy-content="{{help_icon_tooltip_text}}"></i>
{{/if}}
{{#if show_reset_button}}
{{> ../components/icon_button icon="reset" intent="neutral" custom_classes="reset-user-setting-to-default" data-tippy-content=(t "Reset users to default") aria-label=(t "Reset users to default") }}
{{/if}}
</label>
</div>
{{/unless}}

View File

@@ -0,0 +1,18 @@
{{#unless (eq render_only false)}}
<div class="input-group {{#if is_disabled}}control-label-disabled{{/if}}">
<label for="{{#if prefix}}{{prefix}}{{/if}}{{setting_name}}" class="{{setting_name}}_label" id="{{#if prefix}}{{prefix}}{{/if}}{{setting_name}}_label">
{{label}}
{{#if label_parens_text}}
(<i>{{label_parens_text}}</i>)
{{/if}}
{{#if help_link}}
{{> ../help_link_widget link=help_link }}
{{/if}}
{{#if help_icon_tooltip_text}}
<i class="tippy-zulip-tooltip fa fa-info-circle settings-info-icon" {{#if hide_tooltip}}style="display: none;"{{/if}} data-tippy-content="{{help_icon_tooltip_text}}"></i>
{{/if}}
</label>
<input type="text" inputmode="numeric" pattern="\d*" value="{{setting_value}}" class="{{setting_name}} settings_text_input setting-widget prop-element" name="{{setting_name}}" data-setting-widget-type="number"
id="{{#if prefix}}{{prefix}}{{/if}}{{setting_name}}" {{#if is_disabled}}disabled{{/if}} />
</div>
{{/unless}}

View File

@@ -0,0 +1,11 @@
{{#if show_save_discard_buttons}}
<div class="save-button-controls hide">
<div class="inline-block subsection-changes-save">
{{> ../components/action_button custom_classes="save-button" variant="solid" intent="brand" label=(t "Save changes") }}
</div>
<div class="inline-block subsection-changes-discard">
{{> ../components/action_button custom_classes="discard-button" variant="subtle" intent="neutral" label=(t "Discard") }}
</div>
</div>
{{/if}}
<div class="alert-notification {{#if section_name}}{{section_name}}-status{{/if}}"></div>

View File

@@ -0,0 +1,59 @@
<tr class="user_row{{#if is_active}} active-user{{else}} deactivated_user{{/if}}" data-user-id="{{user_id}}">
<td class="user_name panel_user_list">
{{> ../user_display_only_pill display_value=full_name user_id=user_id is_bot=is_bot img_src=img_src is_active=is_active is_current_user=is_current_user}}
</td>
{{#if display_email}}
<td class="email settings-email-column">
<span class="email">{{display_email}}</span>
</td>
{{else}}
<td class="email settings-email-column">
<span class="hidden-email">{{t "(hidden)"}}</span>
</td>
{{/if}}
<td>
<span class="user_role">{{user_role_text}}</span>
</td>
{{#if display_last_active_column}}
<td class="last_active">
{{#if last_active_date}}
{{last_active_date}}
{{else}}
<div class="loading-placeholder"></div>
{{/if}}
</td>
{{/if}}
{{#if can_modify}}
<td class="actions">
<span class="user-status-settings">
<span class="tippy-zulip-delayed-tooltip" data-tippy-content="{{t 'Manage user'}}">
{{> ../components/icon_button
icon="user-cog"
intent="neutral"
custom_classes="open-user-form manage-user-button"
disabled=cannot_edit
}}
</span>
{{#if is_active}}
<span class="deactivate-user-tooltip {{#if cannot_deactivate}}tippy-zulip-tooltip{{/if}}"
{{#if cannot_deactivate}}data-tippy-content="{{t 'This user cannot be deactivated.'}}"{{/if}}>
{{> ../components/icon_button
icon="user-x"
intent="danger"
custom_classes="deactivate"
disabled=cannot_deactivate
}}
</span>
{{else}}
<span class="reactivate-user-tooltip">
{{> ../components/icon_button
icon="user-plus"
intent="success"
custom_classes="reactivate"
}}
</span>
{{/if}}
</span>
</td>
{{/if}}
</tr>

View File

@@ -0,0 +1,22 @@
<tr class="stream-notifications-row" data-stream-id="{{stream.stream_id}}">
<td class="stream-controls">
<span class="stream-privacy-original-color-{{stream.stream_id}} stream-privacy filter-icon" style="color: {{stream.color}}">
{{> ../stream_privacy
invite_only=stream.invite_only
is_web_public=stream.is_web_public }}
</span>
{{stream.stream_name}}
<i class="zulip-icon icon-button-brand zulip-icon-mute tippy-zulip-delayed-tooltip unmute_stream" role="button" tabindex="0" data-tippy-content="{{t 'Unmute' }}" aria-label="{{t 'Unmute' }}" {{#unless muted}}style="display: none;"{{/unless}}></i>
<i class="zulip-icon icon-button-neutral zulip-icon-reset tippy-zulip-delayed-tooltip reset_stream_notifications" role="button" tabindex="0" data-tippy-content="{{t 'Reset to default notifications' }}" aria-label="{{t 'Reset to default notifications' }}"></i>
</td>
{{#each stream_specific_notification_settings}}
{{> notification_settings_checkboxes
setting_name=this
prefix=(lookup ../stream "stream_id")
is_checked=(lookup ../stream this)
is_disabled=(lookup ../is_disabled this)
is_mobile_checkbox=(eq this "push_notifications")
push_notifications_disabled=../push_notifications_disabled
}}
{{/each}}
</tr>

View File

@@ -0,0 +1,7 @@
<div>
{{#unless is_guest}}
{{#unless zulip_plan_is_not_limited}}
<div class="upgrade-organization-banner-container banner-wrapper"></div>
{{/unless}}
{{/unless}}
</div>

View File

@@ -0,0 +1,42 @@
{{#with attachment}}
<tr class="uploaded_file_row" data-attachment-name="{{name}}" data-attachment-id="{{id}}">
<td>
<a type="submit" class="tippy-zulip-delayed-tooltip" href="/user_uploads/{{path_id}}" target="_blank"
rel="noopener noreferrer" data-tippy-content="{{t 'View file' }}">
{{ name }}
</a>
</td>
<td>{{ create_time_str }}</td>
<td>
{{#unless (eq message_ids.length 0)}}
<div class="attachment-messages">
{{#each message_ids}}
<a class="ind-message" href="/#narrow/id/{{ this }}">
#{{ this }}
</a>
{{/each}}
</div>
{{/unless}}
</td>
<td class="upload-size">{{ size_str }}</td>
<td class="actions">
<span class="edit-attachment-buttons">
<a type="submit" href="/user_uploads/{{path_id}}" class="hidden-attachment-download" download></a>
{{> ../components/icon_button
icon="download"
intent="info"
custom_classes="tippy-zulip-delayed-tooltip download-attachment"
data-tippy-content=(t "Download")
}}
</span>
<span class="edit-attachment-buttons">
{{> ../components/icon_button
icon="trash"
custom_classes="tippy-zulip-delayed-tooltip delete remove-attachment"
intent="danger"
data-tippy-content=(t "Delete")
}}
</span>
</td>
</tr>
{{/with}}

View File

@@ -0,0 +1,13 @@
<div id="admin-user-list" class="settings-section" data-name="users">
<div class="tab-container"></div>
{{>active_user_list_admin .}}
{{>imported_user_list_admin .}}
{{>deactivated_users_admin .}}
{{>invites_list_admin .}}
</div>

View File

@@ -0,0 +1,3 @@
<div id="user-notification-settings" class="settings-section" data-name="notifications">
{{> notification_settings . prefix="user_" for_realm_settings=false}}
</div>

View File

@@ -0,0 +1,3 @@
<div id="user-preferences" class="settings-section" data-name="preferences">
{{> preferences . prefix="user_" for_realm_settings=false}}
</div>

View File

@@ -0,0 +1,38 @@
<div id="user-topic-settings" class="settings-section" data-name="topics">
<p>
{{#tr}}
Zulip lets you follow topics you are interested in, and mute topics you want to ignore.
You can also <z-automatically-follow>automatically follow</z-automatically-follow>
topics you start or participate in, and topics where you're mentioned.
{{#*inline "z-automatically-follow"}}<a href="/help/follow-a-topic#automatically-follow-topics" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<div class="settings_panel_list_header">
<h3 class="settings-table-title">{{t "Topic settings"}}
{{> ../help_link_widget link="/help/topic-notifications" }}
</h3>
{{> settings_save_discard_widget section_name="user-topics-settings" }}
{{> filter_text_input id="user_topics_search" placeholder=(t 'Filter') aria_label=(t 'Filter invitations')}}
</div>
<div class="progressive-table-wrapper" data-simplebar data-simplebar-tab-index="-1">
<table class="table table-striped wrapped-table">
<thead class="table-sticky-headers">
<tr>
<th data-sort="alphabetic" data-sort-prop="stream">{{t "Channel" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="alphabetic" data-sort-prop="topic">{{t "Topic" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="numeric" data-sort-prop="visibility_policy">{{t "Status" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
<th data-sort="numeric" data-sort-prop="date_updated" class="active topic_date_updated">{{t "Date updated" }}
<i class="table-sortable-arrow zulip-icon zulip-icon-sort-arrow-down"></i>
</th>
</tr>
</thead>
<tbody id="user_topics_table" data-empty="{{t 'You have not configured any topics yet.'}}" data-search-results-empty="{{t 'No topics match your current filter.' }}"></tbody>
</table>
</div>
</div>