[pull] master from mattermost:master - #954
Merged
Merged
Conversation
i18n-ci-template.yml existed to fail any PR that touched a non-English translation file unless it came from the weblate account, back when translations arrived exclusively through Weblate. Translations can now be authored in-repo and land in the same PR as the English string they translate, so that gate rejects exactly the change it should be letting through. The changed-file detection stays -- a direct edit to a locale catalog is still worth surfacing on the PR -- but it emits a warning annotation instead of failing, and the weblate-account bypass is gone with nothing left to bypass.
…add/remove on Save (#38056) * [MM-69866] Add Applies-to resource picker (Users, Channels, Posts) to New attribute Adds an "Applies to" Card to the Global Attributes "New attribute" page, letting a sysadmin pick which resources (Users, Channels, Posts) an attribute applies to before saving. Each selected resource becomes its own linked PropertyField, created serially after the template so a partial failure can be attributed to a specific resource and rolled back deterministically (linked fields deleted before the template, per the server's deletion-order protection). A `user`-scoped linked field shares its namespace with Custom Profile Attributes, so name conflicts and the shared 20-field cap are newly reachable failure modes -- both get distinct, actionable banners instead of a generic failure message. Client-only change; no server, migration, or Client4 changes required. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Split the Applies-to row into one component per resource type Replaces the single resourceType-parameterized AttributeAppliesToItem with three dedicated components (User/Channel/Post), each hardcoding its own icon, label, and testids instead of looking them up by a prop. All three share one prop signature (AttributeAppliesToItemProps, exported from attribute_applies_to_constants.tsx) so the parent's Record<ResourceObjectType, ComponentType<...>> lookup map fails to compile if any of the three drift from it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix Prettier formatting in the global_attributes E2E files npm run check for e2e-tests/playwright runs lint && prettier && tsc, and CI's prettier --check step was failing on both files -- they'd only been checked against webapp's ESLint config locally, not this package's Prettier config. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Move the Applies-to row's Remove action into the expanded state The collapsed row no longer has any remove affordance -- the only way to remove a resource is to expand it first, then click "Remove resource" in the header (still a sibling of the toggle, not nested inside its clickable area). Styled per the design prototype: a plain text button, transparent by default, --error-text colored, with a rgba(--error-text-color-rgb, 0.08) hover tint -- the same pattern already used by OrphanedFieldDeleteButton (system_properties) rather than a new one-off style. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Add 12px right margin to the Applies-to row's Remove button Matches the design prototype's spacing between the button and the row's right edge. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Rename applies-to constants file to .ts The file has no JSX, so the .tsx extension was misleading. * Polish the Applies-to card empty state and expanded rows Match the design: updated copy and type, primary/tertiary add buttons, header-only open tint, and a 176px form row in the expanded body. * Drop bottom padding on the last Applies-to body row It stacked with the container padding and looked doubled. * Size Unique name label, value, and Edit to 12px The caption and Edit link were 14px against a 12px label; shrink the edit input to match. * Treat Unique name click-away as Done Opening Edit then clicking away left the input open and froze auto-derivation. Blur now uses the same commit path as Done, matching the channel URL field. * Lock Type to Text while an external source is linked LDAP and SAML only sync on text fields; disabling the type menu until the last chip is removed keeps that invariant in the UI. * Show linked sources on the Options line as Synced with chips Once a source is selected the chips replace the Text help copy; the divider stays until then so the unlinked state still separates Options from the add-source trigger. * Order flex container properties to satisfy stylelint. * Show CPA banners only for Users and copy leftover-template rollback. Channels and Posts name conflicts used User Attribute wording, and a leftover template after a linked-field rollback looked like a clean save. E2E cleanup now rediscovers template and linked fields instead of relying on the success-path list. * Use Compass Button for Applies-to row chrome. Override quaternary styling so the accordion header stays body-text chrome, and keep Remove as tertiary destructive. * Await hanging creates before unmount-save negative asserts. waitFor(() => Promise.resolve()) returns on the first check and can pass before finalizeSave, so the mount guard was not actually load-bearing. * Drop unused PropertyField and ResourceObjectType imports from the Playwright spec. * [MM-69864][MM-69870] Edit existing attributes and persist Applies-to add/remove on Save Open the Definition form for managed attributes, PATCH on Save, and keep Applies-to add/remove local until Save diffs against the linked fields loaded at mount. Co-authored-by: Julien Tant <JulienTant@users.noreply.github.com> * Wait for deferred Edit navigation in listing tests and satisfy no-negated-condition. Co-authored-by: Julien Tant <JulienTant@users.noreply.github.com> * Format Playwright global attributes edit tests with Prettier. Co-authored-by: Julien Tant <JulienTant@users.noreply.github.com> * Split Global Attributes Playwright specs into listing and form files. Flag-off access-gate coverage stays in the listing spec so the form spec never turns GlobalAttributes off. Co-authored-by: Julien Tant <JulienTant@users.noreply.github.com> * Use dedicated type-lock tooltip copy and skip Applies-to focus on edit hydrate. The external-source lock was showing the accessible name as a tooltip. Edit hydration of all three resource types was treated as adding the last type and stole Display name autofocus. Co-authored-by: Julien Tant <JulienTant@users.noreply.github.com> * Fix Applies-to removal data-loss and lock Name while resources are linked. Addresses review feedback: Save deleted removed linked fields before PATCHing the template, so a PATCH failure unrelated to type (e.g. a name conflict) still lost every value on the removed resource. Save now orders DELETE/PATCH based on whether the type actually changed -- PATCH first when it didn't, so a failure aborts before anything is deleted -- and warns with a confirmation dialog before removing any resource with a persisted linked field. Also locks Unique name editing while a linked field is still persisted, since the server does not propagate a rename onto it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Report partial-save, not "nothing else was saved", when the removal DELETE fails after a successful PATCH. deleteRemovedLinkedFields is called both before and after the template PATCH depending on typeChanged, but reused the same error copy for both -- "nothing else was saved" is only true for the before-PATCH case. Give the after-PATCH case its own applies_to_remove_partial_save error kind/message so the banner doesn't contradict the update that actually went through. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Disable linking a new external source while an attribute still applies to a resource * Fix Unique name silently unpinning after a no-op Edit/Done round-trip in edit mode. handleDoneClick's "did the committed value change from the current auto-slug" heuristic is correct for create mode (a coincidental match keeps live derivation on) but was also applying in edit mode, where the loaded name must stay pinned regardless. When the persisted name happened to equal the current auto-slug, opening Edit and clicking Done with no real change would unpin it, and the next Display name edit would silently re-slug the Unique name out from under the admin. Reported by Lindy on the PR. Adds Jest and Playwright regression coverage; verified the Playwright tests reproduce the exact symptom when the fix is reverted. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Mattermost Build <build@mattermost.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Julien Tant <JulienTant@users.noreply.github.com>
* webapp: remove string refs from the file preview and multiselect lists String refs are rejected under StrictMode. Neither of these was read: the file preview row is looked up through its data-client-id attribute, and the multiselect list only needs a ref on the selected row. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit 0c718a4) * webapp: remove the remaining string refs from selector modal rows Each of these list rows fell back to a string ref for the unselected case, which strict mode reports because string refs can't be attached twice and don't survive a render being restarted. The unselected row never needs a ref, and nothing read the one AddUsersToRoleModal was setting. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit e727ac0) --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
…-dom (#38240) * webapp: stop bundling a second copy of react-dom into @mattermost/components react-dom is only a devDependency of the package, so rollup inlined the whole renderer (both the development and production builds) into dist/index.esm.js rather than treating it as external. The web app therefore loaded two react-dom instances: the shared singleton, and the one TourTipBackdrop's createPortal call pulled in. Two renderers sharing one tree is a hazard under concurrent rendering, and the duplicate also cost 1.2MB of bundle. dist/index.esm.js drops from 1,264,396 to 83,919 bytes. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit 9d42d25) * webapp: take react-bootstrap's unsafe lifecycle fix TabContent used UNSAFE_componentWillReceiveProps and Dropdown used UNSAFE_componentWillUpdate. React reports both under StrictMode, and neither is safe to interrupt under concurrent rendering. Every tab strip in the web app mounts TabContent, so this reached the emoji picker, drafts, scheduled posts and the admin console. The fix is mattermost/react-bootstrap#14. TabContent's only job in that lifecycle was clearing animation bookkeeping when animation is turned off, which is derived state, and Dropdown reads focus out of the DOM before the menu is removed, which is what getSnapshotBeforeUpdate exists for. Both workspaces that depend on react-bootstrap have to move together. Pinning only channels leaves platform/components on the old commit, which stops npm hoisting the two into one copy and puts a second, unfixed copy in the tree. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> * webapp: repin react-bootstrap to the merged commit mattermost/react-bootstrap#14 landed on 0.34 as a squash merge, d693ec8. The branch was pinned to 797ff61, the pull request head, which is now unreachable from any branch there and will disappear whenever the fork is pruned. Content is unchanged: 797ff61 and d693ec8 share the tree e029175 and the parent c177015, so the lockfile's integrity hash is untouched. Only the resolved commit moves, in both workspaces that depend on react-bootstrap. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* webapp: stop react-transition-group from calling findDOMNode Every CSSTransition and Transition in the web app was rendered without a nodeRef, so react-transition-group looked its DOM node up with findDOMNode. React 18 warns about that under StrictMode and React 19 removes the API entirely. Where the transitioning element was already ours, the existing ref is reused. MenuWrapperAnimation and the mobile right drawer animate arbitrary children, so those gained a wrapper element to hang the ref on; both wrappers are static boxes, so the positioned content inside them is unaffected. Passing nodeRef also changes the transition callback signature: the node is no longer the first argument, so AutoHeightSwitcher reads it from its own ref. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit d8ef488) * webapp: update snapshots for the menu animation wrapper Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit c16e038) --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
… safe to remount (#38239) * webapp: let PerformanceReporterController be unmounted The effect assumed the component would never unmount and logged an error if it did, so it had no cleanup. React re-runs effects on every mount, and StrictMode mounts twice on purpose, which left an orphaned PerformanceReporter behind on every page load: a PerformanceObserver still observing, a report timer still running, and a visibilitychange listener still attached, all duplicating the telemetry the live reporter sends. The reporter now disconnects on cleanup and ignores web vitals afterwards, since web-vitals callbacks can't be unregistered. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit 8587f31) * webapp: replace UNSAFE_componentWillReceiveProps in PermissionSystemSchemeSettings The last unsafe lifecycle left in the web app, and the one StrictMode reports when the system scheme page is opened. componentWillReceiveProps runs during the render phase, so an interrupted render can invoke it more than once per commit; the equivalent check in componentDidUpdate runs once, after the commit. Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com> (cherry picked from commit 68f324d) --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Load sidebar DM/GM profiles once channels have loaded * Add e2e coverage for sidebar DM/GM profiles on load * Revert "Load sidebar DM/GM profiles once channels have loaded" This reverts commit b562945. * Gate sidebar profile loading on the channels and memberships too * Fix sidebar profile initialization load race * Batch the initial sidebar load flags with their data --------- Co-authored-by: Mattermost Build <build@mattermost.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )