mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
@@ -323,6 +323,10 @@ Source: https://lucide.dev/icons/undo-2
|
||||
Copyright: 2013-2022 Cole Bemis
|
||||
License: ISC License
|
||||
|
||||
Files: web/shared/icons/folder.svg
|
||||
Copyright: 2013-2023 Cole Bemis (https://lucide.dev/icons/folder)
|
||||
License: ISC License
|
||||
|
||||
Files: web/third/bootstrap/css/bootstrap.app.css
|
||||
Copyright: 2012 Twitter, Inc.
|
||||
License: Apache-2.0
|
||||
|
@@ -222,6 +222,7 @@ EXEMPT_FILES = make_set(
|
||||
"web/src/settings_components.ts",
|
||||
"web/src/settings_emoji.ts",
|
||||
"web/src/settings_exports.ts",
|
||||
"web/src/settings_folders.ts",
|
||||
"web/src/settings_invites.ts",
|
||||
"web/src/settings_linkifiers.ts",
|
||||
"web/src/settings_muted_users.ts",
|
||||
|
8
web/shared/icons/folder.svg
Normal file
8
web/shared/icons/folder.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M 4,2 C 2.354992,2 1,3.354992 1,5 v 13 c 0,1.645008 1.354992,3 3,3 h 16 c 1.645008,0 3,-1.354992 3,-3 V 8 C 23,6.354992 21.645008,5 20,5 h -7.900391 a 1.0001,1.0001 0 0 0 -0.0098,0 c -0.341098,0.00334 -0.656154,-0.1643212 -0.84375,-0.4492188 a 1.0001,1.0001 0 0 0 -0.0078,-0.00977 L 10.435547,3.3496094 C 9.8813254,2.5080344 8.937363,2.0001659 7.9296875,2 Z m 0,2 h 3.9296875 c 0.3374958,5.56e-5 0.6503148,0.1673542 0.8359375,0.4492187 a 1.0001,1.0001 0 0 0 0.00586,0.00977 l 0.8027344,1.1914062 c 7.94e-4,0.00121 0.00311,7.486e-4 0.00391,0.00195 C 10.138461,6.5006393 11.092583,7.0099688 12.109375,7 H 20 c 0.564129,0 1,0.4358712 1,1 v 10 c 0,0.564129 -0.435871,1 -1,1 H 4 C 3.4358712,19 3,18.564129 3,18 V 5 C 3,4.4358712 3.4358712,4 4,4 Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 865 B |
@@ -26,7 +26,7 @@ export function initialize(params: StateData["channel_folders"]): void {
|
||||
}
|
||||
|
||||
export function get_channel_folders(include_archived = false): ChannelFolder[] {
|
||||
const channel_folders = [...channel_folder_by_id_dict.values()].sort((a, b) => a.id - b.id);
|
||||
const channel_folders = [...channel_folder_by_id_dict.values()];
|
||||
return channel_folders.filter((channel_folder) => {
|
||||
if (!include_archived && channel_folder.is_archived) {
|
||||
return false;
|
||||
|
@@ -63,6 +63,7 @@ import * as settings_components from "./settings_components.ts";
|
||||
import * as settings_config from "./settings_config.ts";
|
||||
import * as settings_emoji from "./settings_emoji.ts";
|
||||
import * as settings_exports from "./settings_exports.ts";
|
||||
import * as settings_folders from "./settings_folders.ts";
|
||||
import * as settings_invites from "./settings_invites.ts";
|
||||
import * as settings_linkifiers from "./settings_linkifiers.ts";
|
||||
import * as settings_notifications from "./settings_notifications.ts";
|
||||
@@ -122,6 +123,7 @@ export function dispatch_normal_event(event) {
|
||||
case "add": {
|
||||
channel_folders.add(event.channel_folder);
|
||||
inbox_ui.complete_rerender();
|
||||
settings_folders.populate_channel_folders();
|
||||
break;
|
||||
}
|
||||
case "update":
|
||||
|
99
web/src/settings_folders.ts
Normal file
99
web/src/settings_folders.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import $ from "jquery";
|
||||
import SortableJS from "sortablejs";
|
||||
|
||||
import render_admin_channel_folder_list_item from "../templates/settings/admin_channel_folder_list_item.hbs";
|
||||
|
||||
import * as channel from "./channel.ts";
|
||||
import * as channel_folders from "./channel_folders.ts";
|
||||
import * as channel_folders_ui from "./channel_folders_ui.ts";
|
||||
import * as ListWidget from "./list_widget.ts";
|
||||
import * as settings_ui from "./settings_ui.ts";
|
||||
import {current_user} from "./state_data.ts";
|
||||
import * as util from "./util.ts";
|
||||
|
||||
const meta = {
|
||||
loaded: false,
|
||||
};
|
||||
|
||||
function update_folder_order(this: HTMLElement): void {
|
||||
const order: number[] = [];
|
||||
$(".channel-folder-row").each(function () {
|
||||
order.push(Number.parseInt($(this).attr("data-channel-folder-id")!, 10));
|
||||
});
|
||||
settings_ui.do_settings_change(
|
||||
channel.patch,
|
||||
"/json/channel_folders",
|
||||
{order: JSON.stringify(order)},
|
||||
$("#admin-channel-folder-status").expectOne(),
|
||||
);
|
||||
}
|
||||
|
||||
export function do_populate_channel_folders(): void {
|
||||
const folders_data = channel_folders.get_channel_folders();
|
||||
|
||||
const $channel_folders_table = $("#admin_channel_folders_table").expectOne();
|
||||
|
||||
ListWidget.create($channel_folders_table, folders_data, {
|
||||
name: "channel_folders_list",
|
||||
get_item(folder) {
|
||||
return folder;
|
||||
},
|
||||
modifier_html(folder) {
|
||||
return render_admin_channel_folder_list_item({
|
||||
folder_name: folder.name,
|
||||
folder_description: folder.description,
|
||||
id: folder.id,
|
||||
is_admin: current_user.is_admin,
|
||||
});
|
||||
},
|
||||
$parent_container: $("#channel-folder-settings").expectOne(),
|
||||
$simplebar_container: $("#channel-folder-settings .progressive-table-wrapper"),
|
||||
});
|
||||
|
||||
if (current_user.is_admin) {
|
||||
const field_list = util.the($("#admin_channel_folders_table"));
|
||||
SortableJS.create(field_list, {
|
||||
onUpdate: update_folder_order,
|
||||
filter: "input",
|
||||
preventOnFilter: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function populate_channel_folders(): void {
|
||||
if (!meta.loaded) {
|
||||
// If outside callers call us when we're not loaded, just
|
||||
// exit and we'll draw the widgets again during set_up().
|
||||
return;
|
||||
}
|
||||
do_populate_channel_folders();
|
||||
}
|
||||
|
||||
export function set_up(): void {
|
||||
do_populate_channel_folders();
|
||||
meta.loaded = true;
|
||||
|
||||
$("#channel-folder-settings").on(
|
||||
"click",
|
||||
".add-channel-folder-button",
|
||||
channel_folders_ui.add_channel_folder,
|
||||
);
|
||||
$("#channel-folder-settings").on("click", ".edit-channel-folder-button", (e) => {
|
||||
const folder_id = Number.parseInt(
|
||||
$(e.target).closest(".channel-folder-row").attr("data-channel-folder-id")!,
|
||||
10,
|
||||
);
|
||||
channel_folders_ui.handle_editing_channel_folder(folder_id);
|
||||
});
|
||||
$("#channel-folder-settings").on("click", ".archive-channel-folder-button", (e) => {
|
||||
const folder_id = Number.parseInt(
|
||||
$(e.target).closest(".channel-folder-row").attr("data-channel-folder-id")!,
|
||||
10,
|
||||
);
|
||||
channel_folders_ui.handle_archiving_channel_folder(folder_id);
|
||||
});
|
||||
}
|
||||
|
||||
export function reset(): void {
|
||||
meta.loaded = false;
|
||||
}
|
@@ -7,6 +7,7 @@ import * as settings_account from "./settings_account.ts";
|
||||
import * as settings_bots from "./settings_bots.ts";
|
||||
import * as settings_emoji from "./settings_emoji.ts";
|
||||
import * as settings_exports from "./settings_exports.ts";
|
||||
import * as settings_folders from "./settings_folders.ts";
|
||||
import * as settings_invites from "./settings_invites.ts";
|
||||
import * as settings_linkifiers from "./settings_linkifiers.ts";
|
||||
import * as settings_muted_users from "./settings_muted_users.ts";
|
||||
@@ -78,6 +79,7 @@ export function initialize(): void {
|
||||
"organization-level-user-defaults",
|
||||
settings_realm_user_settings_defaults.set_up,
|
||||
);
|
||||
load_func_dict.set("channel-folders", settings_folders.set_up);
|
||||
}
|
||||
|
||||
export function load_settings_section(section: string): void {
|
||||
@@ -115,5 +117,6 @@ export function reset_sections(): void {
|
||||
settings_user_topics.reset();
|
||||
settings_muted_users.reset();
|
||||
alert_words_ui.reset();
|
||||
settings_folders.reset();
|
||||
// settings_users doesn't need a reset()
|
||||
}
|
||||
|
@@ -902,7 +902,8 @@ input[type="checkbox"] {
|
||||
.admin_profile_fields_table,
|
||||
.edit_profile_field_choices_container,
|
||||
.profile_field_choices_table,
|
||||
.admin_linkifiers_table {
|
||||
.admin_linkifiers_table,
|
||||
.admin_channel_folders_table {
|
||||
.movable-row {
|
||||
.move-handle {
|
||||
cursor: move;
|
||||
|
31
web/templates/settings/admin_channel_folder_list_item.hbs
Normal file
31
web/templates/settings/admin_channel_folder_list_item.hbs
Normal file
@@ -0,0 +1,31 @@
|
||||
<tr class="channel-folder-row movable-row" data-channel-folder-id="{{id}}">
|
||||
<td class="channel_folder_name_container">
|
||||
{{#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 class="channel_folder_description_container">
|
||||
<span class="channel_folder_description">{{folder_description}}</span>
|
||||
</td>
|
||||
{{#if is_admin}}
|
||||
<td class="actions">
|
||||
{{> ../components/icon_button
|
||||
icon="edit"
|
||||
intent="neutral"
|
||||
custom_classes="tippy-zulip-delayed-tooltip edit-channel-folder-button"
|
||||
data-tippy-content=(t "Edit")
|
||||
}}
|
||||
{{> ../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>
|
||||
{{/if}}
|
||||
</tr>
|
28
web/templates/settings/admin_channel_folders.hbs
Normal file
28
web/templates/settings/admin_channel_folders.hbs
Normal file
@@ -0,0 +1,28 @@
|
||||
<div id="channel-folder-settings" class="settings-section" data-name="channel-folders">
|
||||
<div class="settings_panel_list_header">
|
||||
<h3>{{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")
|
||||
attention="quiet"
|
||||
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>
|
||||
{{#if is_admin}}
|
||||
<th class="actions">{{t "Actions" }}</th>
|
||||
{{/if}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="admin_channel_folders_table" data-empty="{{t 'No channel folders configured.' }}"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
@@ -17,6 +17,8 @@
|
||||
|
||||
{{> bot_list_admin . }}
|
||||
|
||||
{{> admin_channel_folders .}}
|
||||
|
||||
{{> default_streams_list_admin . }}
|
||||
|
||||
{{> auth_methods_settings_admin . }}
|
||||
|
@@ -109,6 +109,11 @@
|
||||
<div class="text">{{t "Default user settings" }}</div>
|
||||
<i class="locked fa fa-lock tippy-zulip-tooltip" {{#if is_admin}}style="display: none;"{{/if}} data-tippy-content="{{t 'Only organization administrators can edit these settings.' }}"></i>
|
||||
</li>
|
||||
<li class="sidebar-item collapse-org-settings {{#unless is_admin}}hide-org-settings{{/unless}}" tabindex="0" data-section="channel-folders">
|
||||
<i class="sidebar-item-icon zulip-icon zulip-icon-folder"></i>
|
||||
<div class="text">{{t "Channel folders" }}</div>
|
||||
<i class="locked fa fa-lock tippy-zulip-tooltip" {{#if is_admin}}style="display: none;"{{/if}} data-tippy-content="{{t 'Only organization administrators can edit these settings.' }}"></i>
|
||||
</li>
|
||||
{{#unless is_guest}}
|
||||
<li class="sidebar-item collapse-org-settings {{#unless is_admin}}hide-org-settings{{/unless}}" tabindex="0" data-section="default-channels-list">
|
||||
<i class="sidebar-item-icon fa fa-exchange" aria-hidden="true"></i>
|
||||
|
Reference in New Issue
Block a user