mirror of
https://github.com/hanzoai/team.git
synced 2026-09-30 01:57:35 +00:00
* Add discoverable private channels request-to-join UX Let users mark private channels discoverable, find them in Browse Channels, submit and withdraw join requests, and track status via My pending requests instead of DM notifications. * Drop unrelated server changes from the branch Restore server files to master; this PR is webapp-only and builds on the existing discoverable-channels server implementation. * Close Request to Join modal immediately on submit Drop the in-modal pending state so the modal closes as soon as the request is sent, rather than flipping into a "sent / Withdraw" view before disappearing. Browse Channels rows already handle the post-send state (Requested pill + Withdraw), so the modal's pending branch was redundant and visually noisy. * Fix lint in channel_settings_info_tab test Split multi-prop JSX onto separate lines and remove the trailing blank line inside the Discoverable toggle describe block. Resolves the react/jsx-max-props-per-line and padded-blocks errors that were failing check-lint and cascading into a skipped build / failed Spinwick. * Fix stylelint property order in request_join_channel_modal SCSS Move min-width before align-items in .RequestJoinChannelModal__header to satisfy stylelint's order/properties-order rule (dimensions before flex alignment). * Restore unintended deletions from original branch commit The initial PR commit accidentally reverted master-side changes in several shared files when the AI agent regenerated them. The rebase onto current master preserved those reverts. Restore each piece while keeping the branch's discoverable additions: - client4.ts: previewLicense method - websocket_actions.ts: handleFileUploadRejected function + switch case - websocket_message.ts / websocket_messages.ts: FileUploadRejected type - config.ts: License type fields (expires_at, customer required, sku_short_name, is_gov_sku) - constants.tsx: CHANNEL_MENTION_AUTO_FOLLOW notification section - en.json: master keys (admin.license.*, admin.access_control.*, etc.) restored; discoverable keys re-inserted using the Mattermost i18n formatter sort rule (case-insensitive, '_' before '.') - package-lock.json: reset to master * Sync webapp package-lock.json with master to fix CI install The branch carried a stale package-lock.json pinning [email protected].0 while package.json (identical to master) declares [email protected].4. npm aborted with an ERESOLVE peer conflict (@typescript-eslint/[email protected].0 peers eslint@^8.56.0), failing check-lint and the E2E check before any code ran. This branch adds no dependencies, so the lockfile is restored to match master. * Fix join-request pending count double-decrement and prune stale pending map Decrement countsByChannel from the actual pending->terminal transition instead of the incoming status alone, so the acting admin's optimistic dispatch plus the server's WebSocket echo of a single approve/deny no longer double-decrements the badge. Make CREATED count-idempotent for re-delivered events. Rebuild myPendingByChannel from the authoritative full list on RECEIVED_MY_CHANNEL_JOIN_REQUESTS so a request that resolved while the client missed the WS event no longer lingers as stale. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Surface discoverable channels in Browse without requiring a search getChannels only returns public channels, so non-member discoverable private channels (and the Discoverable filter) were empty until the user typed a search term. Fetch them on mount via an empty-term non-admin search (already ABAC-filtered server-side), fold them into the default All list and the Discoverable filter, and resolve My pending requests rows against them. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Browse row cleanup: drop unused action, keep Withdraw if discoverability revoked Remove the requestJoinChannel action that was wired into Browse Channels but never called (the confirmation modal dispatches it directly). Show the Withdraw affordance for any non-member with an open request even after an admin flips the channel's discoverable flag off, instead of falling through to a Join button the server rejects for a private channel. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Fix discoverable-toggle a11y labels and gate settings toggle on in-progress type - Description <label>s reused aria-label={discoverableTitle}, so screen readers announced the title twice and skipped the description; point them at discoverableDescription (channel settings + new channel modal). - Gate the channel-settings discoverable toggle on the in-progress channelType selection rather than the saved channel.type, so it appears immediately during a Public->Private conversion, matching the New Channel modal. The save flow already applies the privacy conversion before the discoverable patch. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Guard Browse request/withdraw re-entry and make Withdraw keyboard-accessible Ignore row clicks that would re-trigger request/withdraw while one is already in flight (the row bypassed the disabled button), and disable the buttons whenever any request/withdrawal is pending. Drop tabIndex={-1} from the Withdraw button: pending rows are a no-op on Enter, so the button was the only action and needed to stay keyboard-focusable. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Persist untracked join-request updates so duplicate terminal events stay idempotent When a terminal CHANNEL_JOIN_REQUEST_UPDATED arrives for a row not yet in byChannel (only the count was loaded), store it instead of leaving the list unchanged. A re-delivered terminal event then finds it as terminal and no longer decrements countsByChannel a second time. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Memoize filtered pending join-request selectors getPendingChannelJoinRequests and getMyPendingJoinRequestList ran an unmemoized .filter() on every call, returning a new array reference each time and causing avoidable re-renders in any connected consumer. Wrap both in createSelector. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Address review: drop redundant done() guards and harden withdraw error message done is a required callback, so the if (done) guards in handleRequestToJoin and handleWithdrawRequest were dead. Fall back to server_error_id / a generic string when the withdraw error has no message, since error.message isn't guaranteed at runtime. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Address review: use a class for the discoverable row indicator The indicator rendered id='discoverableIndicatorContainer' on every discoverable row, producing duplicate ids in the DOM when more than one discoverable channel is listed. Switch it to a class (and update the SCSS selector + test) so the markup stays valid. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Add discoverable private channels admin join-request queue UX (#37082) QA deferred to the base branch * Fix Quick Switch join flow for discoverable channels in recent/default lists (MM-68764) The discoverableNonMember / hasPendingJoinRequest flags were only set on Quick Switch search results, so a discoverable private channel surfaced via the Recent or default (no-search-term) list fell through to the legacy private-channel join confirmation, which the server rejects for a non-member — leaving the user in a broken confirm/error loop. Extract the detection into a shared applyDiscoverableFlags helper and run it on every channel-list path (search via formatGroup, recent + unread via wrapChannels) so the Request to Join flow fires consistently. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Bound concurrency of sidebar join-request count prefetch Address CodeRabbit: the effect fired one count request per manageable discoverable channel simultaneously. Process them in capped batches (5 at a time) and cancel in-flight work on unmount / dependency change so a user who manages many channels doesn't trigger an unbounded request burst. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Add ChannelHeader snapshot test for pending join requests Address CodeRabbit: cover the join-request badge's conditional rendering with a hasPendingJoinRequests=true snapshot case. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Add e2e tests for discoverable private channels request-to-join UX Cover common use cases behind the DiscoverableChannels feature flag: a non-member requesting to join a discoverable private channel from Browse Channels and withdrawing, and selecting a discoverable channel from Find Channels (Cmd+K) routing to the Request to Join modal rather than the legacy join. Add supporting Browse Channels modal page-object helpers. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Address review: locate Browse Channels rows by display name in e2e helpers Per the Playwright suite conventions, filter rows by visible display name (.more-modal__row + hasText) instead of data-testid, and pass channel.display_name from the spec. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Reveal Browse Channels row actions on keyboard focus (:focus-within) Address review: the Withdraw button is keyboard-focusable (tabIndex removed earlier) but the row action buttons are visibility:hidden and only revealed on :hover / row :focus. Tabbing to the Withdraw button moves focus off the row, so the buttons hid again. Add :focus-within so the actions stay visible while any child button holds keyboard focus. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> * Route discoverable channel URL / mention-link navigation to Request to Join Address review: opening a discoverable private channel a user isn't a member of via a pasted channel URL or a ~channel mention link fired the legacy 'Join private channel' confirmation, which attempts a direct join the server rejects, leaving the user on a broken channel view. When the feature flag is on and the channel is discoverable, redirect to a safe channel and open the Request to Join modal instead — matching Browse Channels and Quick Switch. Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> --------- Co-authored-by: Ibrahim Serdar Acikgoz <[email protected]> Co-authored-by: Mattermost Build <[email protected]> Co-authored-by: Hanzo Dev <[email protected]>