diff --git a/static/js/hash_util.js b/static/js/hash_util.js index a512eb8b46..333a40a524 100644 --- a/static/js/hash_util.js +++ b/static/js/hash_util.js @@ -153,6 +153,11 @@ export function stream_edit_url(sub) { return hash; } +export function group_edit_url(group) { + const hash = `#groups/${group.id}/${internal_url.encodeHashComponent(group.name)}`; + return hash; +} + export function search_public_streams_notice_url(operators) { const public_operator = {operator: "streams", operand: "public"}; return operators_to_hash([public_operator].concat(operators)); diff --git a/static/js/ui_init.js b/static/js/ui_init.js index 1718e983e5..3c8cdea671 100644 --- a/static/js/ui_init.js +++ b/static/js/ui_init.js @@ -98,6 +98,7 @@ import * as typing from "./typing"; import * as ui from "./ui"; import * as unread from "./unread"; import * as unread_ui from "./unread_ui"; +import * as user_group_edit from "./user_group_edit"; import * as user_groups from "./user_groups"; import * as user_group_settings_ui from "./user_groups_settings_ui"; import {initialize_user_settings, user_settings} from "./user_settings"; @@ -618,6 +619,7 @@ export function initialize_everything() { initialize_kitchen_sink_stuff(); echo.initialize(); stream_edit.initialize(); + user_group_edit.initialize(); stream_edit_subscribers.initialize(); stream_data.initialize(stream_data_params); pm_conversations.recent.initialize(pm_conversations_params); diff --git a/static/js/user_group_edit.js b/static/js/user_group_edit.js new file mode 100644 index 0000000000..f5209b6d1a --- /dev/null +++ b/static/js/user_group_edit.js @@ -0,0 +1,115 @@ +import $ from "jquery"; + +import render_user_group_settings from "../templates/user_group_settings/user_group_settings.hbs"; + +import * as blueslip from "./blueslip"; +import * as browser_history from "./browser_history"; +import * as components from "./components"; +import * as hash_util from "./hash_util"; +import {$t} from "./i18n"; +import {page_params} from "./page_params"; +import * as people from "./people"; +import * as settings_data from "./settings_data"; +import * as ui from "./ui"; +import * as user_group_ui_updates from "./user_group_ui_updates"; +import * as user_groups from "./user_groups"; +import * as user_group_settings_ui from "./user_groups_settings_ui"; + +export let toggler; +export let select_tab = "group_general_settings"; + +function setup_group_edit_hash(group) { + const hash = hash_util.group_edit_url(group); + browser_history.update(hash); +} + +function get_user_group_id(target) { + const $row = $(target).closest(".group-row"); + return Number.parseInt($row.attr("data-group-id"), 10); +} + +function get_user_group_for_target(target) { + const user_group_id = get_user_group_id(target); + if (!user_group_id) { + blueslip.error("Cannot find user group id for target"); + return undefined; + } + + const group = user_groups.get_user_group_from_id(user_group_id); + if (!group) { + blueslip.error("get_user_group_for_target() failed id lookup: " + user_group_id); + return undefined; + } + return group; +} + +export function can_edit(group_id) { + if (!settings_data.user_can_edit_user_groups()) { + return false; + } + + // Admins and moderators are allowed to edit user groups even if they + // are not a member of that user group. Members can edit user groups + // only if they belong to that group. + if (page_params.is_admin || page_params.is_moderator) { + return true; + } + + return user_groups.is_direct_member_of(people.my_current_user_id(), group_id); +} + +export function get_edit_container(group) { + return $(`#groups_overlay .user_group_settings[data-group-id='${CSS.escape(group.id)}']`); +} + +export function show_settings_for(node) { + const group = get_user_group_for_target(node); + const html = render_user_group_settings({ + group, + can_edit: can_edit(group.id), + }); + + ui.get_content_element($("#user_group_settings")).html(html); + user_group_ui_updates.update_toggler_for_group_setting(group); + + $("#user_group_settings .tab-container").prepend(toggler.get()); + const $edit_container = get_edit_container(group); + $(".nothing-selected").hide(); + + $edit_container.addClass("show"); +} + +export function setup_group_settings(node) { + toggler = components.toggle({ + child_wants_focus: true, + values: [ + {label: $t({defaultMessage: "General"}), key: "group_general_settings"}, + {label: $t({defaultMessage: "Members"}), key: "group_member_settings"}, + ], + callback(name, key) { + $(".group_setting_section").hide(); + $("." + key).show(); + select_tab = key; + }, + }); + + show_settings_for(node); +} + +export function open_group_edit_panel_for_row(group_row) { + const group = get_user_group_for_target(group_row); + + $(".group-row.active").removeClass("active"); + user_group_settings_ui.show_user_group_settings_pane.settings(group); + $(group_row).addClass("active"); + setup_group_edit_hash(group); + setup_group_settings(group_row); +} + +export function initialize() { + $("#manage_groups_container").on("click", ".group-row", function (e) { + if ($(e.target).closest(".check, .user_group_settings_wrapper").length === 0) { + open_group_edit_panel_for_row(this); + } + }); +} diff --git a/static/js/user_group_ui_updates.js b/static/js/user_group_ui_updates.js new file mode 100644 index 0000000000..9b8777423a --- /dev/null +++ b/static/js/user_group_ui_updates.js @@ -0,0 +1,7 @@ +import * as user_group_edit from "./user_group_edit"; + +// This module will handle ui updates logic for group settings, +// and is analogous to stream_ui_updates.js for stream settings. +export function update_toggler_for_group_setting() { + user_group_edit.toggler.goto(user_group_edit.select_tab); +} diff --git a/static/js/user_groups_settings_ui.js b/static/js/user_groups_settings_ui.js index e633b6088a..9addebe4b1 100644 --- a/static/js/user_groups_settings_ui.js +++ b/static/js/user_groups_settings_ui.js @@ -35,6 +35,11 @@ export const show_user_group_settings_pane = { $t({defaultMessage: "User group settings"}), ); }, + settings(group) { + $(".settings, #user-group-creation").hide(); + $("#groups_overlay .settings").show(); + $("#groups_overlay .user-group-info-title").text(group.name); + }, create_user_group() { $(".nothing-selected, .settings, #user-group-creation").hide(); $("#user-group-creation").show(); diff --git a/static/styles/dark_theme.css b/static/styles/dark_theme.css index 99243257a0..6db7c096df 100644 --- a/static/styles/dark_theme.css +++ b/static/styles/dark_theme.css @@ -573,6 +573,7 @@ body.dark-theme { border-top: none; } + .group-row.active, .stream-row.active, .emoji-info-popover .emoji-showcase-container, .emoji-info-popover .emoji-popover .emoji-popover-category-tabs, diff --git a/static/templates/user_group_settings/user_group_settings.hbs b/static/templates/user_group_settings/user_group_settings.hbs new file mode 100644 index 0000000000..2f04d20c04 --- /dev/null +++ b/static/templates/user_group_settings/user_group_settings.hbs @@ -0,0 +1,15 @@ +
+
+
+
+
+ +
+ General group settings. +
+ +
+ Group member settings. +
+
+
diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 148009154f..b31fa34d90 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -203,6 +203,8 @@ EXEMPT_FILES = make_set( "static/js/user_group_create.js", "static/js/user_group_create_members.js", "static/js/user_group_create_members_data.js", + "static/js/user_group_edit.js", + "static/js/user_group_ui_updates.js", "static/js/user_groups_settings_ui.js", "static/js/user_profile.js", "static/js/user_settings.ts",