* chore: Replace lodash with es-toolkit
Migrate all direct lodash imports to es-toolkit/compat for a smaller,
faster, lodash-compatible utility library. Transitive lodash usage from
other packages remains unchanged.
* fix: Restore isPlainObject semantics in CanCan policy
The lodash migration aliased `isObject` to `lodash/isPlainObject` and
the codemod incorrectly mapped the local name to es-toolkit's `isObject`,
which also returns true for arrays and functions. This caused condition
objects in policy definitions to be skipped, breaking authorization
checks across the codebase.
* fix: Restore unicode-aware length counting in validators
es-toolkit/compat's size() returns string.length, while lodash's _.size()
counts unicode code points. Switch to [...value].length to preserve the
previous behavior so multi-byte characters like emoji count as one.
* Update Switch component onChange handler to use boolean callback
- Remove synthetic event handling from Switch component
- Update onChange signature to (checked: boolean) => void
- Update all call points across the codebase:
- PublicAccess.tsx: Updated handlers for indexing, showLastModified, and published switches
- Security.tsx: Created individual handlers for all security preferences
- Preferences.tsx: Created individual handlers for user preferences
- CollectionForm.tsx: Added createSwitchRegister helper for react-hook-form compatibility
- TemplatizeDialog: Updated publish handler
- DocumentMenu.tsx: Added handlers for embeds and full-width toggles
- Search.tsx: Updated SearchTitlesFilter handler
- Application.tsx: Added createSwitchRegister helper
- Details.tsx: Updated public branding handler
- Features.tsx: Created individual handlers for seamless edit and commenting
- OAuthClientForm.tsx: Added createSwitchRegister helper
- Maintained backward compatibility with react-hook-form
- Improved type safety and code clarity
* Fix ESLint floating promise errors
- Add void operator to onChange call in CollectionForm.tsx
- Add void operator to document.save call in DocumentMenu.tsx
These changes fix the @typescript-eslint/no-floating-promises errors
while maintaining the existing functionality.
* Fix Switch component onChange handlers in remaining files
- Updated DocumentCopy.tsx handlers to use boolean parameter
- Updated Notifications.tsx to use closure pattern for event types
- Updated SlackListItem.tsx to use closure pattern for event names
- All TypeScript errors resolved
* Refactor createSwitchRegister into utils/forms
- Created shared utility function in app/utils/forms.ts
- Removed duplicate implementations from CollectionForm, Application, and OAuthClientForm
- Updated all usage points to use the shared utility
- Improved TypeScript typing with Record<string, unknown>
- Fixed imports and removed unused variables
- Maintained existing functionality while reducing code duplication
* Fix TypeScript errors in createSwitchRegister utility
- Updated generic constraint from Record<string, unknown> to FieldValues
- Added Path import from react-hook-form for proper type safety
- Fixed parameter type from keyof TFormData to Path<TFormData>
- Improved type compatibility with react-hook-form's UseFormRegister
Resolves TypeScript compilation errors in CI pipeline.
* Remove unnecessary handlePublishChange callbacks
- Removed handlePublishChange wrapper in DocumentCopy.tsx
- Removed handlePublishChange wrapper in TemplatizeDialog/index.tsx
- Updated Switch components to use setPublish directly
- Simplified code by leveraging boolean callback from Switch component
Since Switch now passes boolean directly, no need for intermediate callbacks.
* Address review feedback: simplify callbacks and fix fullWidth behavior
1. DocumentCopy.tsx:
- Remove handleRecursiveChange callback wrapper
- Use setRecursive directly with Switch component
2. DocumentMenu.tsx:
- Add void user.save() to persist user preference
- Add document.fullWidth = checked for optimistic update behavior
Both changes leverage the boolean callback from Switch component properly.
* Update Security.tsx
* i18n
---------
Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom@getoutline.com>
* Iteration, before functional component
* Use react-hook-form, shared form for new and edit
* Avoid negative margin on input prefix
* Centered now default for modals
* types
* Working, but messy
* Add InputColor component
* types
* Show default theme values when not customized
* Support custom theme on team sign-in page
* Payload validation
* Custom theme on shared documents
* Improve theme validation
* Team -> Workspace in settings
* clarify default role and allowed domains
* language tweaks
* Update app/scenes/Settings/Security.tsx
Co-authored-by: Tom Moor <tom.moor@gmail.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
The logic for this is that we show the button if either:
a) one or more new non-empty domains have been added, or
b) an existing domain was modified, even if the modification was then undone.
The reasoning for b) is as follows:
If a user adds a new domain row, makes changes, then removes the domain row, it is clear to the user that no changes have been made, and therefore the "save" button should not be visible.
However, as soon as the user makes any changes to an existing domain, they want to feel confident that they can hit save and ensure that whatever change they made is persisted; even if the change is identical to the current state, because they may not be able to recall accurately what the current state was. In those situations a user gets more confidence out of being able to hit save, than they would from being told by the system "you haven't made any changes".
Fixes#3412
Previously the only way to restrict the domains for a Team were with the ALLOWED_DOMAINS environment variable for self hosted instances.
This PR migrates this to be a database backed setting on the Team object. This is done through the creation of a TeamDomain model that is associated with the Team and contains the domain name
This settings is updated on the Security Tab. Here domains can be added or removed from the Team.
On the server side, we take the code paths that previously were using ALLOWED_DOMAINS and switched them to use the Team allowed domains instead