Compare commits

...

1353 Commits

Author SHA1 Message Date
Tom Moor 2c870f0dbb 0.73.1 2023-11-14 07:56:56 -05:00
Tom Moor cd359f0e76 fix: Migration script fails on fresh installation
closes #6153
2023-11-14 07:43:15 -05:00
Apoorv Mishra ff7f9d68d5 fix: restore working of babel-plugin-styled-components (#6140) 2023-11-14 09:56:24 +05:30
Tom Moor 8c85029d55 Improve reliability of team deletion 2023-11-13 22:06:24 -05:00
Tom Moor 530b8a1989 0.73.0 2023-11-13 20:47:36 -05:00
Tom Moor b3047e2599 yarn.lock 2023-11-13 20:47:32 -05:00
Tom Moor 1898a34418 Rearchitect import (#6141) 2023-11-13 17:15:38 -08:00
dependabot[bot] 2143269bcd chore(deps-dev): bump @types/enzyme-adapter-react-16 from 1.0.6 to 1.0.9 (#6147)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 17:01:50 -08:00
dependabot[bot] 14987f1e6d chore(deps-dev): bump @types/react-avatar-editor from 13.0.0 to 13.0.2 (#6148)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 17:01:36 -08:00
dependabot[bot] 482dbec901 chore(deps-dev): bump @types/koa-logger from 3.1.2 to 3.1.5 (#6145)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 17:01:25 -08:00
Tom Moor 48d688c0a5 Store source metadata for imported documents (#6136) 2023-11-11 07:52:29 -08:00
Tom Moor 90605e110a fix: Include maximum import size 2023-11-10 08:28:17 -05:00
dependabot[bot] 854802e137 chore(deps): bump @babel/plugin-proposal-decorators from 7.21.0 to 7.23.2 (#6022)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 18:31:20 -08:00
Tom Moor 6684c420d3 chore: Upgrade @types/node 2023-11-09 19:36:48 -05:00
Tom Moor 1c6f8dda5e fix: Cleanup empty folders when using local storage provider, closes #5978 2023-11-09 19:24:16 -05:00
Tom Moor 1a556b6ff2 fix: Internal server error during import with nested documents 2023-11-09 19:24:16 -05:00
Tom Moor 0964d03a17 More use of isProduction/isDevelopment getters 2023-11-09 19:24:16 -05:00
Tom Moor 1ace76eb44 fix: Show correct favicon for team on login screen if public branding is enabled 2023-11-09 19:24:16 -05:00
Tom Moor a1b52e18dd chore: Centralize environment detection 2023-11-09 19:24:16 -05:00
Tom Moor 096a65b0f9 fix: Improve error handling on env boolean parsing 2023-11-09 19:24:16 -05:00
Tom Moor d8d49f6950 fix: Internal server error during import with nested documents 2023-11-09 19:24:16 -05:00
Apoorv Mishra a7dd5c6798 fix: allow script injection from react dev tools in dev and stage envs (#6120) 2023-11-09 10:40:04 +05:30
dependabot[bot] 71c4c88bbe chore(deps-dev): bump babel-jest from 29.6.4 to 29.7.0 (#6123)
Bumps [babel-jest](https://github.com/jestjs/jest/tree/HEAD/packages/babel-jest) from 29.6.4 to 29.7.0.
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v29.7.0/packages/babel-jest)

---
updated-dependencies:
- dependency-name: babel-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 18:07:32 -05:00
dependabot[bot] 9ddf31632f chore(deps-dev): bump @types/addressparser from 1.0.1 to 1.0.2 (#6124)
Bumps [@types/addressparser](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/addressparser) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/addressparser)

---
updated-dependencies:
- dependency-name: "@types/addressparser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 18:06:51 -05:00
dependabot[bot] 067fd11663 chore(deps): bump core-js from 3.33.0 to 3.33.2 (#6125)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.33.0 to 3.33.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.33.2/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 18:06:16 -05:00
Tom Moor 446fffd367 fix: Mention attributed incorrectly 2023-11-06 08:19:23 -05:00
Tom Moor 03bdc4e00d Display domain on share button 2023-11-05 13:43:36 -05:00
Tom Moor 7b88547051 Add more fields to shared links management screen 2023-11-05 13:39:34 -05:00
Tom Moor 9be180d44d fix: Incorrect cursor on sortable table header cells 2023-11-05 12:44:53 -05:00
Tom Moor 733bd39ae4 fix: Sort nodes correctly in useCollectionTrees. closes #6102 2023-11-05 12:38:39 -05:00
Tom Moor 7c319c17c6 fix: Correct user on documents in deleted collection (#6116) 2023-11-05 06:43:38 -08:00
Tom Moor c76aa845f4 fix: Protect against view updates after destroyed in async uploads 2023-11-04 21:57:13 -04:00
Tom Moor ec79cab8b8 fix: Uncaught error in JSZip file reading crashes worker process. closes #6109 2023-11-04 21:51:09 -04:00
Tom Moor c769a95f65 API: Add endpoint to check custom domain resolution (#6110) 2023-11-04 12:21:47 -07:00
Tom Moor b2ad6ca9bc Refactor to middleware, support old routes 2023-11-01 23:52:18 -04:00
Tom Moor a48d8fac88 Return correct canonical url for share with domain 2023-11-01 23:45:41 -04:00
Tom Moor 1b73339800 fix: Link on 'Not Found' page for root share leads to custom domain landing 2023-11-01 23:20:41 -04:00
Tom Moor f0bf60eb40 Add graceful redirect from old share paths 2023-11-01 23:17:54 -04:00
Tom Moor 0f072acfd9 fix: Guard undefined ctx.state 2023-11-01 23:14:45 -04:00
Tom Moor 2838503273 Backend of public sharing at root (#6103) 2023-11-01 19:10:00 -07:00
Tom Moor 1d6ef2e1b3 perf: Remove unneeded query before custom domain redirect 2023-10-31 22:32:29 -04:00
Tom Moor 0700e2f5ef fix: Incorrect import – really need a lint rule for this 2023-10-31 22:20:31 -04:00
Tom Moor a9ff0c245d Toggle current todo item with Mod-Enter 2023-10-31 22:10:55 -04:00
Tom Moor 4af45c68cc Remove unused InputRich component 2023-10-31 21:58:30 -04:00
Tom Moor df6d8c12cc Refactor Editor components to be injected by associated extension (#6093) 2023-10-31 18:55:55 -07:00
dependabot[bot] 44198732d3 chore(deps-dev): bump @types/fs-extra from 11.0.1 to 11.0.3 (#6098)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 18:51:20 -07:00
dependabot[bot] 667e42e814 chore(deps): bump fetch-retry from 5.0.5 to 5.0.6 (#6097)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 18:51:09 -07:00
dependabot[bot] 5027ae9def chore(deps-dev): bump @types/natural-sort from 0.0.22 to 0.0.23 (#6096)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 18:50:54 -07:00
dependabot[bot] 07ce213232 chore(deps): bump slugify from 1.6.5 to 1.6.6 (#6099)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 18:50:47 -07:00
Tom Moor ed447f5811 fix: Eroneous toast on export 2023-10-30 08:41:09 -04:00
Tom Moor d593976b4d Add a button to upload images into comments (#6092) 2023-10-29 17:42:49 -07:00
Tom Moor 44cbf4359f Add success message on import completion 2023-10-29 20:42:23 -04:00
Tom Moor f0825b4cd9 fix: Remove broken comment ability on templates 2023-10-29 20:27:06 -04:00
Tom Moor 9f6c1f8b67 Hide scrollbars on search filters bar 2023-10-29 19:20:15 -04:00
Tom Moor 6b13a32234 fix: Refactor hover previews to reduce false positives (#6091) 2023-10-29 15:31:12 -07:00
Tom Moor 90bc60d4cf Move pinned collection documents above description 2023-10-29 12:12:23 -04:00
Apoorv Mishra 3fd429baa9 usePaginatedRequest hook for simpler handling of pagination on FE (#6060)
* feat: usePaginatedRequest hook

* fix: spread params

* fix: handle limit zero

* fix: handle case when stars.fetchPage returns empty array

* fix: use stars.orderedData for reactivity
2023-10-29 20:01:47 +05:30
Tom Moor 4d3655bc6c Remove usage of .at() for browser compat 2023-10-28 22:22:10 -04:00
Tom Moor 7b98ce3514 fix: Background transition on home screen 2023-10-28 20:42:57 -04:00
Tom Moor e6196ae79e fix: Find and replace dialog should be fixed when scrolling 2023-10-28 19:51:13 -04:00
Tom Moor 89f3d47327 Port HTML import improvements from enterprise codebase 2023-10-28 19:09:53 -04:00
Tom Moor 846fb122cd fix: Misalignment of code block line numbers when font-size is increased in Edge
closes #5612
2023-10-28 13:40:47 -04:00
Tom Moor 884f3c5896 fix: Emoji position when document is full-width 2023-10-28 13:12:30 -04:00
Tom Moor f2df25d115 Persist full-width as user preference when toggled
closes #5562
2023-10-28 13:03:38 -04:00
Tom Moor 92ba095124 fix: Guard against empty items in Facepile users, closes #6087 2023-10-28 12:45:02 -04:00
Tom Moor 1e847dc1cf Cleanup and refactor AuthStore (#6086) 2023-10-28 09:43:50 -07:00
Tom Moor 3cd90f3e74 Remove duplicative test 2023-10-28 11:38:35 -04:00
Tom Moor 964d2b6bb3 Allow use of useCurrentUser/useCurrentTeam hooks in unauthenticated components 2023-10-28 11:38:35 -04:00
Translate-O-Tron 56f9755cd9 New Crowdin updates (#6036) 2023-10-28 08:38:28 -07:00
Agnès Haasser 057d8a7f3b API - allow search of a group using its name (#6066) 2023-10-28 08:36:16 -07:00
Tom Moor 7380f6d5ae fix: Maximum number of connections reached, closes #5446
The opposite of onDisconnect is connected, not onConnect. smh.
2023-10-28 10:32:58 -04:00
Tom Moor 08d89fb57a fix: Enforce emoji flags on macOS 2023-10-26 23:58:02 -04:00
Tom Moor b53c595e1b fix: FILE_STORAGE_UPLOAD_MAX_SIZE not considered for direct uploads. closes #6078 2023-10-26 21:57:48 -04:00
Tom Moor f23a7bd685 fix: Development cannot start s3 2023-10-26 21:50:57 -04:00
Tom Moor 60941dc285 fix: Title is duplicated on imported collections 2023-10-26 21:27:06 -04:00
Tom Moor 33576b794a fix: Misalignment of menu item icon when text overflows 2023-10-26 20:37:36 -04:00
Tom Moor a6f8872baa fix: Selecting flag inserts a different flag
closes #6079
2023-10-26 20:37:36 -04:00
github-actions[bot] fb56b00e81 chore: Auto Compress Images (#6080)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2023-10-26 17:35:35 -07:00
Prikshit Singh d6fcf44bf4 Add instagram embed (#6075) 2023-10-26 17:34:25 -07:00
Tom Moor afb5ccbf74 fix: Improve quality of search results from : emoji search
closes #6073
2023-10-25 22:13:03 -04:00
Tom Moor d7dacd0cd3 test 2023-10-25 21:29:42 -04:00
Tom Moor 5402731ec3 fix: Do not prevent local IP connections to OIDC server
ref #6064
2023-10-25 20:54:26 -04:00
Tom Moor bf6bd3f8d0 Allow share record creation when disabled at team level for private sharing 2023-10-25 20:50:09 -04:00
Tom Moor 35fd1227e7 docs: Remove reference to huntr.dev 2023-10-25 20:32:28 -04:00
Tom Moor 2fcf9149b5 fix: Templatize no longer works, closes #6067 2023-10-25 20:29:36 -04:00
Tom Moor f063bef968 Merge branch 'main' of github.com:outline/outline 2023-10-25 19:46:03 -04:00
dependabot[bot] 3e1287064b chore(deps): bump crypto-js from 4.1.1 to 4.2.0 (#6072)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-25 16:10:28 -07:00
Pranav Joglekar d4b598570d fix: remember prev selected lang when creating new code block (#6062) 2023-10-24 19:35:55 -07:00
dependabot[bot] 04ac417bef chore(deps-dev): bump @types/node from 18.0.6 to 18.18.6 (#6056)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 20:08:30 -07:00
dependabot[bot] 1b11b9e31b chore(deps): bump oy-vey from 0.12.0 to 0.12.1 (#6057)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 20:08:12 -07:00
dependabot[bot] 6adf80d4e7 chore(deps): bump react-virtualized-auto-sizer and @types/react-virtualized-auto-sizer (#6058)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 20:07:53 -07:00
dependabot[bot] 7bc8f1fc72 chore(deps-dev): bump @types/react-color from 3.0.6 to 3.0.9 (#6055)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-23 20:07:40 -07:00
Tom Moor 5fc68db5da Improve reliability of document operations with websocket disconnected 2023-10-22 23:21:33 -04:00
Tom Moor 1abe4964e8 fix: Can't perform a React state update on an unmounted component 2023-10-22 22:08:36 -04:00
Tom Moor b0095e6fe1 Remove fakes3, no longer neccessary 2023-10-22 21:42:10 -04:00
Tom Moor e7f3e500cd fix: Menu height on mobile prevents closing 2023-10-22 21:30:39 -04:00
Tom Moor ef76405bd6 Move toasts to sonner (#6053) 2023-10-22 14:30:24 -07:00
Tom Moor 389297a337 fix: Include notice on where collection exports end up 2023-10-22 15:32:08 -04:00
Tom Moor 1a3b2dc307 Improve Redis error handling 2023-10-22 14:02:36 -04:00
Tom Moor fb74494108 Do not expose insightsEnabled, templateId on public shares 2023-10-22 13:49:50 -04:00
Tom Moor 764dc84da9 test 2023-10-21 22:20:17 -04:00
Tom Moor 3bf35affb1 fix: Enable management of notifications without SMTP configured
closes #6046
2023-10-21 21:36:11 -04:00
Tom Moor 9f6c90c86a fix: Improve performance of base64 detection regex 2023-10-21 21:29:06 -04:00
jannschu 0518cdc6d9 Use transaction from middleware for more database queries (#6051) 2023-10-21 14:31:14 -07:00
dependabot[bot] 5df48b3204 chore(deps-dev): bump @relative-ci/agent from 4.1.8 to 4.1.10 (#6018)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-18 19:11:31 -07:00
Translate-O-Tron c32aee8372 New Crowdin updates (#6028) 2023-10-18 15:50:30 -07:00
Agnès Haasser 3589980864 API : allow filter user list via emails (#6031) 2023-10-18 05:36:16 -07:00
Tom Moor d536fa9939 translation: team -> workspace 2023-10-18 08:32:43 -04:00
Tom Moor 89694a561f translation: Pinned to team home -> Pinned to home 2023-10-17 23:30:26 -04:00
Tom Moor ac7668b5f7 Merge branch 'main' of github.com:outline/outline 2023-10-17 23:29:54 -04:00
github-actions[bot] 76b12cbad5 chore: Auto Compress Images (#6027)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2023-10-17 20:14:29 -07:00
Prikshit Singh bb8fd93628 Add LinkedIn embed (#5933)
Co-authored-by: Prikshit singh <prikshit.singh@aimedlabs.com>
2023-10-17 20:12:20 -07:00
Translate-O-Tron 12f7e3d1da New Crowdin updates (#5897) 2023-10-17 20:11:52 -07:00
Tom Moor ba612a557f translation: knowledgebase -> workspace 2023-10-17 22:34:01 -04:00
Tom Moor 608e1eeaa0 Remove unused translations 2023-10-17 21:51:26 -04:00
Tom Moor 297536bfe5 Remove duplicate translation. ref: https://crowdin.com/translate/outline/44/en-es\?filter\=basic\&value\=0\#3202 2023-10-17 21:28:55 -04:00
Tom Moor caafdb2fe7 fix: Ensure initials on avatars are always displayed uppercase 2023-10-17 18:49:33 -04:00
Tom Moor ea97963feb fix: RangeError: Position -1 out of range 2023-10-17 18:20:57 -04:00
Tom Moor 03869784be fix: permanantly -> permanently 2023-10-17 18:16:41 -04:00
Tom Moor 43ee487e91 Add 'Rename' option to document sidebar menu 2023-10-17 18:15:35 -04:00
Tom Moor 955705dd64 fix: deletedAt property not reactive 2023-10-16 22:59:12 -04:00
Tom Moor d8b7d14419 fix: Unarchiving a deleted draft adds to collection structure 2023-10-16 22:54:26 -04:00
Tom Moor d89ce1ea4d fix: Remove comment open in selection toolbar on deleted documents 2023-10-16 22:30:24 -04:00
Tom Moor 5bc5759f42 Add userId to views response, closes #6014 2023-10-16 21:26:35 -04:00
Tom Moor 03c739032d fix: views.list should not include deleted users 2023-10-16 21:21:03 -04:00
Tom Moor 0bec781695 fix: Improve validation of edge cases with documents.move endpoint. closes #6015 2023-10-16 21:04:39 -04:00
Tom Moor a357cbaf8d perf: Improve performance of Placeholder extension 2023-10-16 19:38:11 -04:00
Tom Moor 0b7253bb0c fix: Tighten valiation around URLs in database fields
closes #6012
2023-10-16 19:38:11 -04:00
Tom Moor 31cb9c865f fix: Assumption that url passed to storeFromUrl will send content-length header 2023-10-16 19:38:11 -04:00
Tom Moor 787b893cd2 Increase max collection description 2023-10-16 19:38:11 -04:00
Tom Moor faf97401e6 feat: add "Copy document" dialog (#6009) 2023-10-16 16:13:57 -07:00
Tom Moor 1ce0d3470e Make code block Enter behavior the same as quote block (#6010) 2023-10-16 16:13:23 -07:00
dependabot[bot] bedad9d802 chore(deps): bump @babel/traverse from 7.22.5 to 7.23.2 (#6023)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 16:13:01 -07:00
dependabot[bot] e2c5daefac chore(deps-dev): bump @types/natural-sort from 0.0.21 to 0.0.22 (#6017)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 16:05:48 -07:00
dependabot[bot] 3feb104288 chore(deps-dev): bump @types/crypto-js from 4.1.1 to 4.1.2 (#6019)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-16 16:04:51 -07:00
Tom Moor 9e3b2c043c fix: Port escape overrides from enterprise fork 2023-10-15 10:54:27 -04:00
Tom Moor d5bac6cbca fix: Paragraphs in table cells skipped in import
Port HTML importer rules from enterprise fork
2023-10-15 10:54:27 -04:00
Tom Moor 00ee8729ec fix: Import of breaks from HTML files 2023-10-14 17:44:25 -07:00
Tom Moor 1305e3746b fix: Warning setState after unmounted 2023-10-14 17:27:02 -04:00
Tom Moor 02731e73c5 fix: Hover cards appearing on embeds, change to allow-list approach 2023-10-14 09:29:08 -04:00
Tom Moor b3f9707ffb Add 'open' link to Grist embeds 2023-10-14 09:22:57 -04:00
Tom Moor c32ac1a265 fix: Table of contents slightly covers emoji picker
closes #6006
2023-10-14 09:07:17 -04:00
Tom Moor 6a74fdf6cf fix: Allow browser translation of documents in read-only, closes #5998 2023-10-12 23:33:57 -04:00
Tom Moor a84008085f Merge branch 'main' of github.com:outline/outline 2023-10-12 23:17:09 -04:00
dependabot[bot] 3212d37ca5 chore(deps): bump vite from 4.4.9 to 4.4.11 (#5972)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-12 05:44:41 -07:00
dependabot[bot] 47837e315a chore(deps): bump zod from 3.21.4 to 3.22.4 (#5974)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-12 05:38:45 -07:00
Tom Moor a652386329 fix: Use consistent active state on recent search items 2023-10-11 23:39:11 -04:00
ktmouk c5c323690b Add the keyboard operation on recent search items (#5987)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-10-11 20:37:57 -07:00
Tom Moor 8bfd17c8d4 Remove creator name in template menu, closes #5976 2023-10-11 22:30:20 -04:00
Tom Moor e8646acd21 fix: Mermaid diagrams are not hidden under a collapsed heading. closes #5979 2023-10-11 22:27:38 -04:00
Tom Moor ffbe4c1b80 fix: Prevent potential page scroll on context menu open 2023-10-11 22:17:18 -04:00
Tom Moor b63cd67c24 fix: Expensive recursive regex when using French language, closes #5939 2023-10-11 21:32:44 -04:00
Tom Moor 0d319d50b8 Shakes fist at autocomplete 2023-10-11 09:24:37 -04:00
Tom Moor a579ecd512 fix: Commenting on code blocks does not work in read-only view 2023-10-10 19:35:45 -04:00
Tom Moor 547b6c0ac9 fix: Allow context menus to use more available viewport height 2023-10-10 19:32:24 -04:00
Tom Moor bf53ac4f4b fix: Ensure video src passed to player is sanitized 2023-10-10 19:22:05 -04:00
Tom Moor 09938c2649 perf: Avoid recreating transaction when no upload placeholders exist 2023-10-10 19:19:44 -04:00
Tom Moor 8354a5bc37 fix: Use of view after destroyed, closes #5982 2023-10-10 19:00:12 -04:00
Tom Moor fec1a72780 fix: Remove zapier from CSP on self-hosted 2023-10-09 21:11:05 -04:00
dependabot[bot] 4181aa0f3c chore(deps-dev): bump @types/react-helmet from 6.1.6 to 6.1.7 (#5973)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 11:46:34 -07:00
dependabot[bot] 5305c142a2 chore(deps): bump prosemirror-tables from 1.3.2 to 1.3.4 (#5971)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-09 11:07:35 -07:00
Tom Moor 594898affc fix: Sidebar should collapse after control click (again)
closes #5958
2023-10-07 21:14:48 -04:00
Tom Moor 6402f0bfcf fix: Enable backtick inline code shortcut on keyboard layouts that use composition for character
Add Cmd+e shortcut to toggle inline code on macOS

closes #5955
2023-10-07 21:11:50 -04:00
Tom Moor 2f3247b500 fix: Cannot read properties of undefined (reading 'width') 2023-10-07 20:59:18 -04:00
Tom Moor b6706efe6f Add validation to require protocol on urls in env
Related #5961
2023-10-07 17:49:24 -04:00
Tom Moor 63263eee82 Tweak floating toolbar style 2023-10-06 12:31:03 -04:00
Tom Moor 9924fa6621 feat: Allow commenting in code (#5953)
* Allow commenting in code marks

* Allow commenting in code blocks

* Floating comment toolbar in code block
2023-10-06 06:56:59 -07:00
dependabot[bot] ac319de1df chore(deps): bump postcss from 8.4.27 to 8.4.31 (#5952)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-05 20:07:13 -07:00
Tom Moor 2108ca29df fix: Sidebar toggle icon should always appear when hovering over sidebar 2023-10-05 22:55:49 -04:00
Tom Moor ea4de0dfb5 chore: Docs, define additional client-side relations 2023-10-05 22:32:58 -04:00
Tom Moor 773c35ebc3 fix: Correctly clear accessToken when logging out.
Token is correctly rotated on the server, it just isnt correctly removed on the client.
closes #5940
2023-10-05 22:10:07 -04:00
Tom Moor 0ae4c7d6bd Merge branch 'main' of github.com:outline/outline 2023-10-05 21:52:13 -04:00
Tom Moor 50faefbc45 fix: Reserve space for unread dot on notifications flyover 2023-10-05 21:47:34 -04:00
Tom Moor eb71a8f933 fix: Various compounding memory leaks in editor (#5950) 2023-10-05 17:01:27 -07:00
Tom Moor a2f037531a Add registering of client-side relationship properties (#5936) 2023-10-05 16:50:59 -07:00
Tom Moor e70d4e60fd fix: Microsoft logo does not inheret accent color
closes #5944
2023-10-05 19:50:22 -04:00
Tom Moor 5e0b812083 fix: 'Untitled' is not translated
closes #5949
2023-10-05 19:44:54 -04:00
Tom Moor 1359f44814 fix: Links to attachments do not work in emailed notifications (#5935) 2023-10-04 18:25:07 -07:00
Tom Moor e1c90d3938 fix: Correctly invalidate translations cache on change
closes #5924
2023-10-04 21:12:58 -04:00
Tom Moor e967641bb6 fix: Clicking collapse sidebar does not hide sidebar until clicked elsewhere
closes #5928
2023-10-03 20:52:29 -04:00
Tom Moor 4d2a5ae748 fix: 'latest' tagging in build process. Incorrect check assumed image built on main instead of non-prerelease tag 2023-10-03 08:14:27 -04:00
Tom Moor 56cae8a545 0.72.0 2023-10-02 20:24:17 -04:00
dependabot[bot] e5e049a671 chore(deps): bump react-dropzone from 11.3.2 to 11.7.1 (#5913)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 16:26:12 -07:00
dependabot[bot] 48438eea2d chore(deps): bump i18next-http-backend from 2.2.0 to 2.2.2 (#5914)
Bumps [i18next-http-backend](https://github.com/i18next/i18next-http-backend) from 2.2.0 to 2.2.2.
- [Changelog](https://github.com/i18next/i18next-http-backend/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-http-backend/compare/v2.2.0...v2.2.2)

---
updated-dependencies:
- dependency-name: i18next-http-backend
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 15:44:47 -07:00
dependabot[bot] 8e7dfdb6a0 chore(deps-dev): bump @types/react-window from 1.8.5 to 1.8.6 (#5915)
Bumps [@types/react-window](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-window) from 1.8.5 to 1.8.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-window)

---
updated-dependencies:
- dependency-name: "@types/react-window"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 15:44:31 -07:00
dependabot[bot] c8acf96790 chore(deps-dev): bump @types/sequelize from 4.28.10 to 4.28.16 (#5917)
Bumps [@types/sequelize](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/sequelize) from 4.28.10 to 4.28.16.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/sequelize)

---
updated-dependencies:
- dependency-name: "@types/sequelize"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 15:44:21 -07:00
Tom Moor e7b7032284 feat: Allow deletion of imports (#5907) 2023-10-01 18:24:50 -07:00
Tom Moor 16cd82a732 fix: JSON import fails if the same import has been imported and deleted previously 2023-10-01 15:16:55 -04:00
Tom Moor 41a6f77998 fix: Types on overridden findByPk methods (#5908) 2023-10-01 12:02:56 -07:00
Tom Moor e2a6d828a9 Allow creating published share record, closes #5902 2023-09-30 12:38:16 -04:00
Tom Moor 2868ab2d00 fix: Floating toolbar overflow 2023-09-29 22:32:43 -04:00
Tom Moor aa79bc85f1 fix: Mobile toolbar appears on Windows touchscreen
fix: Improve mobile toolbar
2023-09-29 00:18:22 -04:00
Tom Moor 5397907599 chore: Refactor upload placeholder (#5898) 2023-09-28 20:13:40 -07:00
Tom Moor f4fd9dae5f feat: Native video display (#5866) 2023-09-28 17:28:09 -07:00
Tom Moor bd06e03b1e Added more debugging logs for #5564 2023-09-28 17:36:10 -04:00
Tom Moor 5b2bb41ead fix: Remember previous path when logging out due to auth expired
closes #5893
2023-09-28 17:22:52 -04:00
Translate-O-Tron 2e759e4e81 New Crowdin updates (#5857) 2023-09-28 06:01:38 -07:00
Tom Moor 5a89edbcb2 fix: withCollection scopes on UserPermission, GroupPermission 2023-09-27 23:08:06 -04:00
Tom Moor 6eab716779 fix: Mention menu hanging after backspace 2023-09-27 22:41:30 -04:00
Tom Moor 6de96b1d9d perf: Don't render SuggestionMenu contents until active 2023-09-27 21:19:55 -04:00
dependabot[bot] 318a1120d4 chore(deps): bump aws-sdk from 2.1369.0 to 2.1464.0 (#5888)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-27 06:26:01 -07:00
Tom Moor 86cb861ca7 Improve clarity of error message when database SSL disabled and file storage cannot be written 2023-09-27 09:07:49 -04:00
Tom Moor 2261514138 Improve debugging when OIDC userinfo endpoint does not return JSON 2023-09-26 23:46:56 -04:00
Tom Moor 402695c2e3 fix: Remove zero count on drafts 2023-09-25 23:10:16 -04:00
Tom Moor 9e810387c0 Add cache-control headers to attachments.redirect response 2023-09-25 21:30:57 -04:00
Tom Moor b1ddf417be fix: Capture errors recreating transform and log, these are non-critical 2023-09-25 20:45:34 -04:00
Tom Moor 0014bcf22d chore: Remove unused dep 2023-09-25 20:42:10 -04:00
Tom Moor 606a4e0772 Add small cache to mermaid diagrams, follow on to #5852 2023-09-25 20:41:18 -04:00
Tom Moor 4807c60042 fix: Do not modify internet server error before pushing to Sentry 2023-09-25 18:11:53 -04:00
dependabot[bot] dd02bd9c03 chore(deps): bump bull from 4.10.4 to 4.11.3 (#5886)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 15:04:40 -07:00
antran22 1639c657c8 feat: update mermaid rendering flow (#5852)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-09-25 14:03:25 -07:00
dependabot[bot] 25b961b3b8 chore(deps): bump katex from 0.16.7 to 0.16.8 (#5884)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 14:03:04 -07:00
dependabot[bot] 144ba0ced9 chore(deps): bump sequelize from 6.32.1 to 6.33.0 (#5885)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 14:02:55 -07:00
dependabot[bot] d340f8977d chore(deps-dev): bump lint-staged from 13.2.3 to 13.3.0 (#5887)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-25 14:02:43 -07:00
Apoorv Mishra 7145f7ef51 UserPermission and GroupPermission models (#5860)
* fix: rename to group_permissions

* fix: delete null collectionId records before setting non null constraint

* fix: use scope with collectionId not null

* fix: update model with documentId

* fix: rename to GroupPermission

* fix: rename collection_users to user_permissions

* fix: teamPermanentDeleter test

* fix: use scope with collectionId not null

* fix: update model with documentId

* fix: rename to UserPermission

* fix: create views upon table rename for zero downtime

* fix: remove comments
2023-09-25 10:51:29 +05:30
Tom Moor 43bdb97639 fix: Aggressive embed conversion on server Markdown -> Ydoc 2023-09-24 23:12:38 -04:00
Tom Moor 136ee0ad1d fix: 500 server error when files.create request is closed by client (#5878) 2023-09-24 13:30:52 -07:00
Tom Moor 517f2634e3 chore: Create data directory inside Dockerfile (#5862) 2023-09-24 12:03:00 -07:00
Tom Moor 42cc991317 fix: files.create permissions (#5877)
* fix: files.create permissions

* test

* new
2023-09-24 12:02:49 -07:00
Tom Moor e50e0bba53 Allow file access not in Attachments table (#5876)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-24 06:43:37 -07:00
Tom Moor d0bb6c6a41 fix: Size of export does not update dynamically on screen 2023-09-23 18:11:17 -04:00
Tom Moor 6aec085942 fix: Error handling on streams missing error handler on read streams.
Related https://github.com/outline/outline/discussions/5855
2023-09-23 18:08:36 -04:00
Tom Moor 65d3c8309e fix: Unable to store/read in avatars bucket with local file system storage
closes #5873
2023-09-23 15:00:48 -04:00
Tom Moor 5c7c9ceeb1 JSDoc, closes #5874 2023-09-23 14:31:55 -04:00
Tom Moor 3f11b014c5 fix: --watch mode no longer working
closes #5867
2023-09-22 09:01:51 -04:00
Tom Moor 76862b626b Allow setting createdAt, emoji properties through documents.create (#5864) 2023-09-21 19:37:27 -07:00
Tom Moor 8833e578f1 fix: JS error hitting up or down with entire document selection
closes #5863
2023-09-21 21:16:59 -04:00
Tom Moor 8c661345f0 fix: Incorrect translation of != null 2023-09-21 10:24:18 -04:00
Tom Moor 89537aabc3 Vendorize prosemirror-recreate-transform (#5861) 2023-09-21 05:44:23 -07:00
Tom Moor 6672536cde fix: Retain image and video placeholders when document remotely edited 2023-09-21 00:15:54 -04:00
Tom Moor 34d4209dd5 fix: Race condition with setting awareness field 2023-09-20 23:48:14 -04:00
Translate-O-Tron 27befbf3f7 New Crowdin updates (#5767) 2023-09-20 18:04:03 -07:00
Tom Moor 5aa7b42f8b fix: Cannot read properties of undefined (reading 'id') 2023-09-20 20:27:50 -04:00
Apoorv Mishra 67b1fe5514 Local file storage (#5763)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-09-20 15:12:03 -07:00
dependabot[bot] fea50feb0d chore(deps): bump @babel/preset-react from 7.22.5 to 7.22.15 (#5838)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 05:42:57 -07:00
dependabot[bot] 1b1b95d673 chore(deps-dev): bump @types/semver from 7.5.0 to 7.5.2 (#5839)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 05:41:52 -07:00
dependabot[bot] 1137d45f92 chore(deps): bump node-fetch and @types/node-fetch (#5840)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 05:41:37 -07:00
Tom Moor 091ef340f4 fix: Mermaid syntax error diagram sometimes displayed at side of document
ref https://github.com/outline/outline/discussions/5834
2023-09-16 19:33:28 -04:00
Tom Moor 432fa970e5 fix: Pasting single line of code should use a mark, not a block by default. 2023-09-16 17:59:12 -04:00
Tom Moor 59734f2bf7 fix: Check commenting feature is enabled on all comments endpoints 2023-09-16 17:46:02 -04:00
Tom Moor 4fa3270f4e Port changes from enterprise codebase 2023-09-16 08:36:22 -04:00
Tom Moor 3582a6a0a2 Bump thickness of LetterIcon to better match other icons 2023-09-15 21:19:12 -04:00
Tom Moor 8c2a47db9d fix: Serve CORS header for fonts 2023-09-15 21:10:03 -04:00
Tom Moor 266a2f4485 fix: integrations.delete event not handled in DeliverWebhookTask 2023-09-15 20:48:24 -04:00
Tom Moor c20eac0b03 fix: Letter icon at all sizes 2023-09-15 08:58:40 -04:00
Tom Moor 6b4feb51e0 Add letter icon option for collections 2023-09-15 08:54:22 -04:00
Tom Moor b79f86d347 Enter at beginning of first table column should insert row above 2023-09-14 23:34:25 -04:00
Tom Moor 411ab6b785 fix: Backspace emoji as first character in heading converts to paragraph 2023-09-14 22:19:27 -04:00
Tom Moor 924ab156f3 fix: Allow mention and emoji menus in headings 2023-09-14 09:11:18 -04:00
Tom Moor 7e17e82ac8 fix: Handle emoji field in imported documents
closes #5810
2023-09-13 22:05:21 -04:00
Tom Moor ef22a5dc52 fix: Escape to exit popover in Safari fullscreen exits fullscreen instead.
closes #5812
2023-09-13 21:23:17 -04:00
Tom Moor 56a526e930 fix: Respect fullWidth setting when creating document from template 2023-09-13 20:54:37 -04:00
Tom Moor a32857c715 fix: Cannot edit templates in settings with separate editing mode 2023-09-13 20:27:45 -04:00
Tom Moor 882408bc0e Add actions to create document from template in command bar 2023-09-12 22:09:38 -04:00
Tom Moor b80ee89588 Correctly resize full width images when table of contents is opened/closed (#5826)
* stash

* restore

* Self review
2023-09-12 18:33:25 -07:00
Apoorv Mishra d81db7e4f6 fix: typo in includesMembership function (#5823) 2023-09-12 16:56:34 +05:30
Apoorv Mishra 401d1ba871 multipart middleware (#5809)
* fix: multipart middleware

* fix: reviews
2023-09-12 10:21:58 +05:30
dependabot[bot] 99e3a305d3 chore(deps-dev): bump @relative-ci/agent from 4.1.3 to 4.1.8 (#5815)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 18:58:45 -07:00
dependabot[bot] 5e9151f02a chore(deps-dev): bump eslint-plugin-jsx-a11y from 6.4.1 to 6.7.1 (#5817)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 18:44:43 -07:00
dependabot[bot] 9e218bd4f3 chore(deps): bump socket.io from 4.6.1 to 4.7.2 (#5816)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 18:44:33 -07:00
Tom Moor d43f1b529d fix: Flipped template logic (regressed in 0856f5f) 2023-09-11 09:41:42 -04:00
Tom Moor 0856f5f6ae Move template management to settings (#5811) 2023-09-10 12:46:12 -07:00
Tom Moor ac068c0c07 fix observability regression, from 5c839998 2023-09-09 23:41:48 -04:00
Tom Moor 9602d09964 fix: Add locks to user mutations (#5805) 2023-09-09 20:26:22 -07:00
Tom Moor c22ed0c82e BaseModel -> Model 2023-09-09 22:39:08 -04:00
Tom Moor 6159973df9 fix: Only update views in collaborative server on data change (#5804) 2023-09-09 19:16:02 -07:00
Tom Moor 5c839998c1 fix: Initials do not display on notification avatars (#5803) 2023-09-09 18:01:14 -07:00
Tom Moor 80ef0a38d6 chore: More flakey test improvements (#5801) 2023-09-09 15:30:19 -07:00
Tom Moor 7270e65f0c fix: Remapping gemoji thumbs_up/down 2023-09-08 17:58:19 -04:00
Tom Moor 76845a3308 fix: Cannot leave thumbs up through emoji menu 2023-09-08 10:57:03 -04:00
Tom Moor 5c8bcc11b4 fix: App switches back to default installation language when navigating to root 2023-09-07 22:48:19 -04:00
Tom Moor d8bfb0fe5d cleanup 2023-09-07 22:36:10 -04:00
Tom Moor bb555de1ba fix: In-app document mention notifications do not link to correct doc 2023-09-07 22:17:55 -04:00
Tom Moor 127115272a feat: Return attachments when exporting an individual file (#5778) 2023-09-06 17:53:30 -07:00
Tom Moor d1de5871de fix: Flaky groups test (#5789) 2023-09-06 15:29:30 -07:00
Tom Moor ec0564eb32 chore: Test performance (#5786) 2023-09-06 14:19:21 -07:00
Tom Moor 3eb947e9a5 chore: Improve perf of server tests (#5785) 2023-09-06 04:14:49 -07:00
Tom Moor a724a21c21 fix: Error viewing revisions 2023-09-05 23:55:06 -04:00
Tom Moor c4aad4d4bf fix: Document unfurling on custom domains
closes #5781
2023-09-05 23:19:26 -04:00
Tom Moor 795fe37bd6 fix: Emoji picker should be on right hand side for RTL languages 2023-09-05 07:53:07 -04:00
Tom Moor 262590e507 perf: Improve performance of rendering context menus 2023-09-04 23:29:19 -04:00
Tom Moor 5f788012db Hide document UI while typing 2023-09-04 22:10:27 -04:00
Tom Moor 2358c3d13d refactor 2023-09-04 21:12:28 -04:00
github-actions[bot] a03b95221a chore: Auto Compress Images (#5779)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2023-09-04 17:49:54 -07:00
Tom Moor 3223341062 feat: Add Valtown embed support 2023-09-04 20:48:24 -04:00
Tom Moor ce645b158b fix: Allow pasting Pitch embed links 2023-09-04 20:48:24 -04:00
Tom Moor 74860ed961 feat: Allow users to override team setting for seamless editing (#5772) 2023-09-04 16:19:43 -07:00
Tom Moor c376dc1011 Increase hit area on sidebar buttons 2023-09-04 16:24:58 -04:00
Tom Moor a956f54b5a Hover preview tweak 2023-09-04 16:11:06 -04:00
Tom Moor 1c99e8519a fix: URLs to internal resources should not be sent to Iframely 2023-09-04 14:46:26 -04:00
dependabot[bot] 6079b71d3c chore(deps): bump passport-slack-oauth2 from 1.1.1 to 1.2.0 (#5776)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 11:19:45 -07:00
dependabot[bot] 749c8dc335 chore(deps): bump react-i18next from 12.1.5 to 12.3.1 (#5775)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 11:19:06 -07:00
dependabot[bot] 57d1643d77 chore(deps): bump koa-compress from 5.1.0 to 5.1.1 (#5773)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-04 11:18:48 -07:00
Tom Moor 1df7a42868 Update language on /outline help text
Update Slack hooks to use zod validation

closes #5768
2023-09-04 10:40:46 -04:00
Tom Moor 02cced078f Update .env.sample 2023-09-03 19:14:29 -07:00
Tom Moor d7c331532d Add document unsubscribe link in email footer (#5762) 2023-09-03 16:04:28 -07:00
Jack Woodgate 0261e0712c fix: Safari sidebar animation #5765 (#5766) 2023-09-03 15:42:47 -07:00
Tom Moor f7111991dc Rename Tldraw (beta) -> Tldraw 2023-09-03 17:23:59 -04:00
Tom Moor 10a190cd80 fix: Add support for main and old tldraw domains
closes #5769
2023-09-03 17:23:08 -04:00
Tom Moor 3721ea2333 fix: Allow use of validations middleware in plugins 2023-09-03 16:52:46 -04:00
Tom Moor 1048ea8771 fix: Background error building plugins with no server content 2023-09-03 16:20:54 -04:00
Tom Moor a3cfef09f3 Lockfile 2023-09-03 09:12:20 -04:00
Tom Moor ef71a54120 Merge branch 'main' of github.com:outline/outline 2023-09-03 09:11:33 -04:00
Apoorv Mishra 1c7bb65c7a Document emoji picker (#4338)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-09-03 06:11:14 -07:00
Tom Moor 093ee74a90 fix: Protect against exports larger than memory/max 2023-09-02 22:11:53 -04:00
Tom Moor 0054b7152e Update LICENSE 2023-08-31 18:37:26 -07:00
Tom Moor 8b4b2ca741 fix: S3Storage incorrectly setting hostname 2023-08-31 20:44:34 -04:00
Tom Moor 911bb1f492 Prefer SF Pro on Mac 2023-08-31 20:28:00 -04:00
Tom Moor c9f0c86719 Small improvement to messages posted to Slack
Related #5295
2023-08-31 20:18:25 -04:00
Translate-O-Tron d0fe6ad93f New Crowdin updates (#5697) 2023-08-31 15:12:44 -07:00
Tom Moor 4e53029377 Use "Inter" as default typeface (#5741)
* Inter

* tweaks

* tweaks
2023-08-31 15:07:45 -07:00
Tom Moor 7abb4f9ad6 Improve validation on api/users endpoints (#5752) 2023-08-31 15:06:18 -07:00
Tom Moor dec03b9d84 fix: Remove cloud hosted check before running migrations 2023-08-30 23:03:49 -04:00
Tom Moor d591158c4d Restore sidebar toggle in settings
Cleanup some unused props
2023-08-30 20:38:09 -04:00
Tom Moor fa03f9c08d Add additional rate limits on documents API endpoints 2023-08-30 20:28:22 -04:00
Tom Moor b7055ef853 Move sidebar toggle into the sidebar itself instead of overlaying document content (#5749) 2023-08-29 18:45:03 -07:00
Tom Moor 864ddbd438 fix: Do not attempt to download non-valid urls in document create/import 2023-08-28 21:02:10 -04:00
Tom Moor 30a4303a8e chore: Remove DEPLOYMENT and SUBDOMAINS_ENABLED (#5742) 2023-08-28 17:39:58 -07:00
Tom Moor 7725f29dc7 Merge branch 'main' of github.com:outline/outline 2023-08-28 19:28:46 -04:00
dependabot[bot] 08825c7d97 chore(deps): bump i18next-fs-backend from 2.1.1 to 2.1.5 (#5745)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-28 16:06:40 -07:00
dependabot[bot] 448258746c chore(deps-dev): bump eslint-plugin-import from 2.26.0 to 2.28.1 (#5746)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-08-28 16:06:31 -07:00
Tom Moor b002d51ace Add support for iframes in imported HTML 2023-08-28 18:37:39 -04:00
dependabot[bot] 3e6a22e369 chore(deps): bump @babel/plugin-transform-regenerator from 7.20.5 to 7.22.10 (#5747)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-28 15:36:24 -07:00
Tom Moor 412f3ed9a4 Update README.md 2023-08-27 17:16:42 -07:00
Tom Moor 78ad1b867a fix: Handle base64 and remote images when creating a file (#5740) 2023-08-26 06:15:14 -07:00
Tom Moor c643f62d96 fix: Show more header options in edit mode 2023-08-24 21:51:42 -04:00
Tom Moor 79ff9309fd fix: Write revision when leaving editing mode 2023-08-24 21:18:38 -04:00
Tom Moor 9256c59e60 Add C++ to code language options, closes #5736 2023-08-24 19:52:35 -04:00
Tom Moor 1d90f98a29 fix: Remove overly aggressive AWS_ env variable validation prevents use with IAM roles 2023-08-24 18:16:52 -04:00
Tom Moor 10ec8a59b4 fix: Disable previews in notification items 2023-08-23 22:34:21 -04:00
Tom Moor dfbd89ad53 fix: Improve error message when an individual document in a large import is too large 2023-08-23 21:49:35 -04:00
Tom Moor da9a8af543 fix: Prevent rendering of undefined SVG placeholder 2023-08-23 21:35:05 -04:00
Tom Moor aada5c20cd fix: Clarify separate billing on workspaces 2023-08-23 19:44:42 -04:00
Apoorv Mishra 8f86eadc5d fix: tsc (#5732) 2023-08-23 19:23:41 +05:30
Apoorv Mishra 53c6c5599a Go-To Actions with transactions emails (#5728)
* feat: go-to actions for emails

* fix: comment

* fix: tsc without previewText

* fix: goToAction

* fix: link to original template

* fix: final comments
2023-08-23 18:43:52 +05:30
dependabot[bot] e3ba87dcb0 chore(deps-dev): bump eslint from 8.45.0 to 8.47.0 (#5722)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 07:07:37 -07:00
dependabot[bot] 3c5753621c chore(deps-dev): bump babel-jest from 29.6.1 to 29.6.3 (#5723)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 07:07:24 -07:00
Tom Moor 3366fb46cd fix: Copy Mermaid toolbar incorrectly positioned in read-only
closes #5714
2023-08-21 22:20:42 -04:00
Tom Moor 89bf5373aa chore: Add pointer to troubleshooting when nonce prevents script execution
closes #5718
2023-08-21 21:38:30 -04:00
dependabot[bot] e6b0e434ea chore(deps): bump rate-limiter-flexible from 2.4.1 to 2.4.2 (#5721)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-21 17:25:33 -07:00
dependabot[bot] 225f0dbf11 chore(deps): bump dd-trace from 3.32.1 to 3.33.0 (#5725)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-21 17:25:00 -07:00
Tom Moor 418d3305b2 feat: Add team deletion flow for cloud-hosted (#5717) 2023-08-21 17:24:46 -07:00
Tom Moor 5c07694f6b Refactor 'uploadFromUrl' to base storage implementation
Add safety around using fetch implementation
2023-08-20 13:13:17 -04:00
Tom Moor 74722b80f2 chore: Refactor file storage (#5711) 2023-08-20 07:04:34 -07:00
Apoorv Mishra 4354e1055e Keep nested docs in shared sidebar collapsed by default (#5208)
Co-authored-by: Tom Moor <tom@getoutline.com>
2023-08-20 07:04:04 -07:00
Apoorv Mishra c3a8858c6b fix: re-position hover preview correctly to prevent going out of page bounds (#5702) 2023-08-20 16:42:05 +05:30
Tom Moor 546022e5d6 fix: Allow webhooks to connct to private IPs when self-hosting, restore proxy compatability closes #5709 2023-08-20 07:03:33 -04:00
Tom Moor 33e532847e feat: Add Ukranian language support 2023-08-20 06:52:07 -04:00
Apoorv Mishra c9d62420c8 feat: send header (#5707) 2023-08-20 10:55:04 +05:30
Tom Moor cc2a1865c5 perf: Do not render KeyboardShortcuts guide unless clicked 2023-08-18 19:00:59 +02:00
Tom Moor 1ec87da8a9 fix: Add additional check for mobile device to bottom toolbar
closes #5703
2023-08-18 18:51:39 +02:00
Tom Moor d820b2a617 fix: Scrolling in desktop app sidebar is finicky 2023-08-18 18:45:38 +02:00
Tom Moor 5e7ea165b4 0.71.0 2023-08-18 11:11:32 +02:00
Tom Moor c68d55f49b fix: Inopperable image toolbar appears in read-only mode 2023-08-17 23:30:42 +02:00
Tom Moor 7e349c9db1 perf: Do not load state to calculate navigation node 2023-08-17 23:14:44 +02:00
Tom Moor 13b067fb3f fix: Document importer only replaces first base64 encoded image when there are multiple identical images in a document
closes #5653
2023-08-17 22:46:40 +02:00
Tom Moor 41c346d105 Revert "chore: Update browserslist"
This reverts commit fce90df3aa.
2023-08-17 10:41:36 +02:00
Tom Moor 4788ab3bd6 fix: Add support for Airtable share links with app ID 2023-08-16 22:20:55 +02:00
Tom Moor 5f00b4f744 fix: Incorrect error shown to user when connection limit is reached (#5695) 2023-08-16 12:39:56 -07:00
Tom Moor fd600ced09 fix: Flash of 'not found' screen when deleting a collection 2023-08-15 21:39:01 +02:00
Tom Moor 0047384d70 fix: Code blocks nested in list do not get line numbers 2023-08-15 19:52:16 +02:00
Tom Moor 8bff566c30 fix: Sidebar item misalignment 2023-08-15 11:32:19 +02:00
Tom Moor fce90df3aa chore: Update browserslist 2023-08-15 11:26:48 +02:00
Tom Moor 28ae1af2a3 fix: ctrl+a does not work on Windows in code block (#5692) 2023-08-14 13:16:12 -07:00
Tom Moor 9f0534d544 chore: Bump vite
Reduces full page reloads in dev, increase perf
2023-08-14 20:51:08 +02:00
Tom Moor 4edfab20fe fix: Bug with local dynamic reloading since moving to SSL 2023-08-14 20:48:49 +02:00
Philip Standt c38e045df2 feat: support self hosted grist (#5655)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-08-14 11:46:24 -07:00
Tom Moor b7bfc4bb1a chore: Remove optimize imports to allow vite upgrade (#5691) 2023-08-14 11:44:58 -07:00
dependabot[bot] a71ad43c31 chore(deps): bump nodemailer and @types/nodemailer (#5689)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 10:15:32 -07:00
dependabot[bot] 199fa5844e chore(deps): bump react-window from 1.8.7 to 1.8.9 (#5685)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 10:15:19 -07:00
dependabot[bot] b466f1c8bb chore(deps): bump ws from 7.5.6 to 7.5.9 (#5686)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 10:14:56 -07:00
dependabot[bot] 503e4e1f71 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 5.61.0 to 5.62.0 (#5688)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 10:14:40 -07:00
dependabot[bot] 2bc52be2cf chore(deps): bump email-providers from 1.13.1 to 1.14.0 (#5687)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-14 09:28:58 -07:00
github-actions[bot] 3ba730943c chore: Auto Compress Images (#5682)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2023-08-12 02:47:12 -07:00
Jack Woodgate 6828718cf0 feat: Add Google Maps Embed (#5667) (#5673)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-08-12 02:45:21 -07:00
Tom Moor 9749a53558 feat: Handle pasting iframe for supported embed 2023-08-12 11:44:16 +02:00
Tom Moor f4e4992508 fix: Remove fetch-with-proxy from DeliverWebhookTask 2023-08-11 22:35:38 +02:00
Tom Moor cf2f0b1b5c fix: Flash of empty state in sidebar when creating a new collection 2023-08-11 22:34:14 +02:00
Tom Moor 4a4ea0e531 fix: Text alignment on collection empty state 2023-08-11 22:30:48 +02:00
Tom Moor 8830773acb fix: Mobile styling bugs 2023-08-11 22:26:40 +02:00
Tom Moor f5d2c7890a fix: Unable to create collection with no access permission 2023-08-10 15:13:40 +02:00
Apoorv Mishra 434812dbe3 Allow vite to serve files from workspace's parent directory (#5675)
* fix: allow vite to serve files from workspace parent dir

* trigger ci

* trigger ci
2023-08-09 21:52:44 +05:30
Tom Moor ed5671209a New Crowdin updates (#5647) 2023-08-09 04:23:00 -07:00
Tom Moor c32cec7bff Add support for SSL in development (#5668) 2023-08-09 04:21:41 -07:00
dependabot[bot] 454a4e9a8d chore(deps): bump y-indexeddb from 9.0.9 to 9.0.11 (#5656)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-08-07 15:08:18 -07:00
dependabot[bot] ef9c410d97 chore(deps-dev): bump terser from 5.18.2 to 5.19.2 (#5658)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 14:56:21 -07:00
dependabot[bot] 7c2f779f68 chore(deps): bump fs-extra from 11.1.0 to 11.1.1 (#5657)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-07 14:56:04 -07:00
Tom Moor c45de6904b chore: Upgrade dd-trace 2023-08-07 17:54:54 -04:00
Tom Moor 4758778fc7 test 2023-08-06 13:10:50 -04:00
Apoorv Mishra 401ae73a04 Request validation for /api/collections.* (#5619) 2023-08-06 09:54:13 -07:00
Apoorv Mishra 0ddbd9c608 Calculate HoverPreview position inside useLayoutEffect (#5636) 2023-08-06 09:00:05 -07:00
Tom Moor 6c4e2a9d11 perf: Narrow scopes of Slack hook queries 2023-08-06 11:54:48 -04:00
Tom Moor d8f1f55a80 fix: type is optional input for integrations.list endpoint 2023-08-06 11:09:22 -04:00
Tom Moor 9b811c999d fix: Cannot exit code block with mod-enter shortcut with edit mode enabled 2023-08-05 19:45:54 -04:00
Tom Moor 5a60329021 fix: Unable to access document without reload after 24h+ session 2023-08-05 08:24:37 -04:00
Tom Moor 042ea7b61f Misc fixes from qa pass (#5650) 2023-08-04 20:40:36 -07:00
Tom Moor 80acc16791 fix: Badge's do not correctly use accent text color 2023-08-04 08:46:05 -04:00
Tom Moor 3c25b2b047 Merge branch 'main' of github.com:outline/outline 2023-08-04 08:45:15 -04:00
Adrien Ballet 16f1328a83 Added syntax highlighting for the Verilog and VHDL languages (#5641) 2023-08-03 20:26:41 -07:00
Tom Moor d1a7a30c00 fix: Closing find and replace on long document jumps to end 2023-08-03 22:41:49 -04:00
Tom Moor 5b67273d8f fix: Account for older desktop versions 2023-08-03 21:10:36 -04:00
Tom Moor fdd8ecc79d Add find and replace hooks for desktop app 2023-08-03 20:46:03 -04:00
Tom Moor 7c15d03b50 fix: Crash with some find characters
fix: Warning on close of find dialog
2023-08-03 19:32:09 -04:00
Tom Moor b691311f88 feat: Add find and replace interface (#5642) 2023-08-03 15:47:44 -07:00
Tom Moor eda023c908 Restore code blocks in notices 2023-08-01 21:42:19 -04:00
Apoorv Mishra 2331bbbd36 Request validation for /api/integrations.* (#5638) 2023-08-01 18:17:01 -07:00
Tom Moor 228d1faa9f feat: Add Czech translations, remove Russian translations 2023-08-01 19:43:33 -04:00
Tom Moor ff6d30581a New Crowdin updates (#5637) 2023-08-01 16:29:14 -07:00
Apoorv Mishra 027545a768 Close hover preview upon scroll (#5629) 2023-07-31 15:08:14 -07:00
Tom Moor 91585ee09d feat: Add tracking pixel to notifications for mark-as-read functionality (#5626) 2023-07-31 15:01:50 -07:00
Tom Moor a13f2c7311 New Crowdin updates (#5593) 2023-07-31 15:01:40 -07:00
dependabot[bot] d4a51b420f chore(deps-dev): bump vite-plugin-static-copy from 0.13.0 to 0.17.0 (#5631)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 15:01:20 -07:00
dependabot[bot] faa02623b3 chore(deps-dev): bump concurrently from 7.4.0 to 7.6.0 (#5632)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 14:59:31 -07:00
dependabot[bot] 2baf4d7d8b chore(deps): bump patch-package from 7.0.0 to 7.0.2 (#5630)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 14:59:23 -07:00
dependabot[bot] 2b21ac1b97 chore(deps-dev): bump @types/markdown-it-container from 2.0.5 to 2.0.6 (#5634)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 14:58:59 -07:00
Tom Moor d2fcd1dee6 fix: Skip unsupported node types when uploading
closes #5544
2023-07-30 15:52:08 -04:00
Tom Moor 3b43460a0a fix: Restrict content in notices, closes #5624 2023-07-29 23:42:58 -04:00
Tom Moor 1864ed605f fix: Allow copy code block to clipboard in read-only
closes #5614
2023-07-29 23:24:50 -04:00
Tom Moor 20932a08d0 fix: Selection jumps when dragging and selection ends outside editor bounds 2023-07-29 23:04:21 -04:00
Tom Moor 7e1ea69939 fix: Transparent thumbnails show document behind in hover previews 2023-07-29 22:51:14 -04:00
Tom Moor a3983c36c9 fix: Do not use CDN image component for hover card previews 2023-07-29 22:33:23 -04:00
Tom Moor ccdcda372f chore: Move last usage of sequelize.transaction to middleware 2023-07-29 22:30:26 -04:00
Tom Moor 07ad5032b4 Protect usage of navigator 2023-07-29 21:56:31 -04:00
Tom Moor 286aea2701 fix: Improve empty state for math blocks 2023-07-29 21:22:52 -04:00
Tom Moor 30e63e022c fix: Improve empty state for mermaid diagrams 2023-07-29 21:12:55 -04:00
Tom Moor b88670b58d fix: Improve emoji trigger for french language
closes #5611
2023-07-29 20:58:33 -04:00
Apoorv Mishra ddc883bfcd Preview arbitrary urls within a document (#5598) 2023-07-29 16:51:49 -07:00
Tom Moor 67691477a9 fix: Hover card timer should reset on url change 2023-07-29 19:51:22 -04:00
Apoorv Mishra e3807a1c75 fix: tests 2023-07-26 21:40:34 +05:30
Apoorv Mishra f95ce018e1 perf: cache response 2023-07-26 18:26:39 +05:30
Apoorv Mishra 2201fd7bd6 fix: description chopping and some cleanup 2023-07-26 13:08:43 +05:30
Apoorv Mishra fbb793ab8e fix: styles 2023-07-25 23:16:53 +05:30
Apoorv Mishra 31f8a3fb44 fix: hover card styling 2023-07-25 19:58:35 +05:30
Apoorv Mishra 03ebca2f0c fix: no overloading 2023-07-25 19:35:31 +05:30
Apoorv Mishra 2a17e0cbf6 fix: send user context for authorize calls 2023-07-25 19:35:31 +05:30
Apoorv Mishra 9ac1e13227 fix: just return 204 2023-07-25 19:35:31 +05:30
Apoorv Mishra bd0240b7a5 fix: handle errors from Iframely 2023-07-25 19:35:31 +05:30
Apoorv Mishra 81bd68380e feat: preview arbitrary url 2023-07-25 19:35:31 +05:30
Apoorv Mishra b3d8bd1cc8 cleanup: separate info and description 2023-07-25 19:35:31 +05:30
Apoorv Mishra a30487c2d7 fix: presentUnfurl 2023-07-25 19:35:31 +05:30
Apoorv Mishra 8b3c58a162 fix: coalesce to empty str 2023-07-25 19:35:30 +05:30
Apoorv Mishra 43a91626b2 feat: pipe external urls through iframely 2023-07-25 19:35:30 +05:30
Tom Moor 15c8a4867f fix: Text caret not placed in new math block after creation
fix: Excessive padding on inline math node
2023-07-25 00:04:14 -04:00
Tom Moor d94caf2783 fix: Missing translation for Slack hook 2023-07-24 23:41:34 -04:00
Tom Moor aaeb6f7dc6 fix: Flash of incorrect cursor when hover preview opens 2023-07-24 23:39:27 -04:00
Tom Moor e0289aed40 chore: Enable recommended React eslint rules (#5600) 2023-07-24 18:23:54 -07:00
dependabot[bot] 8865d394c6 chore(deps): bump @joplin/turndown-plugin-gfm from 1.0.47 to 1.0.49 (#5602)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 18:23:30 -07:00
dependabot[bot] 1d893a06f9 chore(deps): bump i18next from 22.5.0 to 22.5.1 (#5604)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 17:54:23 -07:00
dependabot[bot] 0c291ee806 chore(deps): bump styled-components and @types/styled-components (#5601)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 17:53:55 -07:00
dependabot[bot] 8732155dbb chore(deps-dev): bump @typescript-eslint/parser from 5.60.1 to 5.62.0 (#5605)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 17:51:13 -07:00
dependabot[bot] 56e01b784d chore(deps): bump sequelize from 6.29.0 to 6.32.1 (#5603)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-24 17:50:52 -07:00
Tom Moor e47d493d13 fix: Remove absolute positiioning of insights management, closes #5599 2023-07-24 08:28:35 -04:00
Tom Moor 2677c964a5 chore: Improve constraints on file_operations table 2023-07-23 19:51:42 -04:00
Tom Moor f8927ff819 tsc 2023-07-23 17:50:33 -04:00
j0ok34n 72adcd10ef Comment fix
- Workspace administrators will not be able to delete or edit comments within private collections for which they do not have permissions.
- Users will not be able to delete or modify their comments if they have been removed from a private collection.
2023-07-23 15:57:20 -04:00
Tom Moor 7bc37cb700 tsc 2023-07-23 13:11:02 -04:00
Tom Moor 217e53d8b6 fix: Enable toggling of insights while document is draft 2023-07-23 13:06:34 -04:00
Tom Moor 404f5ff871 Merge branch 'main' of github.com:outline/outline 2023-07-23 12:01:54 -04:00
Apoorv Mishra 0db6f39f43 Display correct info in hover preview (#5597) 2023-07-23 09:01:46 -07:00
Tom Moor 479b805613 Add per-document control over who can see viewer insights (#5594) 2023-07-23 09:01:36 -07:00
Tom Moor 48f1047016 chore: improve collections router 2023-07-22 16:39:47 -04:00
Tom Moor caf7333682 fix: Pass user context to document loader in urls unfurl 2023-07-22 16:07:21 -04:00
Tom Moor cd59af4a9b Allow service worker to serve cached unfurl responses 2023-07-22 13:32:01 -04:00
Tom Moor 8d549abaa9 Add rate limiting to unfurl endpoint 2023-07-22 13:27:58 -04:00
Tom Moor 5e705f3dc7 fix: Tweaks to hover card behavior 2023-07-22 12:47:01 -04:00
Apoorv Mishra 5d71398ea6 Preview mentions (#5571)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-07-22 09:13:09 -07:00
Tom Moor dbd85d62cb fix: Duplicate mentions results in duplicate notifications (#5585) 2023-07-21 05:49:14 -07:00
Tom Moor d180ecbe96 fix: Cropping of text on document lists on non-Mac platforms 2023-07-20 22:14:39 -04:00
Tom Moor 9046abb682 Hide 'Self hosted' settings on cloud 2023-07-20 22:01:48 -04:00
Tom Moor 5810ddb589 New Crowdin updates (#5525) 2023-07-20 18:41:11 -07:00
dependabot[bot] 0d30220017 chore(deps): bump @sentry/node from 7.51.2 to 7.59.2 (#5580)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-19 16:29:49 -07:00
Tom Moor b60e46a961 Restore empty table selection, closes #5581 2023-07-19 17:46:14 -04:00
Tom Moor 3c6e2aaac6 fix: Opening contextual menus sometimes change scroll position 2023-07-18 21:31:43 -04:00
Tom Moor eae6204d55 fix: Code toolbar in read-only 2023-07-18 19:39:23 -04:00
Tom Moor 1e78079ade Add SCSS and Sass code highlighting 2023-07-18 19:20:40 -04:00
dependabot[bot] d3fc6fc0fd chore(deps): bump winston from 3.8.2 to 3.10.0 (#5573)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 15:39:03 -07:00
dependabot[bot] 0f10fe4052 chore(deps): bump word-wrap from 1.2.3 to 1.2.4 (#5579)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 15:38:46 -07:00
Tom Moor d928d456de fix: Use correct error type when token is missing 2023-07-17 22:38:44 -04:00
Tom Moor 5206beaf19 fix: 'Plain text' language toolbar showing on code block in position 0 2023-07-17 22:33:47 -04:00
Tom Moor 70113be9af chore: Bump kbar 2023-07-17 22:18:08 -04:00
dependabot[bot] 04ea3431e7 chore(deps-dev): bump jest-cli from 29.5.0 to 29.6.1 (#5574)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 18:37:03 -07:00
dependabot[bot] d3ce70016e chore(deps-dev): bump eslint from 8.44.0 to 8.45.0 (#5572)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 18:25:51 -07:00
dependabot[bot] 46d6664307 chore(deps): bump validator and @types/validator (#5575)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-17 18:25:36 -07:00
Tom Moor 2427f4747a Rebuilding code block menus (#5569) 2023-07-17 18:25:22 -07:00
Tom Moor 60b456f35a closes #5570 2023-07-17 20:10:27 -04:00
Tom Moor 64b2718673 fix: Race condition on login 2023-07-17 19:06:31 -04:00
Tom Moor 4b14fa5dd7 Inherit 'full width' setting creating new child document
towards #5562
2023-07-15 23:21:59 -04:00
Tom Moor abb38ea447 fix: Server error with invalid Prosemirror JSON should be validation error 2023-07-15 23:04:30 -04:00
Tom Moor e81f97b2de Allow override of theme on shared documents 2023-07-15 21:36:04 -04:00
Tom Moor e653b185a4 fix: Regression loading shares in #5552
fix: Double auth.info load with multiple tabs open
fix: Request loop when suspended with multiple tabs open
2023-07-15 21:10:22 -04:00
Tom Moor 39e12cef65 chore: Use httpOnly authentication cookie (#5552) 2023-07-15 13:56:32 -07:00
Tom Moor b1230d0c81 fix: Improve code highlighting in dark mode
closes #5021
2023-07-15 16:54:55 -04:00
dependabot[bot] 6e9e1c15a5 chore(deps-dev): bump babel-jest from 29.5.0 to 29.6.1 (#5550)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-15 11:54:46 -07:00
Tom Moor 66331d3d4f Add csp nonce to all inline script tags (#5566) 2023-07-15 07:15:14 -07:00
Tom Moor ea07b72c7a fix: Show max 3 lines of content on notification items 2023-07-14 21:51:15 -04:00
Tom Moor 5dcd7a74ca fix: Remove no longer required unescaping, closes #5555 2023-07-14 21:46:31 -04:00
Tom Moor 5c83070941 fix: Pasting rich text into image caption inherits styling 2023-07-11 21:28:38 -04:00
Tom Moor a9ab196a18 fix: Guard against empty attachment size
I don't see how this can happen based on default props, but it does
2023-07-11 20:40:48 -04:00
Tom Moor b9fc301589 0.70.2 2023-07-11 19:00:36 -04:00
Tom Moor c56add74c6 fix: Azure single-tenant SSO tokens are unable to refresh (#5551) 2023-07-11 15:59:28 -07:00
dependabot[bot] 5ae4834333 chore(deps): bump pg-tsquery from 8.4.0 to 8.4.1 (#5548)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-10 20:00:15 -07:00
dependabot[bot] 437865e7aa chore(deps-dev): bump terser from 5.16.6 to 5.18.2 (#5549)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-10 19:59:31 -07:00
dependabot[bot] 042f2ff737 chore(deps-dev): bump @typescript-eslint/eslint-plugin from 5.60.1 to 5.61.0 (#5546)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-10 19:59:00 -07:00
Tom Moor 5656384cc4 fix: Error logging second parameter used as interpolation parameters 2023-07-08 15:35:06 -04:00
Tom Moor 098d91808b fix: Selection passed to setSelection must point at the current document, triple clicking caption 2023-07-08 15:02:44 -04:00
Tom Moor 21d446881e perf: Preconnect to CDN 2023-07-08 14:19:51 -04:00
Tom Moor cf32d227e6 fix: Error loading image: [object Event] 2023-07-08 13:57:25 -04:00
Tom Moor e59e121179 fix: Do not log errors for failed webhooks in hosted environment 2023-07-08 13:33:16 -04:00
Tom Moor 98a182c892 Improve reliability of embed regex (missing start char) 2023-07-08 12:04:03 -04:00
Tom Moor 6bc1b789ee fix: State of user preferences UI does not reflect defaults 2023-07-08 11:02:58 -04:00
Tom Moor a8674c7dda fix: Adding guard against double reload
closes #5384
2023-07-08 10:29:42 -04:00
Tom Moor c952dfa065 fix: Cannot unpin archived documents 2023-07-08 10:20:39 -04:00
Tom Moor 9a95fa47a0 fix: Error details are not output in development 2023-07-08 10:20:39 -04:00
dependabot[bot] 5bfb2c89c8 chore(deps): bump smooth-scroll-into-view-if-needed from 1.1.32 to 1.1.33 (#5517)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-08 06:49:11 -07:00
dependabot[bot] 9b6a645928 chore(deps): bump tough-cookie from 4.1.2 to 4.1.3 (#5543)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-08 05:49:23 -07:00
dependabot[bot] d550fb79d3 chore(deps): bump protobufjs from 7.1.2 to 7.2.4 (#5542)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-08 05:44:51 -07:00
Tom Moor ed9cf4cee3 fix: No visible error message when maximm pinned documents is reached 2023-07-07 08:34:50 -04:00
Tom Moor 8cc2853102 fix: Email for document update can include empty diff block 2023-07-07 08:23:42 -04:00
Tom Moor 814bacbead chore: Update node-fetch 2023-07-07 08:05:44 -04:00
Tom Moor 9431df45c2 0.70.1 2023-07-06 22:00:39 -04:00
Tom Moor a75d6b298e fix: Sanitize url missing in editor embeds and widgets 2023-07-06 21:38:02 -04:00
Tom Moor ff1bc5db2a fix: HTML export 2023-07-05 08:47:41 -04:00
Tom Moor e6e9512979 fix: Keyboard handlers should not be considered while composing 2023-07-05 08:47:41 -04:00
Tom Moor 29db1ef1bf Update Crowdin configuration file 2023-07-04 12:15:05 -04:00
Tom Moor b54a370e01 fix: Enter/Esc keys in content editable should not be considered while composing
closes #5523
2023-07-04 08:31:22 -04:00
Tom Moor cce22bcdee fix: Embed with underscore in url fails when hydrating from Markdown 2023-07-04 08:26:47 -04:00
Tom Moor da62c2c044 fix: Extra content in copying notice, closes #5522 2023-07-04 07:07:23 -04:00
dependabot[bot] 201690e342 chore(deps): bump @babel/preset-react from 7.18.6 to 7.22.5 (#5516)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-03 17:43:43 -07:00
dependabot[bot] 4fddc0fd87 chore(deps-dev): bump lint-staged from 13.1.0 to 13.2.3 (#5515)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-03 17:42:22 -07:00
Tom Moor 72c7b0373b fix: Small rendering flash in sidebar when document slug changes 2023-07-03 20:42:10 -04:00
dependabot[bot] 7c5d834f39 chore(deps): bump pg from 8.8.0 to 8.11.1 (#5518)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-03 16:42:28 -07:00
dependabot[bot] f1f3159b12 chore(deps-dev): bump yarn-deduplicate from 6.0.1 to 6.0.2 (#5519)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-03 16:42:12 -07:00
Tom Moor a62739be8f chore: Add allowUrls Sentry configuration to reduce spurious extension errors 2023-07-03 19:24:22 -04:00
Tom Moor 3124423eeb fix: Vertical movement in sidebar when entering title edit 2023-07-03 19:24:22 -04:00
Tom Moor 40dbbe10c5 fix: Small rendering flash in sidebar when document slug changes 2023-07-03 19:24:22 -04:00
Tom Moor a4ba1f18bc fix: Do not send document text when modifying title 2023-07-03 19:24:22 -04:00
Tom Moor 0aabcb8d22 Remove unused isOnlyTitle 2023-07-03 19:24:22 -04:00
Apoorv Mishra 3c2e7b5b63 Request validation for /api/subscriptions.* (#5476)
* chore: req validation for subscriptions.list

* chore: req validation for subscriptions.info

* chore: req validation for subscriptions.create

* chore: req validation for subscriptions.delete

* fix: reuse validations
2023-07-03 08:43:45 +05:30
Tom Moor 9d4a1965b0 0.70.0 2023-07-02 10:24:01 -04:00
Tom Moor ea527bf147 fix 2023-07-01 22:57:59 -04:00
Tom Moor 02744411f3 fix: Do not allow copy/pasting comment marks between documents (#5507) 2023-07-01 12:45:22 -07:00
Tom Moor f843a20a54 chore: Improves linting rule to catch mishandled promises (#5506) 2023-07-01 10:25:51 -07:00
Apoorv Mishra 7aec0e24ef fix: validation err (#5505) 2023-07-01 20:30:34 +05:30
Tom Moor 843092e5f0 test 2023-07-01 10:14:55 -04:00
Tom Moor 1fd7f75929 tsc 2023-07-01 10:11:38 -04:00
Apoorv Mishra 768fcbf6c4 Request validation for /api/stars.* (#5475)
* chore: req validation for stars.create

* chore: req validation for stars.list

* chore: req validation for stars.update

* chore: req validation for stars.delete

* fix: DRY

* fix: group validation attributes and message
2023-07-01 19:25:57 +05:30
Tom Moor f214db0ab7 fix: Scroll to document header on page load 2023-07-01 09:17:37 -04:00
Tom Moor aec190245b fix: No scroll to anchor if already exists 2023-06-30 19:07:36 -04:00
Tom Moor 88775cd287 fix: Database transaction used after committed 2023-06-30 17:15:40 -04:00
Tom Moor 64b2bfe704 fix: Unneccessary animation of sidebar on app load 2023-06-29 22:51:30 -04:00
Tom Moor 8957e86c12 fix: Add server-side validation of comment length 2023-06-29 22:41:57 -04:00
Tom Moor 4bec08ee05 tsc 2023-06-29 21:31:26 -04:00
Tom Moor a3d70622af Improve notifications empty state 2023-06-29 21:10:33 -04:00
Tom Moor 92c8eff61d fix: No need to validate SSO access immediately after sign-in 2023-06-29 21:08:49 -04:00
Tom Moor 73c2a67fa5 fix: Allow any SSO validation rather than _all_ 2023-06-29 21:08:49 -04:00
Tom Moor c2af5db0f8 fix: console error while building plugins without server folder 2023-06-29 21:08:49 -04:00
dependabot[bot] 1e4b59ac6c chore(deps): bump babel-plugin-styled-components from 2.0.7 to 2.1.4 (#5487)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-29 07:05:15 -07:00
dependabot[bot] 9933f30c25 chore(deps): bump react-table and @types/react-table (#5484)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-29 07:04:58 -07:00
Tom Moor bbee4b5791 Add control to enable debug logging in production 2023-06-28 20:26:15 -04:00
Tom Moor 89d5527d39 Handle promise linting (#5488) 2023-06-28 17:18:18 -07:00
Tom Moor f3d8129a13 fix: Await logout 2023-06-27 22:20:41 -04:00
Tom Moor 87a675d02b fix: Add /logout route to those that cannot be redirected after login 2023-06-27 19:51:37 -04:00
Tom Moor a2fae1f1eb fix: Keyboard navigation around inline code marks (#5477) 2023-06-26 15:28:42 -07:00
dependabot[bot] e001b8d161 chore(deps): bump sequelize-cli from 6.6.0 to 6.6.1 (#5483)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 10:50:29 -07:00
dependabot[bot] 5000500f96 chore(deps-dev): bump jest-environment-jsdom from 29.4.1 to 29.5.0 (#5485)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 10:20:33 -07:00
dependabot[bot] 8a33bdcb8a chore(deps): bump react-portal from 4.2.1 to 4.2.2 (#5486)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 10:20:23 -07:00
Apoorv Mishra 9987c15daf chore: req validation for api/developer (#5482) 2023-06-26 19:20:22 +05:30
Tom Moor 06f2d7a993 Reduce view writing 2023-06-26 09:23:47 -04:00
Apoorv Mishra a234a92f80 chore: schema for api/auth (#5481) 2023-06-26 18:37:18 +05:30
Apoorv Mishra 7314a71bf1 Resolve OIDC_DISPLAY_NAME mismatch (#5479)
* fix: oidc name mismatch

* trigger ci
2023-06-26 18:06:56 +05:30
Tom Moor edb9099c9d Cleanup intervals on destroyed views extension 2023-06-25 22:52:28 -04:00
Tom Moor 94882d4d3a Add connection rate limiting to collaboration server 2023-06-25 22:46:43 -04:00
Tom Moor 453bbb3b25 Bump hocuspocus 2023-06-25 18:59:01 -04:00
Tom Moor e58163ef5f Add more logging detail when _health endpoint fails 2023-06-25 16:13:58 -04:00
Tom Moor 7940cef517 Improve document revision creation (#5474) 2023-06-25 05:29:24 -07:00
Apoorv Mishra 86d6117a31 Request validation for /api/shares.* (#5467)
* chore: req validation for shares.info

* chore: req validation for shares.list

* chore: req validation for shares.update

* chore: req validation for shares.create

* chore: req validation for shares.revoke

* fix: review
2023-06-25 17:50:23 +05:30
Tom Moor 4e69ae1ffe fix: Descenders chopped on document list items on Windows 2023-06-24 17:04:40 -04:00
Tom Moor 06033ac781 Add HCL (terraform) to code languages 2023-06-24 16:48:45 -04:00
Tom Moor 25e8c32b84 fix: allow-storage-access-by-user-activation on embeds
closes #5471
2023-06-24 13:56:37 -04:00
Tom Moor 08601a9f84 fix: Error when importing collections with longer descriptions than 1000 chars
related #5472
2023-06-24 13:48:17 -04:00
Tom Moor 831318d941 fix: Invalid LOG_LEVEL in environment results in server crash with no displayed error message
Related: https://github.com/outline/outline/discussions/5466
2023-06-22 09:17:25 -04:00
Apoorv Mishra d96bf5106d chore: request validation for pins (#5465) 2023-06-22 15:57:00 +05:30
Tobi Kremer a094087342 Remove temporary files after processing (#5456)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-06-21 03:47:34 -07:00
Apoorv Mishra 8d69de1be0 chore: request validation for searches (#5460) 2023-06-21 10:38:38 +05:30
Tom Moor 6d556c7a55 Include collectionId in revisions.create webhook payload 2023-06-20 23:12:00 -04:00
Tom Moor eb62b961a4 feat: Add option to not include attachments in exported data (#5463) 2023-06-20 18:17:39 -07:00
Tom Moor 0e5a576439 fix: Clear document policies when public sharing option is updated
closes #5461
2023-06-20 21:17:13 -04:00
Tom Moor e7861d0bb9 fix: New checkbox items should not be checked by default
closes #3663
2023-06-19 20:50:58 -04:00
Tom Moor 25ae923130 fix: Cannot drag attachment without selecting first
closes #5040
2023-06-19 20:20:32 -04:00
Tom Moor d7ae829d92 Add sidebar toggle to command menu 2023-06-19 18:42:29 -04:00
Tom Moor cef048572a fix: Unable to click block action button on full width editor
closes #5444
2023-06-19 17:27:34 -04:00
dependabot[bot] 51ed458ab2 chore(deps): bump compressorjs from 1.1.1 to 1.2.1 (#5455)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 11:35:11 -07:00
dependabot[bot] 38e8a649ef chore(deps): bump @babel/core from 7.21.0 to 7.22.5 (#5453)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 10:24:07 -07:00
dependabot[bot] 127728db29 chore(deps): bump prosemirror-transform from 1.7.2 to 1.7.3 (#5454)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 10:23:55 -07:00
dependabot[bot] 8b87ab0fd7 chore(deps): bump @babel/plugin-transform-destructuring from 7.20.7 to 7.22.5 (#5451)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 10:13:33 -07:00
dependabot[bot] ba65c52e97 chore(deps): bump semver and @types/semver (#5452)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 10:08:21 -07:00
Tom Moor f76f2e61d8 Increase maximum index size, closes #5426 2023-06-19 12:54:04 -04:00
Tom Moor b3c08fdb48 fix: Add guard and log against corrupt zip 2023-06-18 07:43:14 -04:00
Tom Moor 9cfe5da70b fix: Error processing task in DetachDraftsFromCollectionTask 2023-06-18 07:38:57 -04:00
Tom Moor 5fa8ebc587 fix: Unneccessary retry of ValidateSSO task 2023-06-18 07:36:45 -04:00
Tom Moor 9ef375d83c fix: Import max length not correctly communicated on import (#5434) 2023-06-17 00:52:57 -07:00
Tom Moor 9d04d5ebd9 fix: Cursor jump on long title edit on Firefox (#5449) 2023-06-17 00:52:41 -07:00
Christian Rendl 4494a30441 Init app language with DEFAULT_LANGUAGE (#5445) 2023-06-17 00:52:12 -07:00
Tom Moor 7bce4c807d fix #5441 2023-06-14 09:24:20 +03:00
dependabot[bot] 80a9bae761 chore(deps): bump dottie from 2.0.2 to 2.0.4 (#5440)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 12:23:13 -07:00
dependabot[bot] f40e1f09fd chore(deps): bump react-merge-refs from 2.0.1 to 2.0.2 (#5436)
Bumps [react-merge-refs](https://github.com/gregberge/react-merge-refs) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/gregberge/react-merge-refs/releases)
- [Changelog](https://github.com/gregberge/react-merge-refs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gregberge/react-merge-refs/compare/v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: react-merge-refs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 20:56:32 +03:00
dependabot[bot] 2c3e842b3c chore(deps): bump prosemirror-model from 1.19.1 to 1.19.2 (#5438)
Bumps [prosemirror-model](https://github.com/prosemirror/prosemirror-model) from 1.19.1 to 1.19.2.
- [Changelog](https://github.com/ProseMirror/prosemirror-model/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prosemirror/prosemirror-model/compare/1.19.1...1.19.2)

---
updated-dependencies:
- dependency-name: prosemirror-model
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 20:55:52 +03:00
Tom Moor f1d1035550 Increase padding on lists 2023-06-11 18:57:55 +03:00
Tom Moor c23e415237 Update README.md 2023-06-11 09:18:26 +03:00
Tom Moor 137c33c323 fix: Grammar in error message 2023-06-10 22:14:59 +03:00
Tom Moor e00c30bd1f fix: Empty state text align 2023-06-10 22:11:30 +03:00
Tom Moor 1ddb9aba3b feat: Add Canva embed support 2023-06-10 17:03:12 +03:00
Tom Moor 746c27e718 fix: Another fix for heading scrolling 2023-06-10 16:00:51 +03:00
Tom Moor d319bb7d9a Allows commenting outside edit mode when seamless editing is disabled. (#5422) 2023-06-10 05:56:00 -07:00
Tom Moor 3f7e66980b fix: Remove requirement to have SLACK_CLIENT_ID to use SLACK_VERIFICATION_TOKEN 2023-06-10 15:31:27 +03:00
Tom Moor d5c1336580 fix: Error pasting code block into comment, closes #5418 2023-06-10 15:29:39 +03:00
Tom Moor a810d9176f Remove empty comment and mark on cancel 2023-06-07 23:34:50 +03:00
Tom Moor ffbf138748 closes #5403 2023-06-07 22:40:01 +03:00
dependabot[bot] b9844472b9 chore(deps): bump bull from 4.10.2 to 4.10.4 (#5414)
Bumps [bull](https://github.com/OptimalBits/bull) from 4.10.2 to 4.10.4.
- [Release notes](https://github.com/OptimalBits/bull/releases)
- [Changelog](https://github.com/OptimalBits/bull/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/OptimalBits/bull/compare/v4.10.2...v4.10.4)

---
updated-dependencies:
- dependency-name: bull
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 07:52:21 +03:00
dependabot[bot] 4363d4e1e5 chore(deps): bump query-string from 7.1.1 to 7.1.3 (#5415)
Bumps [query-string](https://github.com/sindresorhus/query-string) from 7.1.1 to 7.1.3.
- [Release notes](https://github.com/sindresorhus/query-string/releases)
- [Commits](https://github.com/sindresorhus/query-string/compare/v7.1.1...v7.1.3)

---
updated-dependencies:
- dependency-name: query-string
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 07:51:46 +03:00
dependabot[bot] 46c4185078 chore(deps-dev): bump @types/jsonwebtoken from 8.5.8 to 8.5.9 (#5416)
Bumps [@types/jsonwebtoken](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsonwebtoken) from 8.5.8 to 8.5.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsonwebtoken)

---
updated-dependencies:
- dependency-name: "@types/jsonwebtoken"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 07:51:26 +03:00
dependabot[bot] 424dea8197 chore(deps-dev): bump @types/tmp from 0.2.2 to 0.2.3 (#5417)
Bumps [@types/tmp](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/tmp) from 0.2.2 to 0.2.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/tmp)

---
updated-dependencies:
- dependency-name: "@types/tmp"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 07:51:06 +03:00
dependabot[bot] 0d0b53f292 chore(deps): bump vite from 4.1.3 to 4.1.5 (#5421)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.1.3 to 4.1.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v4.1.5/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.1.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 07:50:47 +03:00
Tom Moor d18994b14e Improve reliability by retrying failed imports (#5408) 2023-06-03 11:17:36 -07:00
Tom Moor a8a506af3e Merge branch 'tom/fix-html-paste' 2023-06-02 09:03:45 +01:00
Tom Moor ba3a47d138 Cleanup observer 2023-06-01 11:03:45 +01:00
Tom Moor c70bef0fdd fix: Pasting of HTML elements in new PM 2023-06-01 10:41:37 +01:00
Tom Moor 5f4e942d31 stash 2023-06-01 10:25:44 +01:00
Tom Moor 874bdb1e11 New Crowdin updates (#5331) 2023-05-30 17:12:54 -07:00
Apoorv Mishra 7f8a177b01 Use umzug to autorun migrations (#5281) 2023-05-30 17:12:38 -07:00
Tom Moor 5e76d72ae6 fix: Document search command menu action went missing, closes #5400 2023-05-30 19:49:05 -04:00
Tom Moor 45641103ba Allow viewing diff before revision is written (#5399) 2023-05-29 19:49:13 -07:00
dependabot[bot] 555691c79b chore(deps): bump @bull-board/koa from 4.12.1 to 4.12.2 (#5398)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 19:02:02 -07:00
dependabot[bot] 20ea422f77 chore(deps-dev): bump babel-plugin-tsconfig-paths-module-resolver from 1.0.3 to 1.0.4 (#5396)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 10:21:39 -07:00
dependabot[bot] 045dbb932e chore(deps): bump i18next from 22.4.15 to 22.5.0 (#5394)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 10:19:47 -07:00
dependabot[bot] 582c4ba99d chore(deps): bump core-js from 3.30.0 to 3.30.2 (#5395)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 10:18:42 -07:00
dependabot[bot] d519e93300 chore(deps-dev): bump @babel/cli from 7.21.0 to 7.21.5 (#5397)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 10:18:27 -07:00
Tom Moor 5dab811c5f fix: Improved guard on floating toolbar position calculation 2023-05-27 09:59:55 -04:00
Tom Moor ef7ae719a6 fix: Incorrect method binding on link serialization 2023-05-27 09:56:36 -04:00
Tom Moor aa80f5667f fix: Suggestion menus should close after typing space beyond trigger
closes #5387
2023-05-25 22:21:26 -04:00
Tom Moor d57ec39113 fix: Attachments in imported JSON reference files on previous instance
closes #5361
2023-05-25 22:09:08 -04:00
Tom Moor be3bcebf6b fix: Remove empty top-level list items in imported HTML content 2023-05-25 21:34:26 -04:00
Tom Moor e9ec31e5b8 fix: Spotify embed shows white background in dark mode 2023-05-25 19:58:01 -04:00
Tom Moor 33b0354cfe fix: Incorrect method binding on link serialization 2023-05-25 18:02:04 -04:00
Tom Moor d5341a486c chore: Upgrade all of prosemirror (#5366)
Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>
2023-05-24 19:24:05 -07:00
dependabot[bot] e340e568e2 chore(deps): bump socket.io-parser from 4.2.1 to 4.2.3 (#5382)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 18:16:22 -07:00
Tom Moor e8b9a1b650 fix: AwarenessChangeEvent type 2023-05-22 23:10:05 -04:00
Tom Moor bb0cd891bd fix: Remove old policies from frontend when collection sharing permission changes 2023-05-22 22:30:53 -04:00
dependabot[bot] fbd16d4b9a chore(deps-dev): bump prettier from 2.1.2 to 2.8.8 (#5372)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-05-22 19:14:56 -07:00
Tom Moor 3317bf2396 fix: User presence is not updated when leaving a document 2023-05-22 21:05:40 -04:00
dependabot[bot] 4e75b4029a chore(deps): bump react-virtualized-auto-sizer from 1.0.5 to 1.0.17 (#5373)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-22 14:56:48 -07:00
dependabot[bot] 73fe70817f chore(deps-dev): bump @types/throng from 5.0.3 to 5.0.4 (#5374)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-22 14:56:38 -07:00
Tom Moor 3c5dc10446 fix: Notification from unknown actor causes app crash 2023-05-22 09:31:18 -04:00
Tom Moor d587360f4b fix: Show desktop sign-in errors within the app 2023-05-21 11:54:38 -04:00
Tom Moor 458f24185a fix: Flashing sidebar on load (suspense boundary) 2023-05-20 21:04:33 -04:00
Tom Moor 502d8b9e8d fix: Tweak back button on desktop app 2023-05-20 18:51:28 -04:00
Tom Moor 7e6831c803 Add notification count to dock icon on desktop 2023-05-20 18:01:55 -04:00
Tom Moor 965d85fb6f fix: Delayed mount around all sidebar loading indicators 2023-05-20 17:20:47 -04:00
Tom Moor 31b9c2b8a4 Improve data prefetching, less false positives 2023-05-20 17:11:40 -04:00
Tom Moor dbad4a9b84 fix: Missing association 2023-05-20 11:47:32 -04:00
Tom Moor f3caaed7fe fix: Scroll notifications to top on open 2023-05-20 11:43:25 -04:00
Tom Moor ac6047bbb7 fix: Mobile hover states make notifications unscrollable 2023-05-20 11:32:05 -04:00
Tom Moor ea885133ac Notifications interface (#5354)
Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>
2023-05-20 07:47:32 -07:00
Tom Moor b1e2ff0713 fix: Various command bar fixes 2023-05-18 18:36:12 -04:00
DandrewsDev dca64fe84b Update providerId to fallback to id in the absence of a sub field. (#5343) 2023-05-18 06:09:08 -07:00
Tom Moor 1e50facd5d chore: collection actions 2023-05-17 23:20:05 -04:00
Tom Moor ce87624289 fix: n.languages is undefined (type seems incorrect here?) 2023-05-17 22:50:47 -04:00
Tom Moor a19c19985e fix: Potential missmatch between selected language preference and browser language preference 2023-05-17 20:23:39 -04:00
Tom Moor 9b257e9593 Animate appearance of pinned documents 2023-05-17 20:13:09 -04:00
Tom Moor aff9413b0f chore: Bump socket.io 2023-05-15 23:38:55 -04:00
Tom Moor de46178871 chore: Bump patch-package 2023-05-15 23:07:00 -04:00
Tom Moor fd700e6fd6 Install curl and update-ca-certificates in container
closes #5277
2023-05-15 23:04:38 -04:00
dependabot[bot] b2ab3b010d chore(deps): bump dd-trace from 3.14.1 to 3.21.0 (#5348)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 15:13:27 -07:00
dependabot[bot] ff72d381fb chore(deps): bump fetch-retry from 5.0.3 to 5.0.5 (#5349)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 15:13:02 -07:00
dependabot[bot] a24f09afe3 chore(deps-dev): bump @types/formidable from 2.0.5 to 2.0.6 (#5351)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 15:12:42 -07:00
dependabot[bot] a6844c7c8a chore(deps): bump vm2 from 3.9.17 to 3.9.18 (#5353)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 15:12:33 -07:00
dependabot[bot] fadf51907d chore(deps): bump tiny-cookie from 2.4.0 to 2.4.1 (#5350)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 15:12:19 -07:00
Tom Moor 42dea7859c chore: Dependency bumps (#5342) 2023-05-13 12:12:02 -07:00
dependabot[bot] 164263f13a chore(deps): bump yjs from 13.5.39 to 13.6.1 (#5320)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-13 11:24:08 -07:00
Mario Noll 35dbeae80b Add OCI image source label (#5338) 2023-05-13 11:23:39 -07:00
Tom Moor e2bc2f2067 Transfer changes from enterprise codebase 2023-05-13 12:30:24 -04:00
Tom Moor 7ce97f4d50 feat: Enable admins to list all collections in workspace 2023-05-11 22:25:12 -04:00
Tom Moor 0ce9931910 fix: Line numbers overlay code when block is horizontally scrollable 2023-05-11 21:47:26 -04:00
Tom Moor 693dfecab7 fix: Reorder code block language choice 2023-05-11 21:35:51 -04:00
Tom Moor 86a7d1c548 New Crowdin updates (#5321) 2023-05-10 17:55:06 -07:00
Conner 44ed374636 feat: add syntax highlighting for jsx and tsx (#5330) 2023-05-10 17:37:31 -07:00
dependabot[bot] 8c5c445f0d chore(deps): bump emoji-regex from 10.0.0 to 10.2.1 (#5317)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [emoji-regex](https://github.com/mathiasbynens/emoji-regex) from 10.0.0 to 10.2.1.
- [Commits](https://github.com/mathiasbynens/emoji-regex/compare/v10.0.0...v10.2.1)

---
updated-dependencies:
- dependency-name: emoji-regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 06:25:32 -07:00
dependabot[bot] 2a0780cfff chore(deps-dev): bump i18next-parser from 7.7.0 to 7.9.0 (#5319)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [i18next-parser](https://github.com/i18next/i18next-parser) from 7.7.0 to 7.9.0.
- [Release notes](https://github.com/i18next/i18next-parser/releases)
- [Changelog](https://github.com/i18next/i18next-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-parser/compare/7.7.0...7.9.0)

---
updated-dependencies:
- dependency-name: i18next-parser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 06:25:16 -07:00
Tom Moor 8d157ff962 fix: Re-focus comment input after comment 2023-05-08 22:52:34 -04:00
Tom Moor 26a8c5e4ab fix: Revert #5278 2023-05-08 22:37:24 -04:00
Tom Moor d9d15bffa5 Merge branch 'feat/ga4-support' 2023-05-08 22:16:48 -04:00
Tom Moor bb2ee9dd40 single 2023-05-08 22:16:21 -04:00
Tom Moor 90b13d5f27 Move 'public branding' option to Settings -> Details 2023-05-08 21:01:08 -04:00
Tom Moor 679a86fe6f Merge branch 'feat/custom-branding' 2023-05-08 19:04:07 -04:00
Tom Moor ab30bfcf24 fix: Cannot sign-in with Gmail on desktop app 2023-05-08 19:03:56 -04:00
Tom Moor 9dfdafa116 fix: Increase collection pagination limit to max, closes #5311 2023-05-08 17:00:13 -04:00
Tom Moor 06be19090c feat: Add support for parsing Confluence notices 2023-05-08 16:09:49 -04:00
Tom Moor 07ae67924f Use team name and favicon (when public branding enabled) on shared links 2023-05-08 14:46:25 -04:00
Tom Moor 1cf597aca7 feat: Add support for GA4 measurement IDs in GOOGLE_ANALYTICS_ID 2023-05-08 12:01:35 -04:00
Tom Moor a0df79ea5a feat: Allow embeds to be used inside tables (#5315) 2023-05-07 18:05:54 -07:00
Newton 738fa55e12 fix: use real boolean instead of aws's bool (#5313) 2023-05-07 14:13:16 -07:00
Apoorv Mishra c8ee501377 Request validation for cron (#5307)
* chore: add validations for /api/cron.*

* fix: coerce limit to number

* fix: review
2023-05-07 10:41:20 +05:30
Rohan Sharma 3421f24896 fix: package.json & yarn.lock to reduce vulnerabilities (#5288)
Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2023-05-06 15:27:05 -07:00
dependabot[bot] 33e67a11ed chore(deps): bump socket.io-client from 4.5.4 to 4.6.1 (#5176)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-04 20:59:07 -07:00
Tom Moor cfe7bebd95 New Crowdin updates (#5243) 2023-05-04 20:06:14 -07:00
Tom Moor ac8946f0c5 fix: Admins should be able to add and remove themselves from collections 2023-05-04 21:52:59 -04:00
Tom Moor 0504e91aa6 fix: Restore edit permission for workspace admins in non-private collections, closes #5300 2023-05-04 21:04:43 -04:00
Tom Moor aebd626954 fix: Error receiving document update for non-preloaded collection 2023-05-04 20:30:10 -04:00
Tom Moor 9942bbee3e fix: Refactor attachment downloads during export to use promises (#5294
* Refactor attachment downloads during export to use promises instead of streams
Date attachments in zip file correctly

* tsc
2023-05-04 17:20:33 -07:00
Chris Aumann d096ba486f Remove "millisecond" suffix from getSignedUrl() function (#5302) 2023-05-04 17:20:02 -07:00
Tom Moor be5cddc14f fix: Duplicate Slack notifications on doc publish 2023-05-02 22:52:35 -04:00
Tom Moor 6e12e8be3a Update 'New issue' links to be more accurate
closes #5292
2023-05-02 21:47:48 -04:00
Tom Moor 9918b9bf13 feat: Add 'delete user' option for admins 2023-05-02 20:14:12 -04:00
Apoorv Mishra 3d6a875631 fix: allow null for subdomain (#5289) 2023-05-02 18:19:08 +05:30
Tom Moor cda8acddbb fix: Horizontal scrollbars with full-width documents 2023-05-01 21:15:17 -04:00
Tom Moor 2ceba5039b Add additional debug logging to InternalOAuthError case 2023-05-01 20:40:23 -04:00
Tom Moor 7d7781d795 Add additional debug logging to no user OIDC case
Related #5241
2023-05-01 20:23:35 -04:00
dependabot[bot] 5ee6cdb2ca chore(deps): bump sequelize-cli from 6.4.1 to 6.6.0 (#5283)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [sequelize-cli](https://github.com/sequelize/cli) from 6.4.1 to 6.6.0.
- [Release notes](https://github.com/sequelize/cli/releases)
- [Changelog](https://github.com/sequelize/cli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sequelize/cli/compare/v6.4.1...v6.6.0)

---
updated-dependencies:
- dependency-name: sequelize-cli
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 14:09:37 -07:00
dependabot[bot] 454a338d24 chore(deps-dev): bump nodemon from 2.0.21 to 2.0.22 (#5284)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.21 to 2.0.22.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.21...v2.0.22)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 14:09:20 -07:00
Tom Moor 85299c6104 Add missing websocket event 2023-05-01 09:26:02 -04:00
Tom Moor 001a083e15 fix: Pasting single Markdown paragraph adds newlines above and below
closes #5264
2023-04-30 20:28:42 -04:00
Tom Moor 7ec4e20546 Revert 2023-04-30 18:10:43 -04:00
Tom Moor 94202920f8 fix: Error receiving document update for non-preloaded collection 2023-04-30 17:45:27 -04:00
Tom Moor f2ea8daf65 Remove no longer used notification_settings table
closes #5062
2023-04-30 17:38:10 -04:00
Tom Moor df1c360b2a fix: Line number alignment in code blocks nested in lists
closes #5217
2023-04-30 16:47:40 -04:00
Tom Moor 60b15b7b46 Upgrade docker image to Node 18 2023-04-30 15:49:19 -04:00
Tom Moor 9280904476 fix: Hidden scrollbars cause movement when navigating context menus, closes #5272 2023-04-30 15:43:46 -04:00
Tom Moor 20f3c55914 Various sidebar fixes (#5278
* fix: Right sidebar depth
Re-arrange order of document metadata

* fix: Comment reply not focused on 'Reply…' tap

* fix: Sidebar animation oddities on mobile/Safari
2023-04-30 12:42:05 -07:00
Tom Moor d8b4fef554 feat: Collection admins (#5273
* Split permissions for reading documents from updating collection

* fix: Admins should have collection read permission, tests

* tsc

* Add admin option to permission selector

* Combine publish and create permissions, update -> createDocuments where appropriate

* Plural -> singular

* wip

* Quick version of collection structure loading, will revisit

* Remove documentIds method

* stash

* fixing tests to account for admin creation

* Add self-hosted migration

* fix: Allow groups to have admin permission

* Prefetch collection documents

* fix: Document explorer (move/publish) not working with async documents

* fix: Cannot re-parent document to collection by drag and drop

* fix: Cannot drag to import into collection item without admin permission

* Remove unused isEditor getter
2023-04-30 06:38:47 -07:00
amplitudes 2942e9c78e Return window origin instead of host (#5276) 2023-04-29 20:36:23 -07:00
Tom Moor 4b810bcdb7 0.69.1 2023-04-29 22:45:21 -04:00
Tom Moor 12bfa6c58d Add additional debug logging to export 2023-04-29 22:05:52 -04:00
Tom Moor ba2bfc7c89 fix: recursive require in test env 2023-04-27 22:31:12 -04:00
Tom Moor 0f8c444af0 Add DD monitoring for simultaneous server connections 2023-04-27 21:48:51 -04:00
Tom Moor 4dade03c33 Allow workspace admins to remove comments (#5270) 2023-04-27 18:34:01 -07:00
Tom Moor ef075c0fa2 fix: Not possible to place caret within existing comment
closes #5268
2023-04-27 20:21:23 -04:00
Tom Moor 4f019b7a99 Add new cron service, useful in dev to automatically run scheduled tasks and can be used in single-server deployments to avoid an external dependency 2023-04-26 22:14:10 -04:00
Tom Moor 217d41332f Automatically error file operations running longer than 12 hours 2023-04-26 21:55:00 -04:00
Tom Moor f1ce23dce9 fix: Webhook category subscriptions do not work correctly, closes #5257 2023-04-26 08:59:24 -04:00
Tom Moor 01707d733a fix: Cannot delete FileOperation referencing collection 2023-04-25 21:58:24 -04:00
Tom Moor 106b335602 fix: Error when pasting embeddable content into comments 2023-04-25 21:56:23 -04:00
Tom Moor b0da3b7cab fix: Throwing event as error 2023-04-24 23:35:46 -04:00
dependabot[bot] 6b978fc780 chore(deps): bump koa and @types/koa (#5250)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [koa](https://github.com/koajs/koa) and [@types/koa](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/koa). These dependencies needed to be updated together.

Updates `koa` from 2.13.4 to 2.14.2
- [Release notes](https://github.com/koajs/koa/releases)
- [Changelog](https://github.com/koajs/koa/blob/2.14.2/History.md)
- [Commits](https://github.com/koajs/koa/compare/2.13.4...2.14.2)

Updates `@types/koa` from 2.13.5 to 2.13.6
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/koa)

---
updated-dependencies:
- dependency-name: koa
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: "@types/koa"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-24 16:28:57 -07:00
dependabot[bot] 473eb93377 chore(deps): bump winston from 3.3.3 to 3.8.2 (#5251)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [winston](https://github.com/winstonjs/winston) from 3.3.3 to 3.8.2.
- [Release notes](https://github.com/winstonjs/winston/releases)
- [Changelog](https://github.com/winstonjs/winston/blob/master/CHANGELOG.md)
- [Commits](https://github.com/winstonjs/winston/compare/v3.3.3...v3.8.2)

---
updated-dependencies:
- dependency-name: winston
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-24 16:28:49 -07:00
dependabot[bot] c418829810 chore(deps): bump react-waypoint from 10.1.0 to 10.3.0 (#5252)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [react-waypoint](https://github.com/civiccc/react-waypoint) from 10.1.0 to 10.3.0.
- [Release notes](https://github.com/civiccc/react-waypoint/releases)
- [Changelog](https://github.com/civiccc/react-waypoint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/civiccc/react-waypoint/compare/v10.1.0...v10.3.0)

---
updated-dependencies:
- dependency-name: react-waypoint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-24 16:28:35 -07:00
Tom Moor d4da028527 0.69.0 2023-04-23 20:31:21 -04:00
Tom Moor e8355171e9 New Crowdin updates (#5224 2023-04-23 12:20:59 -07:00
Apoorv Mishra 86062f396d Deleting a collection should detach associated drafts from it (#5082)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-04-23 12:20:44 -07:00
Tom Moor 7250c0ed64 tsc 2023-04-23 13:38:17 -04:00
Tom Moor 71b2cd1c46 Add success notice style (#5242
* Add success notice style

* Move quote styling closer to notices
Improving parsing of notices when pasting from other tools
2023-04-23 10:34:40 -07:00
Tom Moor 7620d37009 fix: Improve handling of max payload size 2023-04-23 12:38:04 -04:00
Tom Moor 076b854b49 ApiContext -> AppContext 2023-04-23 10:04:18 -04:00
Tom Moor 4134eced2c fix: Hide floating toolbar when dragging content (#5239) 2023-04-23 06:36:06 -07:00
Apoorv Mishra 20d85e3d3a Allow admin to change member's name (#5233)
* feat: allow admins to change user names

* fix: review
2023-04-22 20:48:51 +05:30
Tom Moor f79cba9b55 fix: Newlines added around pasted text content, closes #5236 2023-04-22 10:13:43 -04:00
Tom Moor e2c5fda610 fix: Do not copy edit path from headers
chore: Rename url -> path in routeHelpers
closes #5229
2023-04-22 10:00:09 -04:00
Tom Moor 4b5680a16e fix: Document hover preview should not show for the same document 2023-04-22 09:29:01 -04:00
Tom Moor 43c2e6880a fix: Documents on mobile horizontally scrollable 2023-04-21 23:04:25 -04:00
Tom Moor 53c25a5689 fix: Scroll to end of comment thread, not start 2023-04-21 18:56:23 -04:00
Tom Moor 3e5cd9eb3c fix: Infinite loop connecting Slack in self-hosted
closes https://github.com/outline/outline/discussions/4993
2023-04-21 18:09:28 -04:00
Tom Moor 7740ee2046 Merge branch 'main' of github.com:outline/outline 2023-04-21 18:00:37 -04:00
dependabot[bot] 4cde29541d chore(deps): bump vm2 from 3.9.16 to 3.9.17 (#5232)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.16 to 3.9.17.
- [Release notes](https://github.com/patriksimek/vm2/releases)
- [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/patriksimek/vm2/compare/3.9.16...3.9.17)

---
updated-dependencies:
- dependency-name: vm2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-20 14:44:27 -07:00
Tom Moor af6eb4897e chore: Upgrade mammoth 2023-04-20 10:21:32 -04:00
Tom Moor 54cf3fb8b1 fix: Move rate limiting middleware infront of auth
Tighten rate limits on attachment, comment, and group creation
2023-04-19 22:10:11 -04:00
Apoorv Mishra fb8d8f8159 fix: unwatch migrations dir (#5228) 2023-04-19 18:43:09 +05:30
Apoorv Mishra dadba3f3af Autorun migrations in community edition (#5141)
* fix: autorun migrations in community edition

* re-run tests

* refactor

* fix: review

* fix: double error
2023-04-19 09:27:50 +05:30
Tom Moor f4206f888c fix: Rare unable to login case 2023-04-18 22:14:58 -04:00
Tom Moor 961afe7dc5 fix: Full-width images have margin on side since #5197 2023-04-18 20:11:11 -04:00
Tom Moor e4fb151a71 fix: NaN invalid CSS width issue 2023-04-18 19:49:56 -04:00
Tom Moor d04b15a04b New Crowdin updates (#5206 2023-04-18 16:38:50 -07:00
Tom Moor 1642eb610d fix: Double recursive loops can cause server lockup on deeply nested docs (#5222) 2023-04-18 16:38:35 -07:00
Tom Moor bcffd81c9c Log more debugging info on queue processing 2023-04-18 04:07:38 -04:00
Tom Moor f91cdc3296 Add ability to reset custom theme 2023-04-17 22:48:07 -04:00
Tom Moor c52909fa17 fix: Notice should not be based on theme accent, which may be red/orange etc 2023-04-17 22:42:13 -04:00
Tom Moor 94b4496ae8 fix: Positioning of 'Open' button in embed frames 2023-04-17 22:27:14 -04:00
dependabot[bot] f97b87407e chore(deps-dev): bump eslint-config-prettier from 8.7.0 to 8.8.0 (#5210)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.7.0 to 8.8.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.7.0...v8.8.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-17 19:27:09 -07:00
dependabot[bot] a069350ffa chore(deps-dev): bump @types/enzyme from 3.10.12 to 3.10.13 (#5209)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@types/enzyme](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/enzyme) from 3.10.12 to 3.10.13.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/enzyme)

---
updated-dependencies:
- dependency-name: "@types/enzyme"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-17 19:26:55 -07:00
dependabot[bot] c521c2dcb5 chore(deps-dev): bump @types/katex from 0.14.0 to 0.16.0 (#5211)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@types/katex](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/katex) from 0.14.0 to 0.16.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/katex)

---
updated-dependencies:
- dependency-name: "@types/katex"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-17 19:26:45 -07:00
Tom Moor 746f4e4150 fix: Allow strikethrough of inline code (#5207
* fix: Allow strikethrough of inline code

* Remove unneccessary change
2023-04-17 19:26:36 -07:00
Tom Moor f2b3524d87 fix: Ctrl-a/e in code fences 2023-04-16 09:49:19 -04:00
Tom Moor aa04a5e6f4 fix: Avoid label rendering bug in Mermaid, closes #5196 2023-04-15 10:25:22 -04:00
Tom Moor 2b38368fcd Add list indent/outdent controls on mobile (#5205) 2023-04-15 05:44:23 -07:00
Tom Moor 9c063c9f65 New Crowdin updates (#5164
* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Hebrew translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]
2023-04-14 14:07:07 -07:00
Apoorv Mishra 138c3f1ebe Cursor should remain at the start and title should remain editable (#5199) 2023-04-14 14:06:53 -07:00
Tom Moor 169a99f21e Adds a 60px area to the left and right of editable area (#5197
* Adds a 60px area to the left and right of editable area that allows clicking to focus paragraphs

* tsc
2023-04-13 19:24:33 -07:00
Tom Moor 515f5e8e73 fix: Right sidebar header should be draggable on desktop 2023-04-13 22:14:18 -04:00
Tom Moor facf7cb19a fix: Flash of full suggestions in editor popover when closing 2023-04-13 09:54:41 -04:00
Tom Moor 7cd3bf8859 Add note on comment when edited 2023-04-13 09:52:39 -04:00
Tom Moor 2d354f95fa Add note on comment when edited 2023-04-13 09:17:26 -04:00
Tom Moor 094c4486ce fix: 'Observing' banner creates non-draggable titlebar area on desktop app 2023-04-13 09:09:56 -04:00
Tom Moor 7c44e116fc fix: Various fixes for commenting on mobile (#5195
* fix: Comment sidebar chopped on mobile
fix: Zoom on comment input focus on mobile

* fix: Always show reply option on mobile

* fix: Auto-expand comment sidebar if linked to a specific comment
2023-04-12 19:00:00 -07:00
Tom Moor 821c9368f6 fix: profile.name is not mandatory anymore in OIDC provder 2023-04-12 21:59:24 -04:00
Apoorv Mishra 511e790cb1 Toggle visibility of comment UI based on policy (#5143) 2023-04-12 18:11:58 -07:00
dependabot[bot] 8bd797aed7 chore(deps): bump vm2 from 3.9.15 to 3.9.16 (#5194)
Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.15 to 3.9.16.
- [Release notes](https://github.com/patriksimek/vm2/releases)
- [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/patriksimek/vm2/compare/3.9.15...3.9.16)

---
updated-dependencies:
- dependency-name: vm2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-12 17:48:05 -04:00
Tom Moor 0eef79e6e6 Enable commenting by default 2023-04-11 22:42:56 -04:00
Tom Moor d6b51f3053 fix: Tweak mention style in comments to be more visible 2023-04-11 22:41:05 -04:00
Tom Moor 49d903d6d4 chore: Remove console.log left in code and added eslint rule to prevent it happening again 2023-04-11 22:15:52 -04:00
Tom Moor a9800165c1 fix: Some authentication notices not displayed, injection of arbitrary strings 2023-04-11 21:54:53 -04:00
Apoorv Mishra 3e20c437fa Dummy SMTP env values (#5186) 2023-04-11 16:38:35 -07:00
Apoorv Mishra 21d6fbed87 Collection memberships required to be preloaded before publishing a document (#5187) 2023-04-11 16:38:25 -07:00
Tom Moor 9da99f6955 chore: Parallelize build (#5182
* Parallelize build

* Update package.json
2023-04-10 20:32:04 -07:00
dependabot[bot] a6f1d99b56 chore(deps): bump jsdom from 21.0.0 to 21.1.1 (#5179)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [jsdom](https://github.com/jsdom/jsdom) from 21.0.0 to 21.1.1.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/21.0.0...21.1.1)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 19:12:26 -07:00
dependabot[bot] 4be35d1983 chore(deps-dev): bump @babel/preset-typescript from 7.21.0 to 7.21.4 (#5178)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.21.0 to 7.21.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.21.4/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 16:37:27 -07:00
dependabot[bot] bcbf2e7fc5 chore(deps): bump inline-css from 4.0.1 to 4.0.2 (#5180)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [inline-css](https://github.com/jonkemp/inline-css) from 4.0.1 to 4.0.2.
- [Release notes](https://github.com/jonkemp/inline-css/releases)
- [Commits](https://github.com/jonkemp/inline-css/compare/v4.0.1...v4.0.2)

---
updated-dependencies:
- dependency-name: inline-css
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 16:36:47 -07:00
dependabot[bot] 1b2ecb2798 chore(deps): bump core-js from 3.28.0 to 3.30.0 (#5181)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.28.0 to 3.30.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.30.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 16:36:00 -07:00
Tom Moor 60dbad765a chore: Cleanup editor menu handlers (#5174
* wip

* wip

* refactor
2023-04-10 15:50:21 -07:00
Tom Moor 70f3a998a4 Update dependabot.yml
Stop putting PR's in for major dependency updates
2023-04-10 15:49:57 -07:00
Tom Moor 75aea90972 chore: Editor 'plugin' -> 'extension'
They've always been called extensions, not sure why the folder was plugins. Part of ongoing spring cleaning
2023-04-09 17:27:09 -04:00
Tom Moor 2f9a56aa6f Centralize default user and team preferences. (#5172
Passing the fallback at each callpoint was dumb
2023-04-09 14:23:58 -07:00
Tom Moor 8324b03938 fix: Expand sidebar items on shared document on activation 2023-04-08 14:21:25 -04:00
Tom Moor 64ed25c1a2 Shrink font-size in sidebar and command menu 1pt 2023-04-08 14:17:04 -04:00
Tom Moor 3115bbd5ef chore: Name API keys consistently as the model 2023-04-08 14:16:49 -04:00
Tom Moor aab3a49f2c chore: Bump outline-icons (#5170
* Bump outline-icons to default use currentColor

* wip
2023-04-08 08:16:05 -07:00
Tom Moor 489cfcd0b0 Revert "refactor"
This reverts commit 6e79b93a53.
2023-04-08 10:19:15 -04:00
Tom Moor c82b05a044 fix: React devmode warnings (#5169
* fix: React warning: Cannot change state from within render

* Remove usage of react-side-effect
2023-04-08 07:17:31 -07:00
Tom Moor dcb15bae13 Revert "Upgrade MermaidJS (#5043" (#5167
This reverts commit c97110e72b.
2023-04-08 06:40:00 -07:00
Tom Moor 9c9ceef8ee Notifications refactor (#5151
* Ongoing

* refactor

* test

* Add cleanup task

* refactor
2023-04-08 06:22:49 -07:00
Tom Moor c97110e72b Upgrade MermaidJS (#5043
* Upgrade MermaidJS

* fix: Flashing of diagrams while editing another

* Upgrade vite

* type imports
2023-04-08 06:20:42 -07:00
Tom Moor db73879918 Assorted cleanup, minor bug fixes, styling fixes, eslint rules (#5165
* fix: Logic error in toast
fix: Remove useless component

* fix: Logout not clearing all stores

* Add icons to notification settings

* Add eslint rule to enforce spaced comment

* Add eslint rule for arrow-body-style

* Add eslint rule to enforce self-closing components

* Add menu to api key settings
Fix: Deleting webhook subscription does not remove from UI
Split webhook subscriptions into active and inactive
Styling updates
2023-04-08 05:25:20 -07:00
Tom Moor 422bdc32d9 Add 's' method to access theme props (#5163) 2023-04-07 19:43:34 -07:00
Tom Moor c202198d61 fix: Wide selection of comment toolbar fixes (#5160
* fix: Margin on floating toolbar
fix: Flash of toolbar on wide screens

* fix: Nesting of comment marks

* fix: Post button not visible when there is a draft comment, makes it look like the comment is saved
fix: Styling of link editor results now matches other menus
fix: Allow small link editor in comments sidebar

* fix: Cannot use arrow keys to navigate suggested links
Added animation to link suggestions
Added mixin for text ellipsis

* fix: Link input appears non-rounded when no creation option

* Accidental removal
2023-04-07 15:52:57 -07:00
Tom Moor a5c44ee961 New Crowdin updates (#5066
* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]
2023-04-07 15:52:48 -07:00
dependabot[bot] d0483be133 chore(deps): bump vm2 from 3.9.11 to 3.9.15 (#5161)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.11 to 3.9.15.
- [Release notes](https://github.com/patriksimek/vm2/releases)
- [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/patriksimek/vm2/compare/3.9.11...3.9.15)

---
updated-dependencies:
- dependency-name: vm2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-07 15:52:33 -07:00
Tom Moor 195df69e59 fix: Another mention positioning patch 2023-04-05 22:42:51 -04:00
Tom Moor 1f3d7506d7 Add additional error boundaries, improve display and reload behavior 2023-04-05 21:57:58 -04:00
Tom Moor 24729fa0d4 fix: Table cell selection background should be based on accent color 2023-04-05 21:27:39 -04:00
Tom Moor a585a7d66b fix: Arrow navigation of mentions menu inside a table causes caret to move 2023-04-05 21:07:40 -04:00
Tom Moor 6c16ffb99a fix: Initial positioning of mention menu in comments 2023-04-05 20:06:24 -04:00
Tom Moor 99e4b458df fix: Improve ranking of results in editor menus when filtering using command-score 2023-04-05 18:37:50 -04:00
Tom Moor 9a7ecd7403 fix: Passing of start parameter to YouTube embed 2023-04-05 12:48:48 -04:00
Tom Moor 9573026fdd fix: Move comments empty state text to fixed position 2023-04-05 09:39:30 -04:00
Tom Moor 2458085eed fix: Draft comment on text gets into a strange state when unfocused (#5153) 2023-04-05 06:02:26 -07:00
Tom Moor 3ca86bcc0c fix: Draft comment on text gets into a strange state when unfocused 2023-04-04 23:06:07 -04:00
Tom Moor 1b11cb5aca fix: Missing space in translation string 2023-04-04 22:11:40 -04:00
Tom Moor c71cbf39f5 Open downloads in the same tab 2023-04-04 21:38:30 -04:00
Tom Moor 4a99f9f386 fix: Mentions do not show any options in public collections (#5150)
* Mentions do not show any options in public collections

* Avoid reset data while loading
2023-04-03 18:05:22 -07:00
dependabot[bot] 5421f92a9f chore(deps-dev): bump eslint-import-resolver-typescript from 3.5.2 to 3.5.4 (#5147)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 3.5.2 to 3.5.4.
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.5.2...v3.5.4)

---
updated-dependencies:
- dependency-name: eslint-import-resolver-typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-03 14:50:15 -07:00
dependabot[bot] de58d0fb86 chore(deps-dev): bump @types/nodemailer from 6.4.4 to 6.4.7 (#5148)Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@types/nodemailer](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/nodemailer) from 6.4.4 to 6.4.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/nodemailer)

---
updated-dependencies:
- dependency-name: "@types/nodemailer"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-03 14:49:50 -07:00
Hai 2e28a631b6 Pass query params to authorize endpoint during OIDC login (#5129) 2023-04-02 11:55:09 -07:00
Tom Moor c6068d0fee fix: Styling inconsistency on anchors in headings, closes #5126 2023-04-02 14:50:51 -04:00
Tom Moor cf3689014b fix: Email notifications not sent when mention added to edited comment (#5145
* WIP: Need new email template

* New emails
2023-04-02 11:46:47 -07:00
Tom Moor 40103c9d8f Wait to scroll comments until sidebar animation is complete
Cleanup some unused code
2023-04-02 11:41:41 -04:00
Apoorv Mishra 16a5be1aa6 Additional policy regarding comments on a document (#5130)
* feat: comment policy on document

* fix: add alongside read
2023-04-02 19:21:13 +05:30
Tom Moor 1be1371171 Add image resizing to history stack (allow undo)
Remove placeholder SVG when main image is loaded
2023-04-02 09:19:09 -04:00
Apoorv Mishra 046fe522c1 fix: remove userId col from documents (#5133) 2023-03-31 09:17:58 +05:30
Tom Moor ec3ebb91c0 Adds placeholder during image loading (#5120
* Adds placeholder during image loading

* Small refactor
2023-03-29 20:12:55 -07:00
Tom Moor 381d640719 Auto-reload app every 24h when inactive 2023-03-29 22:01:45 -04:00
Tom Moor f8a6a4b840 fix: Comment button does not appear immediately on focus of document comment input
closes #5118
2023-03-29 20:47:21 -04:00
Tom Moor ace18ce336 fix: Soft breaks after text with comment mark does not work.
Note: This CSS was added waaaay back here: https://github.com/outline/rich-markdown-editor/commit/2d5d5d3e4e17ee517b214243a146b19d9b1dacb4
Since then the equivalent rule has moved to be more specific and this was vestigial.

closes #5119
2023-03-29 18:42:01 -04:00
Tom Moor 794df52080 fix: NotionImportTask 2023-03-29 09:34:04 -04:00
Tom Moor 8a2831ef80 fix: Add support for Zip files created natively on Windows
closes #5117
2023-03-29 08:28:51 -04:00
Tom Moor 980e613a7b fix: Download as Markdown should use .md extension
closes #5113
2023-03-29 07:43:40 -04:00
Tom Moor f86ae64a69 test 2023-03-28 22:44:08 -04:00
Tom Moor a2f1f059c7 fix: Users not mentionable when not in seamless editing mode 2023-03-28 22:32:47 -04:00
Tom Moor 7ba6a9379b Removal of non-collaborative editing code paths (#4210) 2023-03-28 19:13:42 -07:00
Tom Moor 3108a26793 fix: Trim document titles on save, closes #5084 2023-03-28 21:20:57 -04:00
Apoorv Mishra 1b1cd1c8d4 API to fetch users who have read/write permission on a document collection (#5047) 2023-03-28 17:54:32 -07:00
Tom Moor fcc89be622 fix: File uploads can remove document closeby document content, closes #5097 2023-03-28 20:47:34 -04:00
Tom Moor 6040015b8d fix: Regression in 05a8e45f01 overrides image upload behavior 2023-03-28 20:26:19 -04:00
Aditya Sharma 05a8e45f01 Feat: zoom selected image on pressing space key (#5059) 2023-03-28 05:33:22 -07:00
Tom Moor ce294bd1e7 fix: KaTeX parsing on shared links 2023-03-27 21:02:24 -04:00
Tom Moor 8cc4cff0d7 fix: Allow stylesheets to load from CDN 2023-03-27 20:23:54 -04:00
Tom Moor e182dafeac fix: Improve readability of inline code in dark theme
closes #5096
2023-03-27 20:03:42 -04:00
Tom Moor b5e7b7e3ef fix: path not available in browser 2023-03-27 19:40:34 -04:00
dependabot[bot] eab7d17c83 chore(deps): bump zod from 3.20.6 to 3.21.4 (#5103)
Bumps [zod](https://github.com/colinhacks/zod) from 3.20.6 to 3.21.4.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Changelog](https://github.com/colinhacks/zod/blob/master/CHANGELOG.md)
- [Commits](https://github.com/colinhacks/zod/compare/v3.20.6...v3.21.4)

---
updated-dependencies:
- dependency-name: zod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 14:54:06 -07:00
Tom Moor e2e0b01143 fix: Entire header should not become transparent on desktop blur
closes #4700
2023-03-23 23:50:47 -04:00
Tom Moor 45a603f76f fix: Avoid print breaking across image 2023-03-23 23:12:09 -04:00
dependabot[bot] c7e95df5ce chore(deps): bump @joplin/turndown-plugin-gfm from 1.0.45 to 1.0.47 (#5074)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-22 20:28:06 -07:00
Tom Moor d11e17c68b fix: Remove mathml rendering, closes #5080 2023-03-22 22:23:12 -04:00
Tom Moor 8281e4a094 Remove dollar escaping in importer, no longer needed.
closes #5070
2023-03-22 21:58:17 -04:00
Tom Moor 114019c4d8 fix: Comment thread not focused correctly when clicking on mark, closes #5081 2023-03-22 21:49:52 -04:00
Tom Moor e86f17a6f0 fix: Update shortcut documentation for LaTeX 2023-03-22 21:35:34 -04:00
Tom Moor aec8f14836 fix: Link search in editor 2023-03-21 08:51:30 -04:00
Tom Moor 7321970504 Move health check endpoint back to server root 2023-03-19 15:07:34 -04:00
Tom Moor 827c912887 fix: Impossible to type more than one dollar symbol in a paragraph without triggering LaTeX (#5061) 2023-03-19 11:37:17 -07:00
Tom Moor 39eac5c6a6 chore: Upgrade lib0 (#5063) 2023-03-19 11:34:38 -07:00
Tom Moor 68640860fb /_health endpoint now checks the database and redis connections 2023-03-18 12:37:34 -04:00
Tom Moor dafc4fb609 Add curl to base image to make healthchecks easier 2023-03-18 11:27:03 -04:00
Tom Moor c17fc8421e New Crowdin updates (#4930
* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]
2023-03-18 07:07:49 -07:00
Tom Moor 45831e9469 Remove NotificationSettings table (#5036
* helper

* Add script to move notification settings

* wip, removal of NotificationSettings

* event name

* iteration

* test

* test

* Remove last of NotificationSettings model

* refactor

* More fixes

* snapshots

* Change emails to class instances for type safety

* test

* docs

* Update migration for self-hosted

* tsc
2023-03-18 06:32:41 -07:00
Tom Moor 41f97b0563 fix: Users should not be redirected to disabled authentication providers (#5055
* fix: Users should not be redirected to disabled authentication providers
Re-enabled tests in plugin directory

* Fix plugin http tests
2023-03-18 06:17:54 -07:00
Tom Moor 6dd4afccaf fix: Context binding,
closes #5056
2023-03-18 09:17:25 -04:00
Aditya Sharma b68eba4b63 [GH-4699]: Improve share dialog for nested docs (#4719)
Co-authored-by: Tom Moor <tom@getoutline.com>
2023-03-17 14:26:55 -07:00
Jonas Chevalier 17f6d68707 feat: add support for Nix code highlight (#4781
Nix is a build system and package manager and used in one of the top-10
most active repos on GitHub.
2023-03-17 12:58:08 -07:00
Tom Moor 316520dbb0 test 2023-03-17 11:59:33 -04:00
Tom Moor e69935be99 Remove username column (#5052) 2023-03-17 08:23:32 -07:00
Tom Moor 497ab4b89f fix: YouTube links with timestamp cannot be embedded, closes #5051 2023-03-17 11:09:31 -04:00
Tom Moor d2e9910908 Update documentation links 2023-03-16 18:49:56 -07:00
Apoorv Mishra 21a44428f4 Filter groups given a member (#5034)
* feat: filter groups given a member

* Revert "feat: filter groups given a member"

This reverts commit 7dac8bb38d.

* fix: make it work via db query
2023-03-16 12:31:56 +05:30
Tom Moor 6a29104d09 fix: Mermaid diagrams flash when editing and multiple in document 2023-03-15 22:51:40 -04:00
Tom Moor d663b92f2a tsc 2023-03-13 21:08:52 -04:00
Tom Moor 4182cbd5d0 chore: Refactoring some editor controls (#5023)
* Refactor EmojiMenu

* Refactor CommandMenu to functional component

* Remove more direct props, refactor to useEditor

* Remove hardcoded IDs

* Refactor SelectionToolbar to functional component

* fix: Positioning of suggestion menu on long paragraphs
2023-03-13 18:05:06 -07:00
Tom Moor f6ac73a741 Add sanitization to log messages to reduce chance of tokens ending up in server logs 2023-03-13 20:42:22 -04:00
dependabot[bot] 1e2eb00ace chore(deps-dev): bump jest-cli from 29.4.1 to 29.5.0 (#5029)
Bumps [jest-cli](https://github.com/facebook/jest/tree/HEAD/packages/jest-cli) from 29.4.1 to 29.5.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.5.0/packages/jest-cli)

---
updated-dependencies:
- dependency-name: jest-cli
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 16:09:24 -07:00
dependabot[bot] 00549b21a8 chore(deps-dev): bump terser from 5.16.5 to 5.16.6 (#5028)
Bumps [terser](https://github.com/terser/terser) from 5.16.5 to 5.16.6.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.16.5...v5.16.6)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 16:09:01 -07:00
Tom Moor e2dff9afca fix: Viewers cannot delete their own comments 2023-03-11 19:08:12 -05:00
Tom Moor e9ece9125a fix: Comment deletion is not propagated correctly 2023-03-11 19:01:19 -05:00
Tom Moor 2c84036a3a test 2023-03-11 14:16:39 -05:00
Tom Moor 3eabb30949 fix: favicon, apple touch icon, etc not loaded from CDN 2023-03-11 14:10:13 -05:00
Tom Moor af0485fa12 lint 2023-03-09 22:27:40 -05:00
Tom Moor e786888dfb fix: Remove image float and positioning options in comments (#5014)
* cleanup

* Split Image into SimpleImage

* ts
2023-03-09 19:17:16 -08:00
Tom Moor 8fc4cb846a tsc 2023-03-09 21:26:08 -05:00
Tom Moor a3d93c12e0 Add support for opening document sidebar (comments,history,insights) on mobile 2023-03-09 18:58:50 -05:00
Tom Moor 96c90dbb29 fix: Correct cursor on document metadata under title 2023-03-08 22:10:26 -05:00
Mohamed ELIDRISSI e2429f6d85 refactor: add server side validation schema for fileOperations (#4989)
* refactor: move files to subfolder

* refactor: schema for fileOperations.info

* refactor: schema for fileOperations.list

* refactor: schema for fileOperations.delete

* refactor: schema for fileOperations.redirect
2023-03-08 19:01:51 -08:00
Limezy c039501035 Tldraw (#4968)
* Tldraw + Castopod

* Remove Castopor

* Remove files

* Update database.json

* Update database.json

* Updated tests + correctly escaped dots
2023-03-08 19:01:34 -08:00
Tom Moor 6ad76903b9 fix: Styling of metadata under revision title 2023-03-08 20:01:28 -05:00
Tom Moor f21f890cb7 fix: Styling of metadata under revision title 2023-03-08 20:01:03 -05:00
Tom Moor f5d326e237 fix: Missordering of command menu 2023-03-08 19:50:13 -05:00
Tom Moor f48889d77d fix: Template left in tooltip, closes #5009 2023-03-08 19:34:42 -05:00
Tom Moor 4fd6e450ab Enable commenting beta 2023-03-07 21:14:15 -05:00
Tom Moor 6e23f34133 fix: Ensure editor command menus cannot escape rhs of screen 2023-03-07 21:13:16 -05:00
Tom Moor 58f2b9aa2b fix: Invited users should not appear as option in @mention, closes #5006 2023-03-07 20:44:41 -05:00
Tom Moor d3b099819d feat: Add @mention support to comments (#5001)
* Refactor, remove confusing 'packages' language

* Basic notifications when mentioned in comment

* fix: Incorrect trimming of comments

* test
2023-03-06 19:19:49 -08:00
Tom Moor 28c4854985 fix: More strict handling of paste board images 2023-03-06 20:30:29 -05:00
dependabot[bot] 234651448e chore(deps): bump datadog-metrics from 0.10.2 to 0.11.0 (#4998)
* chore(deps): bump datadog-metrics from 0.10.2 to 0.11.0

Bumps [datadog-metrics](https://github.com/dbader/node-datadog-metrics) from 0.10.2 to 0.11.0.
- [Release notes](https://github.com/dbader/node-datadog-metrics/releases)
- [Commits](https://github.com/dbader/node-datadog-metrics/compare/v0.10.2...v0.11.0)

---
updated-dependencies:
- dependency-name: datadog-metrics
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Remove no longer required types package

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-03-06 17:05:36 -08:00
Tom Moor ba13a25a78 fix: Editor menu collapses wrong direction, regressed in #4938 2023-03-06 19:37:42 -05:00
Tom Moor 5c12f52c8d do not send mention and document published emails to one user 2023-03-06 19:37:42 -05:00
dependabot[bot] aaf6a0cb41 chore(deps-dev): bump nodemon from 2.0.20 to 2.0.21 (#4995)
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.20 to 2.0.21.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.20...v2.0.21)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 16:13:07 -08:00
dependabot[bot] 477d28e37e chore(deps-dev): bump i18next-parser from 7.1.0 to 7.7.0 (#4996)
Bumps [i18next-parser](https://github.com/i18next/i18next-parser) from 7.1.0 to 7.7.0.
- [Release notes](https://github.com/i18next/i18next-parser/releases)
- [Changelog](https://github.com/i18next/i18next-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/i18next-parser/compare/7.1.0...7.7.0)

---
updated-dependencies:
- dependency-name: i18next-parser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 16:12:58 -08:00
dependabot[bot] 4e2864a3f9 chore(deps-dev): bump eslint-config-prettier from 8.5.0 to 8.7.0 (#4999)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.5.0 to 8.7.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.5.0...v8.7.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 16:12:46 -08:00
Tom Moor 4ba5d0d8e0 Tweaks, do not send mention and document updated emails to one user 2023-03-06 18:08:17 -05:00
Apoorv Mishra de031b365c Capability to mention users in a document (#4838)
* feat: mention user

* fix: trigger api call on every letter typed

* fix: this allows command menu to re-render upon props change, shouldComponentUpdate prevented re-rendering when necessary

* fix: add node

* fix: mention node styling

* fix: Caret not visible after inserting mention

* fix: apply mentionRule

* fix: label is to be obtained from content, not attrs

* feat: add mentions table and model

* fix: typo

* fix: make all mention nodes visible in shared doc

* feat: parse mention ids from doc text

* feat: MentionsProcessor

* feat: documents.publish tests

* feat: tests for MentionsProcessor

* feat: schedule notifs for mentions

* fix: get rid of Mention model

* fix: put actor id and mention id in raw md

* Revert "fix: put actor id and mention id in raw md"

This reverts commit 3bb8a22e3c560971dccad6d2f82266256bcb2d96.

* Revert "Revert "fix: put actor id and mention id in raw md""

This reverts commit 3c5b36c40cebf147663908cf27d0dce6488adfad.

* fix: review

* fix: no need of set

* fix: show avatar

* fix: get rid of eventName

* fix: font-weight

* fix: prioritize mention notifs

* fix: store id in md

* fix: no need of prepending m

* fix: fetchPage

* fix: Avatars incorrect color

* fix: remove scanRE

* fix: test

* fix: include alphabet other than latin

* lockfile

* fix: regex should test for letters, marks and digits

---------

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-03-06 14:54:57 -08:00
dependabot[bot] 09435ed798 chore(deps): bump @braintree/sanitize-url from 6.0.0 to 6.0.2 (#4982)
Bumps [@braintree/sanitize-url](https://github.com/braintree/sanitize-url) from 6.0.0 to 6.0.2.
- [Release notes](https://github.com/braintree/sanitize-url/releases)
- [Changelog](https://github.com/braintree/sanitize-url/blob/main/CHANGELOG.md)
- [Commits](https://github.com/braintree/sanitize-url/compare/v6.0.0...v6.0.2)

---
updated-dependencies:
- dependency-name: "@braintree/sanitize-url"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-05 18:39:39 -08:00
Tom Moor 591a87b728 Suppress comment notifications when viewing document (#4987)
* Updating views from collaboration server

* refactor

* Suppress comment notifications based on views

* test
2023-03-05 18:33:46 -08:00
Tom Moor f9709897fe fix: Code comment and comment marker classes clash 2023-03-05 17:53:53 -05:00
Tom Moor b795c992fe Change comment sidebar to per-document persistence, closes #4985 2023-03-05 16:59:29 -05:00
Tom Moor 69c7bf6100 Remove duplicate store for right sidebar width, increase default size 2023-03-05 16:43:07 -05:00
Tom Moor ac3284986c fix: Replies to comments in threads only trigger notifications to document subscribers, closes #4984 2023-03-05 16:19:56 -05:00
Tom Moor 646afec491 fix: Cannot access menu on threaded comments, closes #4983 2023-03-05 16:03:13 -05:00
Tom Moor 760355302c Comment notification emails (#4978)
* Comment notification emails

* fix links
fix threading in email inboxes
from is now commenter name

* fix

* refactor

* fix async filter
2023-03-05 08:01:56 -08:00
github-actions[bot] 4ff0fdfb4f chore: Compressed inefficient images automatically (#4971)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2023-03-04 07:00:10 -08:00
Limezy e4fadd01d9 Fix 4952 (#4967)
* First try

* Support old embeds
2023-03-03 08:28:16 -08:00
Mohamed ELIDRISSI bef9673530 refactor: add server side validation schema for views (#4953)
* refactor: move files to subfolder

* refactor: schema for views.list

* refactor: schema for views.create
2023-02-28 18:20:27 -08:00
dependabot[bot] 9a96230976 chore(deps): bump dd-trace from 3.9.3 to 3.14.1 (#4945)
Bumps [dd-trace](https://github.com/DataDog/dd-trace-js) from 3.9.3 to 3.14.1.
- [Release notes](https://github.com/DataDog/dd-trace-js/releases)
- [Commits](https://github.com/DataDog/dd-trace-js/compare/v3.9.3...v3.14.1)

---
updated-dependencies:
- dependency-name: dd-trace
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 18:20:18 -08:00
Tom Moor e90e111139 fix: Cannot upload multiple files at once from editor command menu (#4957) 2023-02-28 16:52:07 -08:00
Tom Moor e4ec1681d5 fix: Cannot scroll on mobile with image on screen 2023-02-28 18:59:22 -05:00
Tom Moor 739a291a46 fix: Cannot read properties of undefined (reading 'message') 2023-02-28 18:55:25 -05:00
Tom Moor 402406a3f7 Search for docs matching selected text when opening link editor 2023-02-28 08:58:45 -05:00
Tom Moor 372c46e2ad Escape to defocus editor 2023-02-27 23:27:17 -05:00
Tom Moor 69612641ce Improve leave animation on new thread form 2023-02-27 23:00:27 -05:00
Tom Moor 58ff82e7b9 fix: Floating toolbar on comments too tight 2023-02-27 21:09:52 -05:00
dependabot[bot] 18905535d3 chore(deps-dev): bump eslint-plugin-react-hooks from 4.2.0 to 4.6.0 (#4944)
Bumps [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/HEAD/packages/eslint-plugin-react-hooks) from 4.2.0 to 4.6.0.
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/HEAD/packages/eslint-plugin-react-hooks)

---
updated-dependencies:
- dependency-name: eslint-plugin-react-hooks
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 17:24:49 -08:00
dependabot[bot] 0ca44223ea chore(deps-dev): bump terser from 5.16.3 to 5.16.5 (#4946)
Bumps [terser](https://github.com/terser/terser) from 5.16.3 to 5.16.5.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.16.3...v5.16.5)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 17:24:27 -08:00
dependabot[bot] cf561e3482 chore(deps): bump ioredis from 5.2.4 to 5.3.1 (#4947)
Bumps [ioredis](https://github.com/luin/ioredis) from 5.2.4 to 5.3.1.
- [Release notes](https://github.com/luin/ioredis/releases)
- [Changelog](https://github.com/luin/ioredis/blob/main/CHANGELOG.md)
- [Commits](https://github.com/luin/ioredis/compare/v5.2.4...v5.3.1)

---
updated-dependencies:
- dependency-name: ioredis
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 17:24:12 -08:00
Tom Moor fff0812659 Various commenting improvements (#4941)
* fix: New threads attached to previous as replies

* fix: Cannot use floating toolbar properly in comments

* perf: Avoid re-writing history on click in editor

* fix: Comment on text selection

* fix: 'Copy link' on comments uses wrong hostname

* Show comment buttons on input focus rather than non-empty input
Increase maximum sidebar size

* Allow opening comments from document menu

* fix: Clicking comment menu should not focus thread

* fix: Selection color

* fix: Draft comments not restored

* Add border above document level comment input

* fix: Floating toolbar not constrainted by offset parent

* fix flash of no comment on saving

* fix: Clicking on editor does not remove draft mark
2023-02-27 16:50:35 -08:00
Apoorv Mishra 6b00ced48f fix: use LOG_LEVEL to set server log severity (#4937) 2023-02-27 21:36:01 +05:30
Tom Moor 51909772a4 Webhook support for comments (#4932)
* fix: Restore newlines in code line numbers as safety measure

* Add comments to webhook payloads
2023-02-26 11:20:00 -08:00
Tom Moor 08df14618c Various commenting improvements (#4938)
* fix: New threads attached to previous as replies

* fix: Cannot use floating toolbar properly in comments

* perf: Avoid re-writing history on click in editor

* fix: Comment on text selection

* fix: 'Copy link' on comments uses wrong hostname

* Show comment buttons on input focus rather than non-empty input
Increase maximum sidebar size

* Allow opening comments from document menu

* fix: Clicking comment menu should not focus thread
2023-02-26 11:19:12 -08:00
Tom Moor b813f20f8f fix: Tab no longer works to nest lists (regression from comment merge) 2023-02-25 22:48:31 -05:00
Tom Moor f0484c8417 fix: Restore newlines in code line numbers as safety measure 2023-02-25 17:51:31 -05:00
Tom Moor 64371b82d1 fix: Use of this inside functional component (bad merge) 2023-02-25 16:38:17 -05:00
Mohamed ELIDRISSI 00baa2bd6d refactor: add server side validation schema for groups (#4881)
* refactor: move files to subfolder

* refactor: schema for groups.list

* refactor: schema for groups.info

* refactor: schema for groups.create

* refactor: schema for groups.update

* refactor: schema for groups.delete

* refactor: schema for groups.memberships

* refactor: schema for groups.add_user

* refactor: schema for groups.remove_user
2023-02-25 12:03:23 -08:00
Tom Moor fc8c20149f feat: Comments (#4911)
* Comment model

* Framework, model, policy, presenter, api endpoint etc

* Iteration, first pass of UI

* fixes, refactors

* Comment commands

* comment socket support

* typing indicators

* comment component, styling

* wip

* right sidebar resize

* fix: CMD+Enter submit

* Add usePersistedState
fix: Main page scrolling on comment highlight

* drafts

* Typing indicator

* refactor

* policies

* Click thread to highlight
Improve comment timestamps

* padding

* Comment menu v1

* Change comments to use editor

* Basic comment editing

* fix: Hide commenting button when disabled at team level

* Enable opening sidebar without mark

* Move selected comment to location state

* Add comment delete confirmation

* Add comment count to document meta

* fix: Comment sidebar togglable
Add copy link to comment

* stash

* Restore History changes

* Refactor right sidebar to allow for comment animation

* Update to new router best practices

* stash

* Various improvements

* stash

* Handle click outside

* Fix incorrect placeholder in input
fix: Input box appearing on other sessions erroneously

* stash

* fix: Don't leave orphaned child comments

* styling

* stash

* Enable comment toggling again

* Edit styling, merge conflicts

* fix: Cannot navigate from insights to comments

* Remove draft comment mark on click outside

* Fix: Empty comment sidebar, tsc

* Remove public toggle

* fix: All comments are recessed
fix: Comments should not be printed

* fix: Associated mark should be removed on comment delete

* Revert unused changes

* Empty state, basic RTL support

* Create dont toggle comment mark

* Make it feel more snappy

* Highlight active comment in text

* fix animation

* RTL support

* Add reply CTA

* Translations
2023-02-25 12:03:05 -08:00
Tom Moor 59e25a0ef0 fix: New Japanese translations from Crowdin (#4927) 2023-02-25 11:15:33 -08:00
Apoorv Mishra af3edd7cb2 fix: coalesce falsy body to {} (#4929) 2023-02-25 11:14:44 -08:00
dependabot[bot] 05c5d0637e chore(deps): bump koa-body from 4.2.0 to 6.0.1 (#4806)
* chore(deps): bump koa-body from 4.2.0 to 6.0.1

Bumps [koa-body](https://github.com/koajs/koa-body) from 4.2.0 to 6.0.1.
- [Release notes](https://github.com/koajs/koa-body/releases)
- [Changelog](https://github.com/koajs/koa-body/blob/master/CHANGELOG.md)
- [Commits](https://github.com/koajs/koa-body/compare/v4.2.0...v6.0.1)

---
updated-dependencies:
- dependency-name: koa-body
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update types

* test

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-02-24 05:11:49 -08:00
Tom Moor f7a62e2497 New Crowdin updates (#4909) 2023-02-23 20:15:17 -08:00
dependabot[bot] 51aa6c5c30 chore(deps): bump @bull-board/koa from 4.6.2 to 4.12.1 (#4906)
Bumps [@bull-board/koa](https://github.com/felixmosh/bull-board/tree/HEAD/packages/koa) from 4.6.2 to 4.12.1.
- [Release notes](https://github.com/felixmosh/bull-board/releases)
- [Changelog](https://github.com/felixmosh/bull-board/blob/master/CHANGELOG.md)
- [Commits](https://github.com/felixmosh/bull-board/commits/v4.12.1/packages/koa)

---
updated-dependencies:
- dependency-name: "@bull-board/koa"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-23 19:19:27 -08:00
dependabot[bot] 9d9df81dec chore(deps): bump sequelize from 6.20.1 to 6.29.0 (#4921)
* chore(deps): bump sequelize from 6.20.1 to 6.29.0

Bumps [sequelize](https://github.com/sequelize/sequelize) from 6.20.1 to 6.29.0.
- [Release notes](https://github.com/sequelize/sequelize/releases)
- [Commits](https://github.com/sequelize/sequelize/compare/v6.20.1...v6.29.0)

---
updated-dependencies:
- dependency-name: sequelize
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* lint

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-02-23 19:19:12 -08:00
Tom Moor 3acc352cf0 Fix PWA manifest (#4922) 2023-02-23 18:52:25 -08:00
Tom Moor 49bc0ed9f7 Optimize lodash bundle size (#4919)
* Optimize lodash bundle size

* Move to vite plugins
2023-02-23 17:57:11 -08:00
Tom Moor a92534dfac fix: Bundle size calculation includes development React (#4912) 2023-02-21 19:57:05 -08:00
Tom Moor 2f64d3c172 Restore core-js dependency 2023-02-21 14:13:55 -05:00
Tom Moor eb42f8006d chore: Remove 16+ unused dependencies (#4910)
* chore: Remove no-longer used webpack loaders

* chore: Remove migration of markdown from Slate documents (2y old)

* chore: Remove more unused deps

* chore: Remove explicit core-js dep

* Remove more unused dependencies

* test
2023-02-21 08:43:28 -08:00
Tom Moor 0887219be6 chore: Bump babel, remove lodash plugin (#4908) 2023-02-20 18:32:46 -08:00
dependabot[bot] f8fe3a749e chore(deps): bump @babel/plugin-proposal-decorators (#4904)
Bumps [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) from 7.18.10 to 7.21.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.21.0/packages/babel-plugin-proposal-decorators)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-decorators"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-20 18:13:35 -08:00
dependabot[bot] 7de9a9b906 chore(deps): bump vite from 4.1.1 to 4.1.3 (#4907)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.1.1 to 4.1.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.1.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-20 18:12:54 -08:00
Tom Moor c33a4103e7 chore: Remove setimmediate polyfill (#4903)
* Add setimmediate to dependencies

* Remove use of setimmediate
2023-02-20 08:24:14 -08:00
Tom Moor a9e373c72f fix: HMR in development 2023-02-20 11:23:25 -05:00
Tom Moor 0e622288ff fix: Line-numbering in code blocks runs horizontal on Linux
closes #4901
2023-02-20 09:08:07 -05:00
Tom Moor 0514c119f9 New Crowdin updates (#4860) 2023-02-19 19:52:41 -08:00
Tom Moor 21a1257d06 chore: Move remaining auth methods to plugins (#4900)
* Move Google, Email, and Azure to plugins

* Move OIDC provider, remove old loading code

* Move AuthLogo to plugin

* AuthLogo -> PluginIcon

* Lazy load plugin settings
2023-02-19 19:52:08 -08:00
Tom Moor 667ffdeaf1 fix: Import size should use larger of AWS_S3_UPLOAD_MAX_SIZE and MAX_IMPORT_SIZE
closes #4899
2023-02-19 19:18:31 -05:00
Tom Moor f63441c15d fix: Docker build 2023-02-19 12:22:37 -05:00
Tom Moor 618967d6da Ensure development commands are ran with development env
Ref #4889
2023-02-19 11:17:31 -05:00
Tom Moor 70beb7524f feat: Custom accent color (#4897)
* 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
2023-02-19 07:43:03 -08:00
Tom Moor 7c05b7326a test 2023-02-18 14:16:34 -05:00
Tom Moor 4805259823 fix: Cursor position changes on new token with line numbers enabled (#4896)
Move line numbers to psuedo element
2023-02-18 10:56:26 -08:00
Tom Moor 66b5dd0a2b fix: Do not show authentication provider plugins that aren't enabled 2023-02-18 13:56:03 -05:00
Tom Moor aece719a07 fix: Trim trailing digits from minimized classnames 2023-02-17 19:04:50 -05:00
Tom Moor 2cd5d0e624 chore: Bump Node to 18 LTS (#4795)
* Bump Node to 18 LTS

* Upgrade Jest
2023-02-16 05:33:54 -08:00
Tom Moor 0207786eec Update Mermaid.js (#4883)
* Update Mermaid.js

* tsc

* Allow using more CI resources

* Downgrade
2023-02-15 20:46:32 -08:00
Tom Moor 12aca51541 0.68.0 2023-02-15 22:51:21 -05:00
Hans Pagel e754f89e5c Replace Webpack with Vite (#4765)
Co-authored-by: Tom Moor <tom@getoutline.com>
Co-authored-by: Vio <vio@beanon.com>
2023-02-15 19:39:46 -08:00
Tom Moor 490d05b68b fix: Incorrect key events trigger on non-qwerty layouts 2023-02-14 19:09:44 -05:00
Tom Moor b50bee1ec7 fix: ga is not defined 2023-02-14 19:03:54 -05:00
Mohamed ELIDRISSI 0976e85a1a refactor: add server side validation schema for authProviders (#4876)
* refactor: move files to subfolder

* refactor: schema for authenticationProviders.info

* refactor: schema for authenticationProviders.update

* refactor: use validated body
2023-02-14 14:49:24 -08:00
dependabot[bot] ab7b20958b chore(deps): bump fs-extra and @types/fs-extra (#4871)
Bumps [fs-extra](https://github.com/jprichardson/node-fs-extra) and [@types/fs-extra](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/fs-extra). These dependencies needed to be updated together.

Updates `fs-extra` from 4.0.3 to 11.1.0
- [Release notes](https://github.com/jprichardson/node-fs-extra/releases)
- [Changelog](https://github.com/jprichardson/node-fs-extra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jprichardson/node-fs-extra/compare/4.0.3...11.1.0)

Updates `@types/fs-extra` from 9.0.13 to 11.0.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/fs-extra)

---
updated-dependencies:
- dependency-name: fs-extra
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: "@types/fs-extra"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 05:57:10 -08:00
dependabot[bot] 8fc1f67697 chore(deps): bump react-i18next from 12.1.1 to 12.1.5 (#4872)
Bumps [react-i18next](https://github.com/i18next/react-i18next) from 12.1.1 to 12.1.5.
- [Release notes](https://github.com/i18next/react-i18next/releases)
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v12.1.1...v12.1.5)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 05:56:46 -08:00
Tom Moor 60101c507a Move bulk of webhook logic to plugin (#4866)
* Move bulk of webhook logic to plugin

* Re-enable cleanup task

* cron tasks
2023-02-12 16:28:11 -08:00
Tom Moor 7895ee207c Clear previous plugin and server files in build directory before rebuilding 2023-02-12 16:43:20 -05:00
Tom Moor e028715afb Minor fixes from enterprise codebase 2023-02-12 16:31:15 -05:00
Tom Moor 33afa2f029 Plugin architecture (#4861)
* wip

* Refactor, tasks, processors, routes loading

* Move Slack settings config to plugin

* Fix translations in plugins

* Move Slack auth to plugin

* test

* Move other slack-related files into plugin

* Forgot to save

* refactor
2023-02-12 10:11:30 -08:00
Mohamed ELIDRISSI 492beedf00 refactor: add server side validation schema for apiKeys (#4859)
* refactor: add tests for apiKey api routes

* refactor: move files to subfolder

* refactor: schema for apiKeys.create and apiKeys.delete
2023-02-11 15:02:52 -08:00
vgwidt 9302beb630 fix: Visual Basic syntax higlighting (#4769) (#4770) 2023-02-11 09:31:37 -08:00
Tom Moor c5cb02e980 fix: Text color on key component 2023-02-10 23:18:10 -05:00
Tom Moor db446ba67d New Crowdin updates (#4734) 2023-02-10 19:36:51 -08:00
Tom Moor 237313a97d fix: Action children not triggerable 2023-02-10 22:36:00 -05:00
Tom Moor fcbd4d3d28 Track action usage 2023-02-10 18:56:12 -05:00
Tom Moor bb6f4b1c1e fix: Attachment converted to links when AWS ACL is public-read, closes #4853 2023-02-10 17:42:09 -05:00
Tom Moor 23b8cc307e Revert "allow node 17 & 18 when installing dependencies (#4844)" (#4846)
This reverts commit c75c61ca4b.
2023-02-08 15:47:09 -08:00
Hans Pagel c75c61ca4b allow node 17 & 18 when installing dependencies (#4844) 2023-02-08 16:22:56 +01:00
Tom Moor 81f655f402 fix: Links with strikethrough do not have hover preview (#4841)
* fix: Links with strikethrough do not have hover preview

* refactor
2023-02-07 19:36:15 -08:00
dependabot[bot] bb1fe1a25f chore(deps): bump zod from 3.19.1 to 3.20.2 (#4833)
Bumps [zod](https://github.com/colinhacks/zod) from 3.19.1 to 3.20.2.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Changelog](https://github.com/colinhacks/zod/blob/master/CHANGELOG.md)
- [Commits](https://github.com/colinhacks/zod/compare/v3.19.1...v3.20.2)

---
updated-dependencies:
- dependency-name: zod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 18:34:22 -08:00
dependabot[bot] b9ffe8aaa3 chore(deps): bump tiny-cookie from 2.3.2 to 2.4.0 (#4836)
Bumps [tiny-cookie](https://github.com/Alex1990/tiny-cookie) from 2.3.2 to 2.4.0.
- [Release notes](https://github.com/Alex1990/tiny-cookie/releases)
- [Changelog](https://github.com/Alex1990/tiny-cookie/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Alex1990/tiny-cookie/compare/v2.3.2...v2.4.0)

---
updated-dependencies:
- dependency-name: tiny-cookie
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 18:33:56 -08:00
dependabot[bot] 97775e14df chore(deps): bump immutable from 4.2.2 to 4.2.4 (#4835)
Bumps [immutable](https://github.com/immutable-js/immutable-js) from 4.2.2 to 4.2.4.
- [Release notes](https://github.com/immutable-js/immutable-js/releases)
- [Changelog](https://github.com/immutable-js/immutable-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/immutable-js/immutable-js/compare/v4.2.2...v4.2.4)

---
updated-dependencies:
- dependency-name: immutable
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 18:33:27 -08:00
Tom Moor 0b6c9d1838 Improve drag-and-drop (#4824)
* Improve drag-and-drop

* fixes

* fix drop highlight showing on ghosted sidebar item
2023-02-04 12:00:32 -08:00
Tom Moor 239e9e294d fix: Microsoft auth silently errors when logged into multiple Microsoft accounts, allow account selection in OAuth flow 2023-02-04 14:56:52 -05:00
Tom Moor 9b002abae3 fix: Ensure tsvector content is below 1Mb limitation
closes #4714
2023-02-04 14:26:54 -05:00
Tom Moor 534eeacc97 fix: Documents with images exported as HTML have broken images
closes #4822
2023-02-04 14:04:38 -05:00
Tom Moor 8b28d6f6e0 fix: Suppress Slack updated notifications when publishing
closes #4821
2023-02-04 14:00:30 -05:00
Tom Moor 59b02154b9 Merge branch 'main' of github.com:outline/outline 2023-02-03 23:08:34 -05:00
Apoorv Mishra 0d6651b0da Scroll children into view upon expansion (#4812)
* feat: smoothly scroll children into view

* fix: disable smooth scroll and throttling
2023-02-03 09:41:24 +05:30
Tom Moor a1cefa9771 fix: FORCE_HTTPS setting results in redirect loop when Outline terminates SSL 2023-02-02 21:45:33 -05:00
Apoorv Mishra 1caa51f58e Viewer should be allowed to subscribe to a document (#4814)
* fix: viewer should be allowed to subscribe to a document

* fix: allow subscribe only if the user has read permission for collection
2023-01-31 19:46:10 +05:30
Tom Moor a2e07e9593 chore: Bump kbar 2023-01-31 08:53:38 -05:00
dependabot[bot] 8f166ca775 chore(deps-dev): bump jest-cli from 28.1.3 to 29.4.1 (#4805)
* chore(deps-dev): bump jest-cli from 28.1.3 to 29.4.1

Bumps [jest-cli](https://github.com/facebook/jest/tree/HEAD/packages/jest-cli) from 28.1.3 to 29.4.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.1/packages/jest-cli)

---
updated-dependencies:
- dependency-name: jest-cli
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Snapshots

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-01-30 20:17:09 -08:00
dependabot[bot] d70aefe9fa chore(deps): bump immutable from 4.0.0 to 4.2.2 (#4807)
Bumps [immutable](https://github.com/immutable-js/immutable-js) from 4.0.0 to 4.2.2.
- [Release notes](https://github.com/immutable-js/immutable-js/releases)
- [Changelog](https://github.com/immutable-js/immutable-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/immutable-js/immutable-js/compare/v4.0.0...v4.2.2)

---
updated-dependencies:
- dependency-name: immutable
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 19:58:33 -08:00
dependabot[bot] 4bc441cc9f chore(deps): bump react-dnd from 14.0.1 to 16.0.1 (#4808)
Bumps [react-dnd](https://github.com/react-dnd/react-dnd) from 14.0.1 to 16.0.1.
- [Release notes](https://github.com/react-dnd/react-dnd/releases)
- [Changelog](https://github.com/react-dnd/react-dnd/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react-dnd/react-dnd/commits)

---
updated-dependencies:
- dependency-name: react-dnd
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 19:58:06 -08:00
Tom Moor f39487d25b fix: PaginatedList does not always load more (#4811) 2023-01-30 19:53:14 -08:00
dependabot[bot] 65a4874301 chore(deps): bump sequelize-typescript from 2.1.3 to 2.1.5 (#4804)
Bumps [sequelize-typescript](https://github.com/RobinBuschmann/sequelize-typescript) from 2.1.3 to 2.1.5.
- [Release notes](https://github.com/RobinBuschmann/sequelize-typescript/releases)
- [Changelog](https://github.com/sequelize/sequelize-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/RobinBuschmann/sequelize-typescript/compare/v2.1.3...v2.1.5)

---
updated-dependencies:
- dependency-name: sequelize-typescript
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 18:19:01 -08:00
Tom Moor d1268167c8 Increase build speed by running concurrently 2023-01-29 16:18:54 -05:00
Tom Moor 80a8f5b7e2 feat: For changes in long tables do not print the entire table in the emailed diff (#4800) 2023-01-29 11:48:37 -08:00
Tom Moor 5473b698a4 Inject DataDog trace ID's into logs when enabled 2023-01-29 13:40:26 -05:00
Apoorv Mishra 2e6c960ae9 fix: remove document name from path (#4798) 2023-01-29 10:36:37 -08:00
Tom Moor d02d3cb55d feat: Add import/export of documents as JSON (#4621)
* feat: Add export of documents as JSON

* Rename, add structured collection description

* stash

* ui

* Add entity creation data to JSON archive

* Import JSON UI plumbing

* stash

* Messy, but working

* tsc

* tsc
2023-01-29 10:24:44 -08:00
Tom Moor 85ca25371c test (#4796) 2023-01-29 06:28:57 -08:00
Tom Moor f0d9bb4898 Friendlier active tab design 2023-01-28 17:22:30 -05:00
Tom Moor 4de780c339 fix: Cmd+K styling does not match context menus
closes #4701
2023-01-28 17:17:35 -05:00
Tom Moor 075555a867 fix: Do not show actively disabled auth providers in self-hosted install (#4794)
* fix: Do not show actively disabled auth providers in self-hosted installation

* self review

* Refactor for easier mocking
2023-01-28 10:02:25 -08:00
Tom Moor aac495fa58 fix: Pipe characters in code marks within tables cause the table layout to break
closes #4783
2023-01-28 13:01:02 -05:00
Apoorv Mishra 7dbc419bbf Change "Move" dialog appearance to match that of "Publish" dialog (#4787)
* refactor: receive items as props in DocumentExplore

* refactor: leverage DocumentExplorer for DocumentMove

* fix: keyboard shortcut for moving document

* refactor: cleanup

* Revert "refactor: cleanup"

This reverts commit 9a0a98eff2.

* fix: get rid of extra parent container

* Revert "fix: get rid of extra parent container"

This reverts commit 908eaf2bba.

* refactor: remove PathToDocument component
2023-01-28 22:33:56 +05:30
Apoorv Mishra 0c572ac2c4 Duplicate docs as unpublished drafts (#4791)
* feat: duplicate docs as unpublished drafts

* fix: use isTemplate

* fix: no need of ternary
2023-01-28 21:32:59 +05:30
Apoorv Mishra 6d45566be3 fix: missing collection name in path in explorer search results (#4793) 2023-01-28 06:29:59 -08:00
Tom Moor d5eabd7771 fix: Allow loading attachments linked from other sites/emails.
Loosens same-site policy to include cookies for navigation events.
closes #4737
2023-01-27 18:52:47 -05:00
Tom Moor b5876dc844 fix: Fallback to username when name is unavailable in OIDC provider
closes #4774
2023-01-27 18:18:08 -05:00
Tom Moor 0272ea03bd fix: Text in revisions is unreadable in dark mode, closes #4782 2023-01-27 18:13:08 -05:00
Apoorv Mishra ad902af52c Move tree implementation out of collections store (#4763)
* refactor: attaching emoji in tree node is unnecessary

* refactor: pass depth and hasChildren as separate props

* refactor: move tree impl into a separate hook

* refactor: separate out as DocumentExplorer for reuse

* fix: separate search and node

* fix: review comments

* fix: tsc
2023-01-27 11:33:51 +05:30
Tom Moor cc14c212b6 fix: Unable to access localStorage in document embedded in iframe with third party cookies blocked (#4777)
* fix: Pasting from Microsoft Office pastes image. Closes #3058

* fix: Use Storage wrapper implementation for all editor calls to localStorage

closes #4776
2023-01-26 04:48:56 -08:00
Tom Moor 9ea606a734 fix: Pasting from Microsoft Office pastes image. Closes #3058 2023-01-25 22:37:47 -05:00
Tom Moor 784631baf4 fix: Handle missing size on attachment 2023-01-25 22:30:21 -05:00
Tom Moor 6ab428a498 fix: Link toolbar does not allow doc search, closes #4757 2023-01-24 09:08:02 -05:00
Apoorv Mishra 88a1f72b59 fix: collections order in publish modal should match with the order in sidebar (#4762) 2023-01-24 04:23:58 -08:00
dependabot[bot] 2021f192bd chore(deps): bump cookiejar from 2.1.3 to 2.1.4 (#4758)
Bumps [cookiejar](https://github.com/bmeck/node-cookiejar) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/bmeck/node-cookiejar/releases)
- [Commits](https://github.com/bmeck/node-cookiejar/commits)

---
updated-dependencies:
- dependency-name: cookiejar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 17:48:14 -08:00
dependabot[bot] 1b6496dff4 chore(deps): bump koa-sslify from 5.0.0 to 5.0.1 (#4753)
Bumps [koa-sslify](https://github.com/turboMaCk/koa-sslify) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/turboMaCk/koa-sslify/releases)
- [Changelog](https://github.com/turboMaCk/koa-sslify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/turboMaCk/koa-sslify/commits)

---
updated-dependencies:
- dependency-name: koa-sslify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 17:41:07 -08:00
dependabot[bot] 6c5dadff8c chore(deps-dev): bump lint-staged from 12.3.8 to 13.1.0 (#4754)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 12.3.8 to 13.1.0.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v12.3.8...v13.1.0)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 17:38:52 -08:00
Apoorv Mishra 6b286d82b8 Ability to choose publish location for a document (#4582)
* feat: initial base structure

* feat: utils for constructing and flattening collection tree

* feat: basic demo to display tree-like structure with virtualization

* feat: make it searchable

* feat: row component

* fix: handle row selection

* fix: scroll jitter

* fix: popover max-height to eliminate extra scroll

* fix: position scrollbar correctly

* fix: do not sort to maintain correct tree-like view

* feat: footer

* fix: scroll to selected item

* fix: deselect item

* fix: display selected location in footer

* fix: deselect item if any upon search trigger

* fix: create draft without collection

* fix: pass down collectionId to all the nodes

* feat: publish document under selected location

* fix: move the doc post publish in case it is supposed to be a nested doc

* fix: wrap text for selected location

* fix: footer background in dark mode and unused css

* fix: popover height in small devices

* fix: no need to spread

* refactor: remove outline

* refactor: border-radius is common

* refactor: remove active and focus

* fix: do not shrink spacer

* fix: scroll list padding with correctly adjusted scrolling

* refactor: use constants

* fix: use padding in favor of spacer

* refactor: border attrs not needed

* refactor: control title padding and icon size centrally

* fix: rename param

* fix: import path

* fix: refactor styles, avoid magic numbers

* fix: type err

* feat: make rows collapsible

* fix: fully expanded without disclosure upon search

* fix: use modal in place of popover

* fix: collapse descendants

* fix: rename PublishPopover to PublishModal

* fix: adjust collapse icon as part of tree view

* fix: enable keyboard navigation

* not sure why collapse and expand shortcuts are not working

* fix: row expansion and search box focus and blur

* fix: remove css hover, handle it via active prop

* fix: discard tree like view for search results

* fix: minor tweaks

* refactor: no need to pass onPublish

* refactor: remove unnecessary attrs from search component

* fix: publish button text

* fix: reset intial scroll offset to 0 on search

* fix: remove search highlights

* fix: clean up search component

* refactor: search and row collapse

* refactor: PublishLocation

* fix: show emoji or star icon if present

* fix: shift focus only from top item

* fix: leading emoji

* fix: baseline text

* fix: make path tertiary

* fix: do not show path for collections

* fix: path text color upon selection

* fix: deleted collection case

* fix: no results found

* fix: space around slash

* Refinement, some small refactors

* fix: Publish shortcut, use Button action

* Allow new document creation from command menu without active collection

* fix: duplicate

* fix: Unneccessary truncation

* fix: Scroll on expand/collapse
Remove wraparound

* fix: tsc

* fix: Horizontal overflow on PublishLocation
Remove pointless moveTo method

* fix: Missing translation

* Remove method indirection
Show expanded collection icon in tree when expanded

* Shrink font size a point

* Remove feature flag

* fix: Path color contrast in light mode
Remove unused expanded/show attributes

* shrink -> collapse, fix expanded disclosure without items after searching

* Mobile styles

* fix: scroll just into view

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-01-23 17:38:24 -08:00
Tom Moor da4a0189dc Update rateLimiter.ts 2023-01-22 14:37:52 -08:00
Tom Moor 312e11e7c1 fix: Any error from rate limiter results in 'Rate limit exceeded' screen 2023-01-22 11:31:48 -05:00
Tom Moor d3dbf53d0b chore: Add insurance rate limiter for when Redis is down/reconnecting 2023-01-22 11:04:30 -05:00
Tom Moor 5b561e98f7 chore: Add configurable per-document connection limit extension (#4717)
* chore: Add configurable per-document connection limit extension

* docs
2023-01-22 07:50:32 -08:00
Tom Moor aa88bb2a7b fix: Check browser has print ability before showing Print option 2023-01-22 10:32:31 -05:00
Tom Moor f83b0ab5e3 fix: Remove :is selector (bad compatibility) 2023-01-22 10:22:41 -05:00
Tom Moor 095028541d fix: Missing translations 2023-01-22 10:14:17 -05:00
Tom Moor c1aa4c8dde fix: Alignment of caption on fullwidth images 2023-01-22 10:13:15 -05:00
Tom Moor 049f49ebe8 fix: Fallback to initials instead of placeholder when offline 2023-01-22 09:46:52 -05:00
Tom Moor f1406577b7 Color transition on icon picker 2023-01-21 23:37:08 -05:00
dependabot[bot] 1da6847e68 chore(deps-dev): bump @typescript-eslint/parser from 5.40.0 to 5.48.1 (#4725)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.40.0 to 5.48.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.48.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-20 09:38:14 -08:00
Tom Moor 21ce145f67 0.67.2 2023-01-16 15:50:56 -08:00
Tom Moor 0a4c7091b5 chore: Yarn dedupe 2023-01-16 15:50:52 -08:00
dependabot[bot] f0f574812d chore(deps-dev): bump @babel/preset-typescript from 7.16.7 to 7.18.6 (#4723)
Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.16.7 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 08:29:44 -08:00
dependabot[bot] 830763a9eb chore(deps): bump jsdom from 20.0.3 to 21.0.0 (#4721)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 20.0.3 to 21.0.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/20.0.3...21.0.0)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 08:29:25 -08:00
Tom Moor 55f2989a3d New Crowdin updates (#4624)
* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New Ukrainian translations from Crowdin [ci skip]
2023-01-15 12:48:57 -08:00
Tom Moor 788450136e test: documents.update apiVersion 2 response 2023-01-15 09:43:56 -05:00
Tom Moor 0c269081d9 fix: Sidebar jumps when publish or unpublish document (#4706)
* Return updated collection in API response for documents.unpublish and documents.update
Allows for improved UX on clientside

* test

* tsc

* tsc
2023-01-15 06:01:06 -08:00
Tom Moor 31f743eb4c fix: Incorrect spacing on IconPicker since menu style was changed
closes #4711
2023-01-14 23:27:45 -05:00
Aditya Sharma 4ca0fc32c1 show collection name in pin menu (#4705)
* show collection name in pin menu

* fix: fetching right collection name

* refactor: better variable names

* Update app/actions/definitions/documents.tsx

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Avoid additional translation

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-01-14 19:17:25 -08:00
Tom Moor 0bed01a062 fix: Cannot click on input in sidebar when editing doc/collection (#4716)
fix: Start editing with all text selected
fix: Styling issue around input
2023-01-14 19:14:50 -08:00
Tom Moor a25372c186 fix: Full-width images in editor are incorrectly aligned in RTL documents
closes #4712
2023-01-14 21:47:33 -05:00
Tom Moor 51baba8fa8 fix: Small unfocusable area below last block in editor, closes #4713 2023-01-14 20:45:15 -05:00
Tom Moor 0cccd7141d fix(collaboration): Avoid writing spurious changes from read-only users when serialized output changes 2023-01-13 23:54:44 -05:00
Tom Moor 6b438e3467 fix: Background on TOC does not transition smoothly on theme change 2023-01-13 22:22:31 -05:00
Tom Moor 0d53e5a7ba chore: Clean build/ folder on every build, remove duplicative scripts 2023-01-13 22:18:25 -05:00
Tom Moor e3db7455b3 feat: Add optional SMTP_NAME configuration for connecting to SMTP servers that require the client to have a specific hostname 2023-01-13 21:49:57 -05:00
Tom Moor d20f379943 feat: Publish and Unpublish available in command menu
fix: Add default error handling for menu actions
2023-01-12 22:39:14 -05:00
Tom Moor e347404502 chore: Improvements to document move behavior (#4689)
* chore: Improvements to document move behavior

* test
2023-01-12 18:48:09 -08:00
Tom Moor 17a8dbb3f0 fix: Prevent moving documents into drafts 2023-01-12 11:15:54 -05:00
Tom Moor 3be170ddb8 0.67.1 2023-01-11 21:27:37 -05:00
Tom Moor 4a97b35d5a fix: Collection structure update on document move 2023-01-11 20:56:14 -05:00
Tom Moor 785b9888dd Respond to slack url verification challenge with JSON instead of raw body 2023-01-11 09:07:15 -05:00
Tom Moor d5158f0a34 0.67.0 2023-01-10 20:32:43 -05:00
Tom Moor 64b72bcf82 /bin/bash -> /bin/sh for Docker 2023-01-10 20:32:37 -05:00
Tom Moor 6be7409d85 fix: Mistake in i18n key 2023-01-10 18:13:59 -05:00
dependabot[bot] fddcbbd7af chore(deps): bump react-hook-form from 7.37.0 to 7.41.5 (#4667)
Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.37.0 to 7.41.5.
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.37.0...v7.41.5)

---
updated-dependencies:
- dependency-name: react-hook-form
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 19:02:44 -08:00
dependabot[bot] 3e7f823e17 chore(deps): bump aws-sdk from 2.1189.0 to 2.1290.0 (#4664)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1189.0 to 2.1290.0.
- [Release notes](https://github.com/aws/aws-sdk-js/releases)
- [Changelog](https://github.com/aws/aws-sdk-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js/compare/v2.1189.0...v2.1290.0)

---
updated-dependencies:
- dependency-name: aws-sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 19:02:19 -08:00
dependabot[bot] 31c47ab37b chore(deps): bump @joplin/turndown-plugin-gfm from 1.0.44 to 1.0.45 (#4663)
Bumps [@joplin/turndown-plugin-gfm](https://github.com/laurent22/joplin-turndown-plugin-gfm) from 1.0.44 to 1.0.45.
- [Release notes](https://github.com/laurent22/joplin-turndown-plugin-gfm/releases)
- [Commits](https://github.com/laurent22/joplin-turndown-plugin-gfm/commits)

---
updated-dependencies:
- dependency-name: "@joplin/turndown-plugin-gfm"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 15:39:52 -08:00
dependabot[bot] cbfb7d2c23 chore(deps): bump luxon from 3.0.1 to 3.2.1 (#4660)
Bumps [luxon](https://github.com/moment/luxon) from 3.0.1 to 3.2.1.
- [Release notes](https://github.com/moment/luxon/releases)
- [Changelog](https://github.com/moment/luxon/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moment/luxon/compare/3.0.1...3.2.1)

---
updated-dependencies:
- dependency-name: luxon
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 07:31:22 -08:00
Tom Moor 9617a15ae8 fix: No value supplied for attribute src
It shouldn't be possible to have an image node with no src, but it does happen occassionally and this prevents the document from persisting. It's better to have a broken image than a doc that won't save
2023-01-07 15:26:06 -05:00
Tom Moor 53414ec3ba feat: Server side translation setup (#4657)
* Server side translation setup

* docs
2023-01-07 11:52:09 -08:00
Tom Moor a333f48102 fix: Hanging } 2023-01-07 10:58:22 -05:00
Tom Moor d4da33424b fix: Math block overrides heading backspace key behavior 2023-01-07 10:01:21 -05:00
Tom Moor e67ac1215a feat: Allow moving draft documents (#4652)
* feat: Allow moving draft documents

* Allow drag-n-drop move of draft documents

* fix: Allow moving draft without a collection

* fix: Allow moving draft without a collection
2023-01-06 19:31:06 -08:00
Tom Moor 9f825b9adf fix: Allow sort by title in documents.list 2023-01-06 16:58:39 -05:00
Tom Moor 4b47bffcf5 fix: images and files with cyrillic names don't import (#4654)
closes #4559
2023-01-06 06:02:15 -08:00
Tom Moor cbd9971bc7 fix: Missing translation on Import screen 2023-01-06 08:32:55 -05:00
Tom Moor c80aec5eb2 fix: build.sh copies dev webpack incorrectly 2023-01-06 05:26:13 -08:00
Tom Moor 5b60f1ab00 tsc 2023-01-05 21:25:17 -05:00
Tom Moor ec2da746dc chore: Convert LinkToolbar to functional component
Co-authored-by: Ítalo Sousa <italusousa@gmail.com>
2023-01-05 21:11:28 -05:00
Tom Moor a065a8426f fix: OL/UL inside of checkbox list is not styled correctly (#4648)
closes #4635
2023-01-05 17:18:07 -08:00
Apoorv Mishra b6141442b7 Validate API request query (#4642)
* fix: refactor to accommodate authentication, transaction and pagination together into ctx.state

* feat: allow passing response type to APIContext

* feat: preliminary work for initial review

* fix: use unknown for base types

* fix: api/attachments

* fix: api/documents

* fix: jsdoc comment for input

* fix: replace at() with index access for compatibility

* fix: validation err message

* fix: error handling

* fix: remove unnecessary extend
2023-01-05 20:24:03 +05:30
Tom Moor 445d19f43e chore: Extract product name from translation strings (#4646) 2023-01-04 19:00:57 -08:00
Tom Moor f655288f67 fix: Issue where possibly logged into the wrong workspace when signing in via desktop app with multiple workspaces 2023-01-04 21:13:13 -05:00
Tom Moor fc6bb3caef fix: Unstable t method causing stars.list to fetch run multiple times. Seems this behavior changed in the recent dep bump 2023-01-04 20:42:48 -05:00
Apoorv Mishra f4461573de Refactor to accommodate authentication, transaction and pagination states together (#4636)
* fix: refactor to accommodate authentication, transaction and pagination together into ctx.state

* feat: allow passing response type to APIContext
2023-01-04 23:51:44 +05:30
Tom Moor bb568d2e62 fix: Exports generate invalid internal links (#4639)
* refactoring

* Refactoring continues

* Refactor export, fix internal links in exported docs

* fix: Dupe document name detection

* sigh
2023-01-04 04:18:59 -08:00
Tom Moor eb50c9e1f1 test: Remove tests associated with exporting documents from shareId 2023-01-03 22:49:02 -05:00
Tom Moor a2e183627c fix: Disabled authentication providers show as enabled in settings 2023-01-03 19:32:16 -05:00
Tom Moor 1c9eee2134 fix: Search on shared documents with custom slug not working
fix: Should not be able to export a document with shareId
2023-01-03 19:28:04 -05:00
Tom Moor 64d8f3091a fix: 'Search titles' filter wraps to multiple lines on small screens 2023-01-02 21:25:24 -05:00
Tom Moor 0d920e02b1 chore: Remove query logging in test env 2023-01-02 21:06:39 -05:00
Tom Moor 6efcf1c1a8 chore: Refactor SearchHelper internals 2023-01-02 20:14:46 -05:00
Tom Moor 435969cf4b chore: Refactor build:server to bashfile 2023-01-02 16:00:01 -05:00
Tom Moor 28a54113e1 fix: Always redirect to custom domain on server if set 2023-01-02 15:48:06 -05:00
Aditya Sharma 712ff8265e feat: add search title only filter for search options (#4587)
* feat: search title only filter

* fix: page reload will keep settings

* fix: working with additional filters

* style changes
2023-01-02 10:00:10 -08:00
dependabot[bot] b6234848fb chore(deps): bump react-i18next from 11.16.6 to 12.1.1 (#4634)
* chore(deps): bump react-i18next from 11.16.6 to 12.1.1

Bumps [react-i18next](https://github.com/i18next/react-i18next) from 11.16.6 to 12.1.1.
- [Release notes](https://github.com/i18next/react-i18next/releases)
- [Changelog](https://github.com/i18next/react-i18next/blob/master/CHANGELOG.md)
- [Commits](https://github.com/i18next/react-i18next/compare/v11.16.6...v12.1.1)

---
updated-dependencies:
- dependency-name: react-i18next
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update related deps, TS fixes

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2023-01-02 09:30:44 -08:00
dependabot[bot] e4880daadf chore(deps-dev): bump yarn-deduplicate from 3.1.0 to 6.0.1 (#4633)
Bumps [yarn-deduplicate](https://github.com/scinos/yarn-deduplicate) from 3.1.0 to 6.0.1.
- [Release notes](https://github.com/scinos/yarn-deduplicate/releases)
- [Changelog](https://github.com/scinos/yarn-deduplicate/blob/master/CHANGELOG.md)
- [Commits](https://github.com/scinos/yarn-deduplicate/compare/v3.1.0...v6.0.1)

---
updated-dependencies:
- dependency-name: yarn-deduplicate
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-02 08:36:59 -08:00
dependabot[bot] 97b0fd465d chore(deps-dev): bump html-webpack-plugin from 4.5.1 to 4.5.2 (#4632)
Bumps [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) from 4.5.1 to 4.5.2.
- [Release notes](https://github.com/jantimon/html-webpack-plugin/releases)
- [Changelog](https://github.com/jantimon/html-webpack-plugin/blob/v4.5.2/CHANGELOG.md)
- [Commits](https://github.com/jantimon/html-webpack-plugin/compare/v4.5.1...v4.5.2)

---
updated-dependencies:
- dependency-name: html-webpack-plugin
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-02 08:36:18 -08:00
dependabot[bot] 423f961ca1 chore(deps): bump katex from 0.16.3 to 0.16.4 (#4630)
Bumps [katex](https://github.com/KaTeX/KaTeX) from 0.16.3 to 0.16.4.
- [Release notes](https://github.com/KaTeX/KaTeX/releases)
- [Changelog](https://github.com/KaTeX/KaTeX/blob/main/CHANGELOG.md)
- [Commits](https://github.com/KaTeX/KaTeX/compare/v0.16.3...v0.16.4)

---
updated-dependencies:
- dependency-name: katex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-02 08:36:06 -08:00
Tom Moor 4ccff8cb29 chore: Convert GroupListItem, AddGroupsToCollection, AddPeopleToCollection, Drafts to functional components 2023-01-02 11:26:51 -05:00
Tom Moor 8c54f6330f chore: Clarify import/export options 2023-01-02 10:39:49 -05:00
Tom Moor 846a1f8eab fix: Remove extra spaces around hard break serialization, closes #4616 2023-01-02 10:26:46 -05:00
Tom Moor 205f7d2a7e chore: Move Input to functional component (#4629)
* chore: Remove ReactHookWrappedInput workaround
Move Input to functional component

* I love Typescript
2023-01-01 10:35:02 -08:00
Tom Moor 2494ca39c1 fix: Improved GA4 integration 2023-01-01 12:27:09 -05:00
Tom Moor 8e4270c321 feat: Add GA integration, support for GA4 (#4626)
* GA integration settings

* trackingId -> measurementId
Hook up script

* Public page GA tracking
Correct layout of settings

* Remove multiple codepaths for loading GA measurementID, add missing db index

* Remove unneccessary changes, tsc

* test
2023-01-01 07:29:08 -08:00
Mohamed ELIDRISSI dc795604a4 refactor: add server-side validation schema for events (#4622)
* refactor: move files to subfolder

* refactor: schema for events.list

* refactor: update nullable fields in Event model

* fix: event actor not nullable

* fix: team not nullable
2022-12-31 13:56:37 -08:00
Tom Moor 05a4f050bb chore: Improve graceful server shutdown (#4625)
* chore: Improve graceful server shutdown

* Replace node timers with custom promise timeout
2022-12-31 13:56:27 -08:00
Tom Moor ad9525bfa3 chore: Refactor icon components
fix: Alignment of Outline logo component
2022-12-31 12:26:39 -05:00
Tom Moor 575f70a9e2 fix: useMousePosition can set state after component unmounted
fix: Clicking item in SubMenu does not close parent menu
2022-12-31 10:34:23 -05:00
Tom Moor e70f1ed84c fix: Extra spacing below inputs
fix: UX fixes in share popover with custom links
2022-12-31 10:34:23 -05:00
Tom Moor 16958560e6 New Crowdin updates (#4586) 2022-12-31 06:06:46 -08:00
Tom Moor cdbc6df485 chore: More tracing improvements 2022-12-31 09:04:45 -05:00
Tom Moor c6fb764631 chore: Move tracing decorators into the codebase (#4623)
* Vendorize tracing, finally fix service name issues

* Upgrade datadaog-metrics, rename decorators -> tracing

* lint
2022-12-31 04:54:51 -08:00
Tom Moor 1e036ebd0e fix: Nested documents do not respect export format 2022-12-30 20:36:15 -05:00
Tom Moor 7a1e6a1b73 feat: Bulk HTML export for collection 2022-12-30 20:13:29 -05:00
Tom Moor 1328162921 fix: Missing cascade constraints on stars table 2022-12-30 18:45:24 -05:00
Tom Moor 2e36ad9d1f fix: Retain title attribute when parsing from Markdown sources 2022-12-30 15:54:31 -05:00
Tom Moor c6c06ac4ce test: Add test for table content 2022-12-30 15:27:18 -05:00
Tom Moor b29a9fbeee chore: Remove reliance on Markdown for document.getSummary, towards #3000 2022-12-30 15:14:59 -05:00
Tom Moor 0f489d54c3 Add DocumentHelper.toPlainText 2022-12-30 14:49:53 -05:00
Tom Moor 7c47ab560e fix: Add check for 'name' returned from OIDC provider, closes #4453 2022-12-30 14:02:00 -05:00
Tom Moor 997d796eb7 chore: Remove anomalous serviceName from traces 2022-12-30 13:42:22 -05:00
Tom Moor 18b69fad99 fix: Improve contrast on danger color 2022-12-30 13:07:40 -05:00
Mohamed ELIDRISSI 318e1df13b refactor: add server side validation schema for attachments (#4606)
* refactor: schema for attachments.create

* refactor: schema for attachments.delete

* refactor: remove deprecated "public" request param
2022-12-30 09:49:01 -08:00
Tom Moor f3469d25fe feat: Bulk HTML export (#4620)
* wip

* Working bulk html export

* Refactor

* test

* test
2022-12-30 09:42:20 -08:00
Tom Moor 1b8dd9399c chore: Export improvements (#4617)
* wip

* i18n
2022-12-27 09:51:39 -08:00
dependabot[bot] ee37ba9355 chore(deps-dev): bump @types/prosemirror-gapcursor from 1.0.4 to 1.3.0 (#4615)
Bumps [@types/prosemirror-gapcursor](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/prosemirror-gapcursor) from 1.0.4 to 1.3.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/prosemirror-gapcursor)

---
updated-dependencies:
- dependency-name: "@types/prosemirror-gapcursor"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-26 08:57:08 -08:00
dependabot[bot] 68ad7607b0 chore(deps): bump pg from 8.5.1 to 8.8.0 (#4614)
Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) from 8.5.1 to 8.8.0.
- [Release notes](https://github.com/brianc/node-postgres/releases)
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.8.0/packages/pg)

---
updated-dependencies:
- dependency-name: pg
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-26 08:56:29 -08:00
dependabot[bot] 393d9c4a72 chore(deps-dev): bump @types/react-helmet from 6.1.5 to 6.1.6 (#4612)
Bumps [@types/react-helmet](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-helmet) from 6.1.5 to 6.1.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-helmet)

---
updated-dependencies:
- dependency-name: "@types/react-helmet"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-26 08:54:37 -08:00
Tom Moor c41bd9592e feat: Add date/time template options to template titles 2022-12-24 15:53:05 +00:00
Tom Moor b8f748be52 Merge branch 'main' of github.com:outline/outline 2022-12-24 12:41:15 +00:00
Tom Moor 82c565f1d4 Add additional filters to search_titles endpoint (#4563)
* Add additional filters to search_titles endpoint

* tests, fixes for drafts

* fix: dateFilter results in 500

* fix: Draft documents returned in collection-only search
2022-12-24 03:44:22 -08:00
dependabot[bot] 504693c68d chore(deps): bump jsonwebtoken from 8.5.1 to 9.0.0 (#4600)
Bumps [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) from 8.5.1 to 9.0.0.
- [Release notes](https://github.com/auth0/node-jsonwebtoken/releases)
- [Changelog](https://github.com/auth0/node-jsonwebtoken/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jsonwebtoken/compare/v8.5.1...v9.0.0)

---
updated-dependencies:
- dependency-name: jsonwebtoken
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-22 04:01:05 -08:00
Tom Moor d261aa4d32 fix: Temporary fix for Mermaid Gantt charts – hardcode width
closes #4594
2022-12-22 06:50:57 -05:00
dependabot[bot] 09c3ee50ba chore(deps): bump prosemirror-dropcursor and @types/prosemirror-dropcursor (#4592)
Bumps [prosemirror-dropcursor](https://github.com/prosemirror/prosemirror-dropcursor) and [@types/prosemirror-dropcursor](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/prosemirror-dropcursor). These dependencies needed to be updated together.

Updates `prosemirror-dropcursor` from 1.4.0 to 1.6.1
- [Release notes](https://github.com/prosemirror/prosemirror-dropcursor/releases)
- [Changelog](https://github.com/ProseMirror/prosemirror-dropcursor/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prosemirror/prosemirror-dropcursor/compare/1.4.0...1.6.1)

Updates `@types/prosemirror-dropcursor` from 1.0.3 to 1.5.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/prosemirror-dropcursor)

---
updated-dependencies:
- dependency-name: prosemirror-dropcursor
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: "@types/prosemirror-dropcursor"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 16:51:12 -08:00
dependabot[bot] 0cb439857d chore(deps): bump babel-plugin-styled-components from 1.12.0 to 2.0.7 (#4589)
Bumps [babel-plugin-styled-components](https://github.com/styled-components/babel-plugin-styled-components) from 1.12.0 to 2.0.7.
- [Release notes](https://github.com/styled-components/babel-plugin-styled-components/releases)
- [Commits](https://github.com/styled-components/babel-plugin-styled-components/compare/v1.12.0...v2.0.7)

---
updated-dependencies:
- dependency-name: babel-plugin-styled-components
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 16:50:21 -08:00
dependabot[bot] 1a69cb057c chore(deps): bump exports-loader from 0.6.4 to 1.1.1 (#4590)
Bumps [exports-loader](https://github.com/webpack-contrib/exports-loader) from 0.6.4 to 1.1.1.
- [Release notes](https://github.com/webpack-contrib/exports-loader/releases)
- [Changelog](https://github.com/webpack-contrib/exports-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/exports-loader/compare/v0.6.4...v1.1.1)

---
updated-dependencies:
- dependency-name: exports-loader
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-20 16:49:41 -08:00
Tom Moor 0fa583e492 fix: Line numbers go missing when editing multiple blocks
closes #4440
2022-12-18 22:19:37 -05:00
Tom Moor 67ec5a1a33 fix: Missing onDelete constraint 2022-12-18 20:49:28 -05:00
Tom Moor 9618d514e1 fix: Switch workspace unreliable 2022-12-17 21:50:50 -05:00
Tom Moor 4b66a52a52 fix: Missing onDelete constraint 2022-12-17 21:19:55 -05:00
Tom Moor bf21863dbf New Crowdin updates (#4565)
* fix: New French translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Spanish translations from Crowdin [ci skip]

* fix: New Danish translations from Crowdin [ci skip]

* fix: New German translations from Crowdin [ci skip]

* fix: New Italian translations from Crowdin [ci skip]

* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Korean translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]

* fix: New Portuguese translations from Crowdin [ci skip]

* fix: New Russian translations from Crowdin [ci skip]

* fix: New Swedish translations from Crowdin [ci skip]

* fix: New Turkish translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Traditional translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Indonesian translations from Crowdin [ci skip]

* fix: New Persian translations from Crowdin [ci skip]

* fix: New Thai translations from Crowdin [ci skip]

* fix: New French translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Vietnamese translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]
2022-12-17 17:17:28 -08:00
Tom Moor acf74b83a8 feat: Full width images (#4389)
* feat: Full width images

* lint

* fix: Enable TOC overlaid on full size images

* Vendorize react-medium-image-zoom

* tsc

* fix

* Remove body scroll lock
2022-12-17 17:17:15 -08:00
Tom Moor f8ba393f7c Use auth.availableTeams endpoint for workspace switching (#4585) 2022-12-17 17:17:02 -08:00
Tom Moor 1995a3fb19 Dynamic bottom padding 2022-12-15 21:03:47 -05:00
Tom Moor 6f57767b7c fix: Return after redirect 2022-12-15 20:04:42 -05:00
Tom Moor a9683f4d53 fix: Add additional padding at the bottom of documents when editing 2022-12-14 20:44:38 -05:00
Tom Moor 600b3e4b3e fix: Small tweaks/fixes to custom domain UI 2022-12-14 08:46:35 -05:00
Tom Moor 02b352a382 fix: Cross-subdomain redirect for shares with custom link 2022-12-14 08:46:20 -05:00
Apoorv Mishra 79829a3129 Ability to create share url slug (#4550)
* feat: share url slug

* feat: add col urlId

* feat: allow updating urlId

* fix: typo

* fix: migrations

* fix: urlId model validation

* fix: input label

* fix: debounce slug request

* feat: link preview

* fix: send slug variant in response if available

* fix: temporary redirect to slug variant if available

* fix: move up the custom link field

* fix: process and display backend err

* fix: reset custom link state on popover close and remove isCopied

* fix: document link preview

* fix: set urlId when available

* fix: keep unique(urlId, teamId)

* fix: codeql

* fix: get rid of preview type

* fix: width not needed for block elem

* fix: migrations

* fix: array not required

* fix: use val

* fix: validation on shareId and test

* fix: allow clearing urlId

* fix: do not escape

* fix: unique error text

* fix: keep team
2022-12-13 17:26:36 -08:00
dependabot[bot] b9dd060736 chore(deps-dev): bump eslint-plugin-prettier from 3.1.4 to 4.2.1 (#4567)
Bumps [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) from 3.1.4 to 4.2.1.
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-plugin-prettier/compare/v3.1.4...v4.2.1)

---
updated-dependencies:
- dependency-name: eslint-plugin-prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 14:35:22 -08:00
dependabot[bot] 301fde26b6 chore(deps): bump copy-to-clipboard from 3.3.1 to 3.3.3 (#4570)
Bumps [copy-to-clipboard](https://github.com/sudodoki/copy-to-clipboard) from 3.3.1 to 3.3.3.
- [Release notes](https://github.com/sudodoki/copy-to-clipboard/releases)
- [Commits](https://github.com/sudodoki/copy-to-clipboard/compare/v3.3.1...v3.3.3)

---
updated-dependencies:
- dependency-name: copy-to-clipboard
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 13:32:56 -08:00
dependabot[bot] 662012da08 chore(deps-dev): bump husky from 7.0.4 to 8.0.2 (#4568)
Bumps [husky](https://github.com/typicode/husky) from 7.0.4 to 8.0.2.
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v7.0.4...v8.0.2)

---
updated-dependencies:
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 13:32:40 -08:00
dependabot[bot] cab8b69e8d chore(deps): bump class-validator from 0.13.2 to 0.14.0 (#4569)
Bumps [class-validator](https://github.com/typestack/class-validator) from 0.13.2 to 0.14.0.
- [Release notes](https://github.com/typestack/class-validator/releases)
- [Changelog](https://github.com/typestack/class-validator/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/typestack/class-validator/compare/v0.13.2...v0.14.0)

---
updated-dependencies:
- dependency-name: class-validator
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 13:32:15 -08:00
Tom Moor 91155295fe fix: Loosen url validation 2022-12-11 21:28:09 -05:00
Tom Moor 80780eedda fix: Mermaid diagrams do not respect dark mode (#4564)
* wip

* Move event binding
2022-12-11 11:33:17 -08:00
Tom Moor e4da92a359 New Crowdin updates (#4533) 2022-12-11 08:35:40 -08:00
Tom Moor 0f19c550f9 fix: Uploaded and immediately deleted images are not removed from storage (#4562)
* fix: Uploaded and immediately deleted images are not removed from storage upon permanant delete
closes #4557

* Move attachment deletion async
2022-12-11 08:29:38 -08:00
Tom Moor 7e22526cc7 Improve error handling 2022-12-11 11:27:54 -05:00
Apoorv Mishra 5c842087a5 feat(server): rate limit all routes (#4561) 2022-12-10 05:47:18 -08:00
Apoorv Mishra 053d10d893 Enhance server side error handling (#4537)
* fix: server side error handling

* fix: push only unknown 500 errors to sentry

* fix: use in-house onerror in favor of errorHandling middleware

* fix: split error template into dev and prod envs

* fix: check Error instance

* fix: error routes in test env

* fix: review comments

* Remove koa-onerror

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-12-09 21:51:42 +05:30
Tom Moor 4f67437b81 chore: Bump Sentry deps (#4556) 2022-12-08 18:05:13 -08:00
Alex 7db2284564 build: harden calibreapp-image-actions.yml permissions (#4555)
Signed-off-by: Alex <aleksandrosansan@gmail.com>

Signed-off-by: Alex <aleksandrosansan@gmail.com>
2022-12-08 17:49:15 -08:00
Tom Moor 92ab7c1700 Bump bull, ioredis (#4553) 2022-12-07 19:06:44 -08:00
Tom Moor 239db70374 fix: Bump qs, fix prototype pollution 2022-12-07 22:05:35 -05:00
dependabot[bot] a650e92979 chore(deps): bump fetch-retry from 4.1.1 to 5.0.3 (#4539)
Bumps [fetch-retry](https://github.com/jonbern/fetch-retry) from 4.1.1 to 5.0.3.
- [Release notes](https://github.com/jonbern/fetch-retry/releases)
- [Commits](https://github.com/jonbern/fetch-retry/compare/4.1.1...5.0.3)

---
updated-dependencies:
- dependency-name: fetch-retry
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 20:21:52 -08:00
dependabot[bot] 5f121ff268 chore(deps-dev): bump eslint-plugin-import from 2.25.3 to 2.26.0 (#4542)
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.25.3 to 2.26.0.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.25.3...v2.26.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 20:11:09 -08:00
Tom Moor ea63023fca feat: added user avatars in author search dropdown (#4551)
* feat: added user avatars in author search dropdown

* cleanup

* cleanup

* feat: added user avatars in author search dropdown

* cleanup

* cleanup

* added user icon

* Size tweaks

Co-authored-by: Aditya Sharma <aditya167411@gmail.com>
2022-12-06 20:10:56 -08:00
Tom Moor 549b7ab030 tsc 2022-12-06 09:32:13 -05:00
Tom Moor 4ce8ea8cd6 fix: Cannot create document from selection in root of collection 2022-12-06 09:10:45 -05:00
Tom Moor 98d79e1e8b perf: Improve collab persistence performance (#4544)
* stash

* Remove query of state in documentCollaborativeUpdater
2022-12-06 05:21:10 -08:00
Tom Moor b0b7c7d647 fix: Document import schema 2022-12-04 22:31:54 -05:00
Tom Moor 481382ee9f Add link to download app (macOS) 2022-12-04 18:03:35 -05:00
Tom Moor 3d6da26ad6 fix: Flash of external link decoration when creating doc from selected text 2022-12-04 17:41:19 -05:00
Tom Moor 0a68266365 fix: Server error in document search with single quotes 2022-12-04 17:10:06 -05:00
Tom Moor 908ca36de2 Merge branch 'main' of github.com:outline/outline 2022-12-04 15:32:33 -05:00
Tom Moor 435a7ab26b Dependency update 2022-12-04 15:07:17 -05:00
Aditya Sharma 8513200900 fix: Don't embed pasted links in list (#4535)
closes https://github.com/outline/outline/issues/4154
2022-12-04 11:41:03 -08:00
Tom Moor 1fd3f3137a chore: Upgrade hocuspocus (#4443)
* dep bump

* Bump to beta 6

* fix: Race condition in indexeddb provider
2022-12-04 11:39:58 -08:00
Tom Moor d16133fda8 Remove ui.isEditing, enable forcing desktop window open without sidebar 2022-12-04 11:55:33 -05:00
Tom Moor cd29cd3aec fix: Various improvements to select input, closes #4528 2022-12-04 10:57:09 -05:00
Tom Moor 13db16283a fix: Cleanup user menu (#4532)
Move confirmation dialogs from window confirmations
2022-12-03 15:33:16 -08:00
Tom Moor d6d1eb4485 feat: Prefix api keys 2022-12-03 18:21:33 -05:00
Tom Moor 0f31d5b45f fix: Generate signing secret on webhook creation 2022-12-03 10:23:31 -05:00
Tom Moor 08a471f230 Add 'members' filter to user details page, closes #4529 2022-12-03 09:36:28 -05:00
Tom Moor e15ad530de tsc 2022-12-03 09:25:53 -05:00
Denis 6354acca85 if OIDC provider gets user_id as integer Postgres failed query (#4527) 2022-12-02 21:46:56 -08:00
Tom Moor e32f2c2257 New Crowdin updates (#4493) 2022-12-02 20:05:45 -08:00
dependabot[bot] 6903a1c481 chore(deps-dev): bump babel-jest from 28.1.3 to 29.3.1 (#4497)
Bumps [babel-jest](https://github.com/facebook/jest/tree/HEAD/packages/babel-jest) from 28.1.3 to 29.3.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.3.1/packages/babel-jest)

---
updated-dependencies:
- dependency-name: babel-jest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-02 19:35:19 -08:00
Denis 571f812771 fix: getEncryptedColumn for empty token (#4507) 2022-12-02 19:28:43 -08:00
Tom Moor 4d1bbf3f80 Upgrade socket.io (#4526)
* Upgrade socket.io, drop support with v2 clients

* tsc
2022-12-02 19:06:37 -08:00
Tom Moor 0a0498d139 fix: Allow subdomains upto 255 in self-hosted, closes #4524 2022-12-02 22:06:13 -05:00
dependabot[bot] 0f19a82488 chore(deps): bump decode-uri-component from 0.2.0 to 0.2.2 (#4525)
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-02 17:16:33 -08:00
Tom Moor fc9d685ef5 fix: Remove unused S3 methods (#4515) 2022-12-01 19:45:24 -08:00
Tom Moor b305154715 Add onLogout method to desktop bridge 2022-12-01 18:14:51 -05:00
Tom Moor d09a3de800 fix: Desktop redirect on Safari 2022-12-01 08:26:01 -05:00
Tom Moor 83b687a632 fix: teamPermanentDeleter execution order 2022-11-30 23:07:37 -05:00
Tom Moor 648424fe2c fix: Desktop redirect on Safari 2022-11-30 23:00:40 -05:00
Tom Moor 63cef45284 fix: documents endpoints allow slug as id parameter 2022-11-29 22:16:46 -05:00
Tom Moor bc299a00f5 Add additional keywords for date slash commands 2022-11-28 23:36:30 -05:00
Tom Moor b40bb71adf fix: Allow clicking anywhere outside command menu to close 2022-11-28 23:35:41 -05:00
Tom Moor 59d9859a64 fix: Prevent hover styling when MenuItem is controlled 2022-11-28 21:18:15 -05:00
Tom Moor fbeaa2ec9f Handle keyboard shortcut request 2022-11-28 20:52:50 -05:00
dependabot[bot] 53669a4be6 chore(deps-dev): bump webpack from 4.44.1 to 4.46.0 (#4495)
Bumps [webpack](https://github.com/webpack/webpack) from 4.44.1 to 4.46.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v4.44.1...v4.46.0)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-28 16:56:17 -08:00
dependabot[bot] 201c3e1f05 chore(deps): bump @babel/preset-react from 7.16.0 to 7.18.6 (#4496)
Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.16.0 to 7.18.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.18.6/packages/babel-preset-react)

---
updated-dependencies:
- dependency-name: "@babel/preset-react"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-28 16:55:50 -08:00
dependabot[bot] 572ffe44aa chore(deps): bump polished from 3.7.2 to 4.2.2 (#4494)
Bumps [polished](https://github.com/styled-components/polished) from 3.7.2 to 4.2.2.
- [Release notes](https://github.com/styled-components/polished/releases)
- [Commits](https://github.com/styled-components/polished/compare/v3.7.2...v4.2.2)

---
updated-dependencies:
- dependency-name: polished
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-28 16:55:35 -08:00
Tom Moor 8ca5d66204 Desktop improvements (#4492)
* Update version to non-promise interface

* History navigation in sidebar
2022-11-28 15:30:50 -08:00
Tom Moor a5e2ac6570 fix: Negated quote query error 2022-11-28 09:01:03 -05:00
Tom Moor b5570a7587 New Crowdin updates (#4479) 2022-11-28 05:52:12 -08:00
Apoorv Mishra d09c583c72 Allow document to be dragged to the top of a collection (#4489) 2022-11-28 05:42:58 -08:00
Tom Moor cc333637dd Desktop support (#4484)
* Remove home link on desktop app

* Spellcheck, installation toasts, background styling, …

* Add email,slack, auth support

* More desktop style tweaks

* Move redirect to client

* cleanup

* Record desktop usage

* docs

* fix: Selection state in search input when double clicking header
2022-11-27 15:07:48 -08:00
Tom Moor ea9680c3d7 lint 2022-11-27 11:05:39 -05:00
Tom Moor d22b44dcff Further improved search matches 2022-11-27 10:46:54 -05:00
Tom Moor fa8685d241 Add support for LaTeX inline and block expressions. (#4446)
* Add support for LaTeX inline and block expressions. (#4364)

Co-authored-by: Tom Moor <tom@getoutline.com>

* tsc

* Show heading markers when LaTeX block is being edited

* Tab to space, name katex chunk

* Fork htmldiff, add support for math nodes

Co-authored-by: luisbc92 <luiscarlos.banuelos@gmail.com>
2022-11-27 06:27:56 -08:00
Tom Moor cb1b8e9764 fix: Improved search engine-like behavior for text queries 2022-11-27 09:26:10 -05:00
Tom Moor 957e9ba0ff fix: Cleanup build directory before building new server assets 2022-11-25 12:02:42 -05:00
Tom Moor 5a42f70b65 Add case for un-mapped custom domain to login page 2022-11-25 10:22:45 -05:00
Tom Moor fd9625b57e fix: TOC not rendered in non-seamless-editing mode 2022-11-24 11:35:29 -05:00
Tom Moor 18535d949e New Crowdin updates (#4476) 2022-11-24 06:51:47 -08:00
Tom Moor a8936039e5 Improved paste handling (#4474)
* Improved paste handling

* Remove file
2022-11-24 06:50:31 -08:00
Apoorv Mishra a6125be6f1 Introduce zod for server-side validations (#4397)
* chore(server): use zod for validations

* fix(server): use ctx.input for documents.list

* fix(server): schema for documents.archived

* fix(server): documents.deleted, documents.viewed & documents.drafts

* fix(server): documents.info

* fix(server): documents.export & documents.restore

* fix(server): documents.search_titles & documents.search

* fix(server): documents.templatize

* fix(server): replace nullish() with optional()

* fix(server): documents.update

* fix(server): documents.move

* fix(server): remaining

* fix(server): add validation for snippet min and max words

* fix(server): fix update types

* fix(server): remove DocumentSchema

* fix(server): collate duplicate schemas

* fix: typos

* fix: reviews

* chore: Fixed case of Metrics import

* fix: restructure /api

* fix: loosen validation for id as it can be a slug too

* Add test for query by slug
Simplify import

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-11-24 10:11:43 +05:30
Tom Moor 100d05035b Merge branch 'main' of github.com:outline/outline 2022-11-23 20:30:38 -05:00
Tom Moor 5b00741b1a New Crowdin updates (#4460) 2022-11-23 17:13:58 -08:00
Aditya Sharma 95f2c69f81 fix: correct stats for update-checker (#4470)
fixes https://github.com/outline/outline/issues/4462
2022-11-23 17:13:39 -08:00
Tom Moor 0794450596 chore: Fixed case of Metrics import 2022-11-22 23:08:52 -05:00
Tom Moor 09f5462068 Enable viewers to upload attachments for documents in collections where they have edit permission (#4468) 2022-11-22 19:05:08 -08:00
dependabot[bot] 4cb1652005 chore(deps-dev): bump babel-plugin-transform-inline-environment-variables from 0.4.3 to 0.4.4 (#4457)
Bumps [babel-plugin-transform-inline-environment-variables](https://github.com/babel/minify) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/babel/minify/releases)
- [Changelog](https://github.com/babel/minify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/minify/compare/babel-plugin-transform-inline-environment-variables@0.4.3...babel-plugin-transform-inline-environment-variables@0.4.4)

---
updated-dependencies:
- dependency-name: babel-plugin-transform-inline-environment-variables
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 19:12:11 -08:00
dependabot[bot] 7dbf098d68 chore(deps): bump jsdom from 20.0.0 to 20.0.3 (#4455)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 20.0.0 to 20.0.3.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/20.0.0...20.0.3)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 19:11:43 -08:00
dependabot[bot] 32e47d86a5 chore(deps-dev): bump @types/crypto-js from 4.1.0 to 4.1.1 (#4454)
Bumps [@types/crypto-js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/crypto-js) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/crypto-js)

---
updated-dependencies:
- dependency-name: "@types/crypto-js"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 19:11:18 -08:00
dependabot[bot] e76e547d8a chore(deps): bump rate-limiter-flexible from 2.3.7 to 2.4.1 (#4456)
Bumps [rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) from 2.3.7 to 2.4.1.
- [Release notes](https://github.com/animir/node-rate-limiter-flexible/releases)
- [Commits](https://github.com/animir/node-rate-limiter-flexible/commits/v2.4.1)

---
updated-dependencies:
- dependency-name: rate-limiter-flexible
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 19:11:07 -08:00
Tom Moor e605961e23 feat: Optional branding on shared documents (#4450)
* feat: Optional branding on shared documents

* Refactor
Remove unneccessarily exposed team id
Remove top-level collapsible document on publicly shared urls

* fix: Branding disappears when revising document
fix: Clicking title should go back to main app when logged in
2022-11-21 16:20:50 -08:00
Tom Moor 088ef81133 fix: Improved styles for diffs, closes #4430 2022-11-20 14:09:11 -05:00
Tom Moor 6e36ffb706 feat: Allow data imports larger than the standard attachment size (#4449)
* feat: Allow data imports larger than the standard attachment size

* Use correct preset for data imports

* Cleanup of expired attachments

* lint
2022-11-20 09:22:57 -08:00
Tom Moor 1f49bd167d fix: Flash of misaligned floating images upon loading 2022-11-19 20:18:55 -05:00
Tom Moor c27987569b fix: Flash of embeds visible upon loading when disabled 2022-11-19 20:09:56 -05:00
Tom Moor ae6855f3df chore: Refactors towards shared menu component (#4445) 2022-11-19 13:15:38 -08:00
Tom Moor 924b554281 fix: Padding below editor not clickable 2022-11-16 23:38:08 -05:00
Tom Moor 552c0ecf01 fix: Pasting document content in title should behave as expected 2022-11-16 23:38:08 -05:00
dependabot[bot] 19d33a7658 chore(deps): bump loader-utils from 1.4.1 to 1.4.2 (#4439)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 19:18:47 -08:00
Tom Moor f43f253286 Refactoring endpoints to transaction middleware 2022-11-15 22:22:35 -05:00
Tom Moor 01a482552a fix: Unable to subscribe to fileOperation webhook events 2022-11-15 20:03:20 -05:00
Tom Moor e6ef5a16cc Fix TOC headings 2022-11-14 21:14:56 -05:00
Tom Moor 4c8138ad4a fix: Some react warnings in dev mode 2022-11-14 19:36:24 -05:00
Tom Moor 4047ec73bb feat: Integrate Zapier App Directory 2022-11-14 18:10:10 -05:00
dependabot[bot] 1e723be556 chore(deps): bump koa-sslify from 2.1.2 to 5.0.0 (#4424)
* chore(deps): bump koa-sslify from 2.1.2 to 5.0.0

Bumps [koa-sslify](https://github.com/turboMaCk/koa-sslify) from 2.1.2 to 5.0.0.
- [Release notes](https://github.com/turboMaCk/koa-sslify/releases)
- [Changelog](https://github.com/turboMaCk/koa-sslify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/turboMaCk/koa-sslify/compare/2.1.2...5.0.0)

---
updated-dependencies:
- dependency-name: koa-sslify
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Nice try dependabot

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-11-14 14:17:05 -08:00
dependabot[bot] 1f5171053e chore(deps): bump core-js from 3.26.0 to 3.26.1 (#4421)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.26.0 to 3.26.1.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.26.1/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 13:35:19 -08:00
dependabot[bot] 829214d9a3 chore(deps): bump @juggle/resize-observer from 3.3.1 to 3.4.0 (#4422)
Bumps [@juggle/resize-observer](https://github.com/juggle/resize-observer) from 3.3.1 to 3.4.0.
- [Release notes](https://github.com/juggle/resize-observer/releases)
- [Commits](https://github.com/juggle/resize-observer/compare/v3.3.1...v3.4.0)

---
updated-dependencies:
- dependency-name: "@juggle/resize-observer"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 13:34:52 -08:00
dependabot[bot] 441055a05e chore(deps-dev): bump @types/validator from 13.7.8 to 13.7.10 (#4423)
Bumps [@types/validator](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/validator) from 13.7.8 to 13.7.10.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/validator)

---
updated-dependencies:
- dependency-name: "@types/validator"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 13:34:40 -08:00
Tom Moor 24a1eac804 Sidebar improvements from comments branch (#4419) 2022-11-13 18:26:53 -08:00
Tom Moor b60c66316a Insights refinements 2022-11-13 14:47:20 -05:00
Tom Moor 3880a956a3 Add document insights panel (#4418)
* Add document context to allow accessing editor in header, modals, and elsewhere

* lint

* framework

* Hacking together fast

* Insights

* Spacing tweak, docs
2022-11-13 10:19:09 -08:00
Tom Moor 762341a4ec feat: Track attachments access (#4416) 2022-11-12 08:41:59 -08:00
Tom Moor 622f464b9f Store import<->document relationship (#4415)
* Store import<->document relationship

* Update 20221112152649-import-document-relationship.js

* Store importId on collection, UI tweaks on import screen
2022-11-12 08:22:41 -08:00
Tom Moor cafe4ed848 Add seed script 2022-11-12 10:16:19 -05:00
Tom Moor cff67f4ca7 fix: Self-hosted logic for allowed domains (#4412)
* fix: Self-hosted logic for allowed domains

* test
2022-11-11 19:19:46 -08:00
Tom Moor 6788005115 Add missing team->user constraint (#4411)
* Add missing team->user constraint

* fix: teamPermanentDeleter cannot complete when team has domains
2022-11-11 09:40:52 -08:00
Tom Moor 26946853da fix: DATABASE_URL missing in env does not produce validation error (#4409)
* fix: DATABASE_URL missing in env does not produce validation error

* lint
2022-11-11 07:11:10 -08:00
Tom Moor d0827e21c1 tsc 2022-11-09 07:40:41 -05:00
Tom Moor eee0abe415 test 2022-11-08 21:42:08 -05:00
Tom Moor e7af0ce6de fix: getPreference fallback 2022-11-08 21:30:14 -05:00
Tom Moor 369ac487b1 feat: Add preference to disable download option for viewers 2022-11-08 21:26:02 -05:00
Tom Moor 587f062677 Remove usage of tiley (#4406)
* First pass

* Mooarrr

* lint

* snapshots
2022-11-08 17:12:22 -08:00
dependabot[bot] 920b58c006 chore(deps): bump loader-utils from 1.4.0 to 1.4.1 (#4405)
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.1/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 05:31:03 -08:00
dependabot[bot] d16d94a0f6 chore(deps): bump core-js from 3.10.2 to 3.26.0 (#4395)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.10.2 to 3.26.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.26.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 05:26:06 -08:00
dependabot[bot] 4d4cd42740 chore(deps): bump @bull-board/koa from 4.2.2 to 4.6.2 (#4394)
Bumps [@bull-board/koa](https://github.com/felixmosh/bull-board/tree/HEAD/packages/koa) from 4.2.2 to 4.6.2.
- [Release notes](https://github.com/felixmosh/bull-board/releases)
- [Changelog](https://github.com/felixmosh/bull-board/blob/master/CHANGELOG.md)
- [Commits](https://github.com/felixmosh/bull-board/commits/v4.6.2/packages/koa)

---
updated-dependencies:
- dependency-name: "@bull-board/koa"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 05:25:35 -08:00
dependabot[bot] b55ba473d1 chore(deps): bump @babel/plugin-transform-destructuring from 7.16.0 to 7.20.2 (#4396)
Bumps [@babel/plugin-transform-destructuring](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-destructuring) from 7.16.0 to 7.20.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.20.2/packages/babel-plugin-transform-destructuring)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-destructuring"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-08 05:24:55 -08:00
Tom Moor c859d2dd84 fix: Deleted text style in history, closes #4231 2022-11-07 21:55:14 -05:00
Tom Moor fd799e00a7 fix: Unauthenticated shared document should default to user preferred language
closes #4384
2022-11-06 18:53:05 -05:00
Tom Moor 5f4d67e2f9 Bump caniuse 2022-11-06 14:10:48 -05:00
Tom Moor 9936f42882 Avoid fsstat on every request, remove koa-static (#4387)
* Avoid fsstat on every request, remove koa-static

* tsx

* Move compression middleware
2022-11-05 06:50:46 -07:00
Translate-O-Tron bac1c9dc14 New Crowdin updates (#4327) 2022-11-03 18:39:23 -07:00
Tom Moor 2df4b352a1 fix: Hard to resize image larger than documen width immediately after uploading 2022-11-03 20:16:56 -04:00
Tom Moor f2fb5dd1e5 fix: Team creation with private avatar. Do not attempt to copy, closes #4378 2022-11-03 08:58:33 -04:00
Tom Moor c2de6b70bc fix: Image resizing on mobile/touchscreen 2022-11-03 08:11:11 -04:00
Tom Moor 88188a0a59 fix: Sanitize url before opening 2022-11-03 07:38:35 -04:00
Tom Moor 5e17b24869 feat: Image resizing (#4368)
* wip

* works

* wip

* refactor

* Support replacing image and retain width
fix: Copy paste does not retain size

* cleanup

* fix: Cannot resize past 100%
fix: Borders to edges on unresized images

* Handle Escape key while dragging

* fix: Embeds and images dont render when edit state changes
fix: Small animation regression
2022-11-02 18:40:37 -07:00
Tom Moor 6f8d01df21 fix: Sanitize url before opening 2022-11-02 21:38:16 -04:00
Mihir Shah 881ea34dfe chore: convert AddGroupToCollection component to functional component (#4204) (#4360) 2022-11-02 17:31:13 -07:00
Tom Moor 3cb0b88f0f Update MarkAsViewed.ts 2022-11-01 18:42:59 -07:00
dependabot[bot] d4cac4983c chore(deps-dev): bump @types/enzyme from 3.10.10 to 3.10.12 (#4371)
Bumps [@types/enzyme](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/enzyme) from 3.10.10 to 3.10.12.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/enzyme)

---
updated-dependencies:
- dependency-name: "@types/enzyme"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-01 05:22:17 -07:00
Tom Moor ab6c5c2e78 Missing observer 2022-11-01 08:21:59 -04:00
Mihir Shah ade26139e6 chore: convert AddPeopleToGroup component to functional component (#4204) (#4359) 2022-11-01 05:17:26 -07:00
Ítalo Sousa 17977064aa Functional Component Refactor: MarkAsViewed (#4365)
* chore: convert MarkAsViewed to functional component

* chore: fix issues with MarkAsViewed refactor
2022-11-01 05:08:07 -07:00
dependabot[bot] 5b55f7ab1c chore(deps): bump jszip from 3.10.0 to 3.10.1 (#4370)
Bumps [jszip](https://github.com/Stuk/jszip) from 3.10.0 to 3.10.1.
- [Release notes](https://github.com/Stuk/jszip/releases)
- [Changelog](https://github.com/Stuk/jszip/blob/main/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/compare/v3.10.0...v3.10.1)

---
updated-dependencies:
- dependency-name: jszip
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 14:21:08 -07:00
Tom Moor 1e62d25861 Refactor document search 2022-10-30 12:41:52 -04:00
Tom Moor 86aa531fad Utility method to re-derive text field from CRDT 2022-10-30 10:29:32 -04:00
Tom Moor f6f90ff406 fix: Unable to login with matching email from another auth provider (#4356)
* fix: Unable to login with matching email from another auth provider

* refactor
2022-10-29 13:46:29 -07:00
Tom Moor 79cbe304da fix: Allow viewers to upload avatar (#4349)
* fix: Allow viewers to upload avatar

* DeleteAttachmentTask

* fix: Previous avatar should be deleted on change, if possible

* fix: Also cleanup team logo on change
2022-10-29 06:08:20 -07:00
Apoorv Mishra 19e26ba402 Return correct permissions upon document update (#4352) 2022-10-28 05:20:42 -07:00
Tom Moor c916d4f594 spike: db transaction as middleware (#4301) 2022-10-26 17:38:37 -07:00
dependabot[bot] 51b3371bf5 chore(deps): bump mermaid and @types/mermaid (#4257)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-10-26 19:07:52 -04:00
Tom Moor 39d8eb8a3a Merge branch 'main' of github.com:outline/outline 2022-10-26 19:01:32 -04:00
Mihir Shah c1fb8c74ff chore: convert Avatar component to functional component (#4204) (#4337) 2022-10-26 16:01:28 -07:00
Duale Siad ca255d9210 Added syntax highlighting for various languages (#4341)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-10-26 16:01:12 -07:00
Tom Moor fe3e8d3830 More flexible subdomain validation 2022-10-26 07:23:33 -04:00
Mihir Shah 808eb540a7 chore: convert PlaceholderText component to functional component (#4204) (#4336) 2022-10-25 14:44:20 -07:00
Apoorv Mishra a89d30c735 Allow drafts to be created without requiring a collection (#4175)
* feat(server): allow document to be created without collectionId

* fix(server): policies for a draft doc without collection

* fix(app): hide share button for drafts

* feat(server): permissions around publishing a draft

* fix(server): return drafts without collection

* fix(server): handle draft deletion

* fix(server): show drafts in deleted docs

* fix(server): allow drafts without collection to be restored

* feat(server): return drafts in search results

* fix: use buildDraftDocument for drafts

* fix: remove isDraftWithoutCollection

* fix: do not return drafts for team

* fix: put invariants

* fix: query clause

* fix: check only for undefined

* fix: restore includeDrafts clause as it was before
2022-10-25 18:01:57 +05:30
dependabot[bot] 6b74d43380 chore(deps-dev): bump eslint-import-resolver-typescript from 3.5.1 to 3.5.2 (#4329)
Bumps [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-import-resolver-typescript/compare/v3.5.1...v3.5.2)

---
updated-dependencies:
- dependency-name: eslint-import-resolver-typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 17:17:51 -07:00
dependabot[bot] 249f340b21 chore(deps-dev): bump nodemon from 2.0.18 to 2.0.20 (#4330)
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.18 to 2.0.20.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.18...v2.0.20)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-24 17:17:38 -07:00
Tom Moor f63bf336f1 fix: Show code block line numbers by default 2022-10-24 19:18:43 -04:00
Tom Moor c3c1de09ab Settings 2022-10-24 18:01:27 -04:00
Tom Moor df46d3754a feat: Authentication provider display (#4332)
* layout

* Refactor

* wip

* Quick changes to make this deployable without full management

* test
2022-10-24 14:01:40 -07:00
Tom Moor 434bb989cc Stray console.log 2022-10-24 12:04:55 -07:00
Translate-O-Tron b5b349be29 New Crowdin updates (#4302) 2022-10-24 06:45:04 -07:00
Tom Moor 87761e9bf2 feat: Code blocks can now optionally display line numbers (#4324)
* feat: Code blocks can now optionally display line numbers as a user preference

* Touch more breathing room
2022-10-24 06:44:46 -07:00
Tom Moor 708f9a3fd6 feat: Add additional 'smart text' replacements 2022-10-23 17:43:17 -04:00
dependabot[bot] 8d47a05591 chore(deps): bump react-hook-form from 7.31.2 to 7.37.0 (#4309)
Bumps [react-hook-form](https://github.com/react-hook-form/react-hook-form) from 7.31.2 to 7.37.0.
- [Release notes](https://github.com/react-hook-form/react-hook-form/releases)
- [Changelog](https://github.com/react-hook-form/react-hook-form/blob/master/CHANGELOG.md)
- [Commits](https://github.com/react-hook-form/react-hook-form/compare/v7.31.2...v7.37.0)

---
updated-dependencies:
- dependency-name: react-hook-form
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-23 11:04:40 -07:00
Daniyaal Beg fabdcd03e2 Update Architecture.md (#4323) 2022-10-23 11:04:08 -07:00
Tom Moor 44ce377c38 fix #4183 2022-10-23 14:00:53 -04:00
github-actions[bot] d43423fc39 chore: Auto Compress Images (#4322)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2022-10-23 10:45:12 -07:00
Tom Moor e00e3e232a fix: Hard to select text in link editor input 2022-10-23 13:43:22 -04:00
Tom Moor 1f1dd23e18 feat: Add block command to create Mermaid diagram
closes #4272
2022-10-23 13:28:01 -04:00
Tom Moor 8ba911b56d fix: Slight misalignment of archived badge 2022-10-23 13:00:57 -04:00
Tom Moor e714e934cb Tweak layout of login screen to account for new custom logos 2022-10-23 11:36:54 -04:00
Tom Moor 60f6a1f1c6 fix: More flexible link validation in editor allows custom protocols
closes #4319
2022-10-23 08:15:15 -04:00
Tom Moor 9af22017fe fix: Do not oclude text on completed tasks, closes #4283 2022-10-23 07:52:23 -04:00
Tom Moor f6ae32deef Co-authored-by: Nan Yu <thenanyu@users.noreply.github.com> 2022-10-22 23:29:39 -04:00
Tom Moor c0a86753bd 0.66.2 2022-10-22 11:24:04 -04:00
Tom Moor f277d08982 fix: Actor on users.delete 2022-10-22 11:17:31 -04:00
Tom Moor 49d53ccfc2 fix: Disallow adding self to collection (#4299)
* api

* ui

* update collection permissions
2022-10-22 11:14:18 -04:00
dependabot[bot] c108a91195 chore(deps-dev): bump @types/markdown-it-container from 2.0.4 to 2.0.5 (#4308)
Bumps [@types/markdown-it-container](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/markdown-it-container) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/markdown-it-container)

---
updated-dependencies:
- dependency-name: "@types/markdown-it-container"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-20 04:44:59 -07:00
dependabot[bot] 6caa61f4a5 chore(deps-dev): bump @types/validator from 13.7.1 to 13.7.8 (#4310)
Bumps [@types/validator](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/validator) from 13.7.1 to 13.7.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/validator)

---
updated-dependencies:
- dependency-name: "@types/validator"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-20 04:44:30 -07:00
Tom Moor a814543aaf fix: Drag-n-drop 2022-10-19 21:53:22 -04:00
Tom Moor 167ade0d59 fix: Flash of starred documents on Home screen 2022-10-19 21:53:22 -04:00
Tom Moor b8b0d927f2 Fade in viewer information 2022-10-19 21:53:22 -04:00
Tom Moor 6072d3320a Handle keyboard navigation 2022-10-19 21:53:22 -04:00
Tom Moor 1a88fd5515 Working fast-click 2022-10-19 21:53:22 -04:00
Tom Moor 3f3c05c800 stash 2022-10-19 21:53:22 -04:00
Apoorv Mishra bb21fa725c Add team preference to use logo for branding (#4285)
* feat: add team preference to use logo for branding

* fix: allow on cloud version too
2022-10-19 10:01:24 +05:30
Tom Moor 98f997387c fix: Multi-method handlers, regressed in methodOverride removal 2022-10-18 23:50:14 -04:00
Tom Moor 7a9c75b9f1 Remove stray log 2022-10-18 21:49:37 -04:00
Tom Moor 98e44f528f 0.66.1 2022-09-21 09:05:39 -04:00
Tom Moor 0e79795856 fix: Cannot download export result, closes #4059 2022-09-21 09:05:26 -04:00
1396 changed files with 80535 additions and 42141 deletions
-1
View File
@@ -14,7 +14,6 @@
]
],
"plugins": [
"lodash",
"styled-components",
[
"@babel/plugin-proposal-decorators",
+21 -8
View File
@@ -3,7 +3,7 @@ version: 2.1
defaults: &defaults
working_directory: ~/outline
docker:
- image: cimg/node:14.19
- image: cimg/node:18.12
- image: cimg/redis:5.0
- image: cimg/postgres:14.2
environment:
@@ -20,6 +20,7 @@ defaults: &defaults
SMTP_FROM_EMAIL: hello@example.com
AWS_S3_UPLOAD_BUCKET_URL: https://s3.amazonaws.com
AWS_S3_UPLOAD_BUCKET_NAME: outline-circle
NODE_OPTIONS: --max-old-space-size=8000
executors:
docker-publisher:
@@ -81,6 +82,7 @@ jobs:
command: yarn test:shared
test-server:
<<: *defaults
parallelism: 3
steps:
- checkout
- restore_cache:
@@ -90,16 +92,23 @@ jobs:
command: ./node_modules/.bin/sequelize db:migrate --url $DATABASE_URL_TEST
- run:
name: test
command: yarn test:server --forceExit
command: |
TESTFILES=$(circleci tests glob "server/**/*.test.ts" | circleci tests split)
yarn test --maxWorkers=2 $TESTFILES
bundle-size:
<<: *defaults
environment:
NODE_ENV: production
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: build-webpack
command: yarn build:webpack
name: build-vite
command: yarn vite:build
- run:
name: Send bundle stats to RelativeCI
command: npx relative-ci-agent
build-image:
executor: docker-publisher
steps:
@@ -136,7 +145,12 @@ jobs:
command: docker push $BASE_IMAGE_NAME:latest
- run:
name: Build and push Docker image
command: docker buildx build -t $IMAGE_NAME:latest -t $IMAGE_NAME:${CIRCLE_TAG/v/''} --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x --push .
command: |
if [[ "$CIRCLE_TAG" == *"-"* ]]; then
docker buildx build -t $IMAGE_NAME:${CIRCLE_TAG/v/''} --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x --push .
else
docker buildx build -t $IMAGE_NAME:latest -t $IMAGE_NAME:${CIRCLE_TAG/v/''} --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x --push .
fi
workflows:
version: 2
@@ -160,9 +174,8 @@ workflows:
- build
- bundle-size:
requires:
- test-app
- test-shared
- test-server
- build
- types
build-docker:
jobs:
-1
View File
@@ -13,5 +13,4 @@ app.json
crowdin.yml
build
docker-compose.yml
fakes3
node_modules
+28 -8
View File
@@ -30,7 +30,7 @@ REDIS_URL=redis://localhost:6379
# URL should point to the fully qualified, publicly accessible URL. If using a
# proxy the port in URL and PORT may be different.
URL=http://localhost:3000
URL=https://app.outline.dev:3000
PORT=3000
# See [documentation](docs/SERVICES.md) on running a separate collaboration
@@ -51,10 +51,20 @@ AWS_REGION=xx-xxxx-x
AWS_S3_ACCELERATE_URL=
AWS_S3_UPLOAD_BUCKET_URL=http://s3:4569
AWS_S3_UPLOAD_BUCKET_NAME=bucket_name_here
AWS_S3_UPLOAD_MAX_SIZE=26214400
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private
# Specify what storage system to use. Possible value is one of "s3" or "local".
# For "local", the avatar images and document attachments will be saved on local disk.
FILE_STORAGE=local
# If "local" is configured for FILE_STORAGE above, then this sets the parent directory under
# which all attachments/images go. Make sure that the process has permissions to create
# this path and also to write files to it.
FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data
# Maximum allowed size for the uploaded attachment.
FILE_STORAGE_UPLOAD_MAX_SIZE=26214400
# –––––––––––––– AUTHENTICATION ––––––––––––––
@@ -99,7 +109,7 @@ OIDC_USERINFO_URI=
OIDC_USERNAME_CLAIM=preferred_username
# Display name for OIDC authentication
OIDC_DISPLAY_NAME=OpenID
OIDC_DISPLAY_NAME=OpenID Connect
# Space separated auth scopes.
OIDC_SCOPES=openid profile email
@@ -139,6 +149,10 @@ MAXIMUM_IMPORT_SIZE=5120000
# requests and this ends up being duplicative
DEBUG=http
# Configure lowest severity level for server logs. Should be one of
# error, warn, info, http, verbose, debug and silly
LOG_LEVEL=info
# For a complete Slack integration with search and posting to channels the
# following configs are also needed, some more details
# => https://wiki.generaloutline.com/share/be25efd1-b3ef-4450-b8e5-c4a4fc11e02a
@@ -162,14 +176,11 @@ SMTP_HOST=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_FROM_EMAIL=
SMTP_REPLY_EMAIL=
SMTP_FROM_EMAIL=hello@example.com
SMTP_REPLY_EMAIL=hello@example.com
SMTP_TLS_CIPHERS=
SMTP_SECURE=true
# Custom logo that displays on the authentication screen, scaled to height: 60px
# TEAM_LOGO=https://example.com/images/logo.png
# The default interface language. See translate.getoutline.com for a list of
# available language codes and their rough percentage translated.
DEFAULT_LANGUAGE=en_US
@@ -180,3 +191,12 @@ RATE_LIMITER_ENABLED=true
# Configure default throttling parameters for rate limiter
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60
# Iframely API config
# IFRAMELY_URL=
# IFRAMELY_API_KEY=
# Enable unsafe-inline in script-src CSP directive
# Setting it to true allows React dev tools add-on in
# Firefox to successfully detect the project
DEVELOPMENT_UNSAFE_INLINE_CSP=false
+18 -1
View File
@@ -3,6 +3,7 @@
"parserOptions": {
"sourceType": "module",
"extraFileExtensions": [".json"],
"project": "./tsconfig.json",
"ecmaFeatures": {
"jsx": true
}
@@ -20,15 +21,30 @@
"eslint-plugin-import",
"eslint-plugin-node",
"eslint-plugin-react",
"import"
"eslint-plugin-lodash"
],
"rules": {
"eqeqeq": 2,
"curly": 2,
"no-console": "error",
"arrow-body-style": ["error", "as-needed"],
"spaced-comment": "error",
"object-shorthand": "error",
"no-mixed-operators": "off",
"no-useless-escape": "off",
"es/no-regexp-lookbehind-assertions": "error",
"react/self-closing-comp": ["error", {
"component": true,
"html": true
}],
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/no-misused-promises": [
"error",
{
"checksVoidReturn": false
}
],
"@typescript-eslint/no-unused-vars": [
"error",
{
@@ -39,6 +55,7 @@
],
"padding-line-between-statements": ["error", { "blankLine": "always", "prev": "*", "next": "export" }],
"lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
"lodash/import-scope": ["warn", "method"],
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off",
"import/newline-after-import": 2,
+2 -2
View File
@@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Feature request
url: https://github.com/outline/outline/discussions/new
url: https://github.com/outline/outline/discussions/new?category=ideas
about: Request a feature to be added to the project
- name: Self hosting questions
url: https://github.com/outline/outline/discussions/new
url: https://github.com/outline/outline/discussions/new?category=self-hosting
about: Ask questions and discuss running Outline with community members
+4
View File
@@ -7,5 +7,9 @@ version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
open-pull-requests-limit: 5
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
schedule:
interval: "weekly"
@@ -24,8 +24,13 @@ on:
workflow_dispatch:
schedule:
- cron: "00 20 * * 0"
permissions: {}
jobs:
build:
permissions:
contents: write
pull-requests: write # to comment on pull request
name: calibreapp/image-actions
runs-on: ubuntu-latest
# Only run on main repo on and PRs that match the main repo.
+2 -2
View File
@@ -7,8 +7,8 @@ node_modules/*
npm-debug.log
stats.json
.DS_Store
fakes3/*
data/*
.idea
*.pem
*.key
*.cert
*.cert
+17 -43
View File
@@ -1,46 +1,32 @@
{
"workerIdleMemoryLimit": "0.75",
"maxWorkers": "50%",
"projects": [
{
"displayName": "server",
"verbose": false,
"roots": [
"<rootDir>/server"
],
"roots": ["<rootDir>/server", "<rootDir>/plugins"],
"moduleNameMapper": {
"^@server/(.*)$": "<rootDir>/server/$1",
"^@shared/(.*)$": "<rootDir>/shared/$1"
},
"setupFiles": [
"<rootDir>/__mocks__/console.js",
"<rootDir>/server/test/env.ts"
],
"setupFilesAfterEnv": [
"<rootDir>/server/test/setup.ts"
],
"testEnvironment": "node",
"runner": "@getoutline/jest-runner-serial"
"setupFiles": ["<rootDir>/__mocks__/console.js", "<rootDir>/server/test/env.ts"],
"setupFilesAfterEnv": ["<rootDir>/server/test/setup.ts"],
"globalSetup": "<rootDir>/server/test/globalSetup.js",
"globalTeardown": "<rootDir>/server/test/globalTeardown.js",
"testEnvironment": "node"
},
{
"displayName": "app",
"verbose": false,
"roots": [
"<rootDir>/app"
],
"roots": ["<rootDir>/app"],
"moduleNameMapper": {
"^~/(.*)$": "<rootDir>/app/$1",
"^@shared/(.*)$": "<rootDir>/shared/$1",
"^.*[.](gif|ttf|eot|svg)$": "<rootDir>/__test__/fileMock.js",
"^uuid$": "<rootDir>/node_modules/uuid/dist/index.js"
},
"modulePaths": [
"<rootDir>/app"
],
"setupFiles": [
"<rootDir>/__mocks__/window.js"
],
"setupFilesAfterEnv": [
"<rootDir>/app/test/setup.ts"
],
"modulePaths": ["<rootDir>/app"],
"setupFiles": ["<rootDir>/__mocks__/window.js"],
"setupFilesAfterEnv": ["<rootDir>/app/test/setup.ts"],
"testEnvironment": "jsdom",
"testEnvironmentOptions": {
"url": "http://localhost"
@@ -48,37 +34,25 @@
},
{
"displayName": "shared-node",
"verbose": false,
"roots": [
"<rootDir>/shared"
],
"roots": ["<rootDir>/shared"],
"moduleNameMapper": {
"^@server/(.*)$": "<rootDir>/server/$1",
"^@shared/(.*)$": "<rootDir>/shared/$1"
},
"setupFiles": [
"<rootDir>/__mocks__/console.js"
],
"setupFilesAfterEnv": [
"<rootDir>/shared/test/setup.ts"
],
"setupFiles": ["<rootDir>/__mocks__/console.js"],
"setupFilesAfterEnv": ["<rootDir>/shared/test/setup.ts"],
"testEnvironment": "node"
},
{
"displayName": "shared-jsdom",
"verbose": false,
"roots": [
"<rootDir>/shared"
],
"roots": ["<rootDir>/shared"],
"moduleNameMapper": {
"^~/(.*)$": "<rootDir>/app/$1",
"^@shared/(.*)$": "<rootDir>/shared/$1",
"^.*[.](gif|ttf|eot|svg)$": "<rootDir>/__test__/fileMock.js",
"^uuid$": "<rootDir>/node_modules/uuid/dist/index.js"
},
"setupFiles": [
"<rootDir>/__mocks__/window.js"
],
"setupFiles": ["<rootDir>/__mocks__/window.js"],
"testEnvironment": "jsdom",
"testEnvironmentOptions": {
"url": "http://localhost"
+15 -2
View File
@@ -5,7 +5,11 @@ ARG APP_PATH
WORKDIR $APP_PATH
# ---
FROM node:16.14.2-alpine3.15 AS runner
FROM node:18-alpine AS runner
RUN apk update && apk add --no-cache curl && apk add --no-cache ca-certificates
LABEL org.opencontainers.image.source="https://github.com/outline/outline"
ARG APP_PATH
WORKDIR $APP_PATH
@@ -20,7 +24,16 @@ COPY --from=base $APP_PATH/package.json ./package.json
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001 && \
chown -R nodejs:nodejs $APP_PATH/build
chown -R nodejs:nodejs $APP_PATH/build && \
mkdir -p /var/lib/outline && \
chown -R nodejs:nodejs /var/lib/outline
ENV FILE_STORAGE_LOCAL_ROOT_DIR /var/lib/outline/data
RUN mkdir -p "$FILE_STORAGE_LOCAL_ROOT_DIR" && \
chown -R nodejs:nodejs "$FILE_STORAGE_LOCAL_ROOT_DIR" && \
chmod 1777 "$FILE_STORAGE_LOCAL_ROOT_DIR"
VOLUME /var/lib/outline/data
USER nodejs
+2 -1
View File
@@ -1,9 +1,10 @@
ARG APP_PATH=/opt/outline
FROM node:16.14.2-alpine3.15 AS deps
FROM node:18-alpine AS deps
ARG APP_PATH
WORKDIR $APP_PATH
COPY ./package.json ./yarn.lock ./
COPY ./patches ./patches
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
yarn cache clean
+2 -2
View File
@@ -3,7 +3,7 @@ Business Source License 1.1
Parameters
Licensor: General Outline, Inc.
Licensed Work: Outline 0.64.0
Licensed Work: Outline 0.71.0
The Licensed Work is (c) 2020 General Outline, Inc.
Additional Use Grant: You may make use of the Licensed Work, provided that
you may not use the Licensed Work for a Document
@@ -15,7 +15,7 @@ Additional Use Grant: You may make use of the Licensed Work, provided that
Licensed Work by creating teams and documents
controlled by such third parties.
Change Date: 2026-05-23
Change Date: 2027-08-18
Change License: Apache License, Version 2.0
+6 -6
View File
@@ -1,24 +1,24 @@
up:
docker-compose up -d redis postgres s3
docker-compose up -d redis postgres
yarn install-local-ssl
yarn install --pure-lockfile
yarn sequelize db:migrate
yarn dev:watch
build:
docker-compose build --pull outline
test:
docker-compose up -d redis postgres s3
docker-compose up -d redis postgres
yarn sequelize db:drop --env=test
yarn sequelize db:create --env=test
yarn sequelize db:migrate --env=test
NODE_ENV=test yarn sequelize db:migrate --env=test
yarn test
watch:
docker-compose up -d redis postgres s3
docker-compose up -d redis postgres
yarn sequelize db:drop --env=test
yarn sequelize db:create --env=test
yarn sequelize db:migrate --env=test
NODE_ENV=test yarn sequelize db:migrate --env=test
yarn test:watch
destroy:
+9 -5
View File
@@ -7,26 +7,26 @@
<img width="1640" alt="screenshot" src="https://user-images.githubusercontent.com/380914/110356468-26374600-7fef-11eb-9f6a-f2cc2c8c6590.png">
</p>
<p align="center">
<a href="https://circleci.com/gh/outline/outline" rel="nofollow"><img src="https://circleci.com/gh/outline/outline.svg?style=shield&amp;circle-token=c0c4c2f39990e277385d5c1ae96169c409eb887a"></a>
<a href="https://circleci.com/gh/outline/outline" rel="nofollow"><img src="https://circleci.com/gh/outline/outline.svg?style=shield"></a>
<a href="http://www.typescriptlang.org" rel="nofollow"><img src="https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg" alt="TypeScript"></a>
<a href="https://github.com/prettier/prettier"><img src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat" alt="Prettier"></a>
<a href="https://github.com/styled-components/styled-components"><img src="https://img.shields.io/badge/style-%F0%9F%92%85%20styled--components-orange.svg" alt="Styled Components"></a>
<a href="https://translate.getoutline.com/project/outline" alt="Localized"><img src="https://badges.crowdin.net/outline/localized.svg"></a>
</p>
This is the source code that runs [**Outline**](https://www.getoutline.com) and all the associated services. If you want to use Outline then you don't need to run this code, we offer a hosted version of the app at [getoutline.com](https://www.getoutline.com).
This is the source code that runs [**Outline**](https://www.getoutline.com) and all the associated services. If you want to use Outline then you don't need to run this code, we offer a hosted version of the app at [getoutline.com](https://www.getoutline.com). You can also find documentation on using Outline in [our guide](https://docs.getoutline.com/s/guide).
If you'd like to run your own copy of Outline or contribute to development then this is the place for you.
# Installation
Please see the [documentation](https://app.getoutline.com/share/770a97da-13e5-401e-9f8a-37949c19f97e/) for running your own copy of Outline in a production configuration.
Please see the [documentation](https://docs.getoutline.com/s/hosting/) for running your own copy of Outline in a production configuration.
If you have questions or improvements for the docs please create a thread in [GitHub discussions](https://github.com/outline/outline/discussions).
# Development
There is a short guide for [setting up a development environment](https://app.getoutline.com/share/770a97da-13e5-401e-9f8a-37949c19f97e/doc/local-development-5hEhFRXow7) if you wish to contribute changes, fixes, and improvements to Outline.
There is a short guide for [setting up a development environment](https://docs.getoutline.com/s/hosting/doc/local-development-5hEhFRXow7) if you wish to contribute changes, fixes, and improvements to Outline.
## Contributing
@@ -96,6 +96,10 @@ Or to run migrations on test database:
yarn sequelize db:migrate --env test
```
## License
# Activity
![Alt](https://repobeats.axiom.co/api/embed/ff2e4e6918afff1acf9deb72d1ba6b071d586178.svg "Repobeats analytics image")
# License
Outline is [BSL 1.1 licensed](LICENSE).
+8 -18
View File
@@ -3,13 +3,7 @@
"description": "Open source wiki and knowledge base for growing teams",
"website": "https://www.getoutline.com/",
"repository": "https://github.com/outline/outline",
"keywords": [
"wiki",
"team",
"node",
"markdown",
"slack"
],
"keywords": ["wiki", "team", "node", "markdown", "slack"],
"success_url": "/",
"formation": {
"web": {
@@ -94,7 +88,7 @@
},
"OIDC_DISPLAY_NAME": {
"description": "Display name for OIDC authentication",
"value": "OpenID",
"value": "OpenID Connect",
"required": false
},
"OIDC_SCOPES": {
@@ -134,11 +128,6 @@
"description": "Live web link to your bucket. For CNAMEs, https://yourbucket.example.com",
"required": false
},
"AWS_S3_UPLOAD_MAX_SIZE": {
"description": "Maximum file upload size in bytes",
"value": "26214400",
"required": false
},
"AWS_S3_FORCE_PATH_STYLE": {
"description": "Use path-style URL's for connecting to S3 instead of subdomain. This is useful for S3-compatible storage.",
"value": "true",
@@ -154,6 +143,11 @@
"description": "S3 canned ACL for document attachments",
"required": false
},
"FILE_STORAGE_UPLOAD_MAX_SIZE": {
"description": "Maximum file upload size in bytes",
"value": "26214400",
"required": false
},
"SMTP_HOST": {
"description": "smtp.example.com (optional)",
"required": false
@@ -188,7 +182,7 @@
"required": false
},
"GOOGLE_ANALYTICS_ID": {
"description": "UA-xxxx (optional)",
"description": "G-xxxx (optional)",
"required": false
},
"SENTRY_DSN": {
@@ -199,10 +193,6 @@
"description": "A sentry tunnel URL for bypassing ad blockers in the UI (optional)",
"required": false
},
"TEAM_LOGO": {
"description": "A logo that will be displayed on the signed out home page",
"required": false
},
"DEFAULT_LANGUAGE": {
"value": "en_US",
"description": "The default interface language. See translate.getoutline.com for a list of available language codes and their rough percentage translated.",
+1
View File
@@ -1,6 +1,7 @@
{
"extends": [
"../.eslintrc",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
],
"plugins": [
+51 -8
View File
@@ -4,6 +4,7 @@ import {
PadlockIcon,
PlusIcon,
StarredIcon,
TrashIcon,
UnstarredIcon,
} from "outline-icons";
import * as React from "react";
@@ -12,17 +13,19 @@ import Collection from "~/models/Collection";
import CollectionEdit from "~/scenes/CollectionEdit";
import CollectionNew from "~/scenes/CollectionNew";
import CollectionPermissions from "~/scenes/CollectionPermissions";
import DynamicCollectionIcon from "~/components/CollectionIcon";
import CollectionDeleteDialog from "~/components/CollectionDeleteDialog";
import DynamicCollectionIcon from "~/components/Icons/CollectionIcon";
import { createAction } from "~/actions";
import { CollectionSection } from "~/actions/sections";
import history from "~/utils/history";
const ColorCollectionIcon = ({ collection }: { collection: Collection }) => {
return <DynamicCollectionIcon collection={collection} />;
};
const ColorCollectionIcon = ({ collection }: { collection: Collection }) => (
<DynamicCollectionIcon collection={collection} />
);
export const openCollection = createAction({
name: ({ t }) => t("Open collection"),
analyticsName: "Open collection",
section: CollectionSection,
shortcut: ["o", "c"],
icon: <CollectionIcon />,
@@ -42,6 +45,7 @@ export const openCollection = createAction({
export const createCollection = createAction({
name: ({ t }) => t("New collection"),
analyticsName: "New collection",
section: CollectionSection,
icon: <PlusIcon />,
keywords: "create",
@@ -60,6 +64,7 @@ export const createCollection = createAction({
export const editCollection = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? `${t("Edit")}` : t("Edit collection"),
analyticsName: "Edit collection",
section: CollectionSection,
icon: <EditIcon />,
visible: ({ stores, activeCollectionId }) =>
@@ -85,6 +90,7 @@ export const editCollection = createAction({
export const editCollectionPermissions = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? `${t("Permissions")}` : t("Collection permissions"),
analyticsName: "Collection permissions",
section: CollectionSection,
icon: <PadlockIcon />,
visible: ({ stores, activeCollectionId }) =>
@@ -104,6 +110,7 @@ export const editCollectionPermissions = createAction({
export const starCollection = createAction({
name: ({ t }) => t("Star"),
analyticsName: "Star collection",
section: CollectionSection,
icon: <StarredIcon />,
keywords: "favorite bookmark",
@@ -117,18 +124,19 @@ export const starCollection = createAction({
stores.policies.abilities(activeCollectionId).star
);
},
perform: ({ activeCollectionId, stores }) => {
perform: async ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return;
}
const collection = stores.collections.get(activeCollectionId);
collection?.star();
await collection?.star();
},
});
export const unstarCollection = createAction({
name: ({ t }) => t("Unstar"),
analyticsName: "Unstar collection",
section: CollectionSection,
icon: <UnstarredIcon />,
keywords: "unfavorite unbookmark",
@@ -142,13 +150,47 @@ export const unstarCollection = createAction({
stores.policies.abilities(activeCollectionId).unstar
);
},
perform: ({ activeCollectionId, stores }) => {
perform: async ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return;
}
const collection = stores.collections.get(activeCollectionId);
collection?.unstar();
await collection?.unstar();
},
});
export const deleteCollection = createAction({
name: ({ t }) => t("Delete"),
analyticsName: "Delete collection",
section: CollectionSection,
icon: <TrashIcon />,
visible: ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return false;
}
return stores.policies.abilities(activeCollectionId).delete;
},
perform: ({ activeCollectionId, stores, t }) => {
if (!activeCollectionId) {
return;
}
const collection = stores.collections.get(activeCollectionId);
if (!collection) {
return;
}
stores.dialogs.openModal({
isCentered: true,
title: t("Delete collection"),
content: (
<CollectionDeleteDialog
collection={collection}
onSubmit={stores.dialogs.closeAllModals}
/>
),
});
},
});
@@ -157,4 +199,5 @@ export const rootCollectionActions = [
createCollection,
starCollection,
unstarCollection,
deleteCollection,
];
+32 -9
View File
@@ -1,10 +1,11 @@
import { ToolsIcon, TrashIcon, UserIcon } from "outline-icons";
import * as React from "react";
import stores from "~/stores";
import { toast } from "sonner";
import { createAction } from "~/actions";
import { DeveloperSection } from "~/actions/sections";
import env from "~/env";
import { client } from "~/utils/ApiClient";
import Logger from "~/utils/Logger";
import { deleteAllDatabases } from "~/utils/developer";
export const clearIndexedDB = createAction({
@@ -14,7 +15,7 @@ export const clearIndexedDB = createAction({
section: DeveloperSection,
perform: async ({ t }) => {
await deleteAllDatabases();
stores.toasts.showToast(t("IndexedDB cache deleted"));
toast.message(t("IndexedDB cache deleted"));
},
});
@@ -28,23 +29,45 @@ export const createTestUsers = createAction({
try {
await client.post("/developer.create_test_users", { count });
stores.toasts.showToast(`${count} test users created`);
toast.message(`${count} test users created`);
} catch (err) {
stores.toasts.showToast(err.message, { type: "error" });
toast.error(err.message);
}
},
});
export const createToast = createAction({
name: "Create toast",
section: DeveloperSection,
visible: () => env.ENVIRONMENT === "development",
perform: async () => {
toast.message("Hello world", {
duration: 30000,
});
},
});
export const toggleDebugLogging = createAction({
name: ({ t }) => t("Toggle debug logging"),
icon: <ToolsIcon />,
section: DeveloperSection,
perform: async ({ t }) => {
Logger.debugLoggingEnabled = !Logger.debugLoggingEnabled;
toast.message(
Logger.debugLoggingEnabled
? t("Debug logging enabled")
: t("Debug logging disabled")
);
},
});
export const developer = createAction({
name: ({ t }) => t("Developer"),
name: ({ t }) => t("Development"),
keywords: "debug",
icon: <ToolsIcon />,
iconInContextMenu: false,
section: DeveloperSection,
visible: ({ event }) =>
env.ENVIRONMENT === "development" ||
(event instanceof KeyboardEvent && event.altKey),
children: [clearIndexedDB, createTestUsers],
children: [clearIndexedDB, toggleDebugLogging, createToast, createTestUsers],
});
export const rootDeveloperActions = [developer];
+338 -59
View File
@@ -18,20 +18,38 @@ import {
CrossIcon,
ArchiveIcon,
ShuffleIcon,
HistoryIcon,
LightBulbIcon,
UnpublishIcon,
PublishIcon,
CommentIcon,
} from "outline-icons";
import * as React from "react";
import { toast } from "sonner";
import { ExportContentType, TeamPreference } from "@shared/types";
import { getEventFiles } from "@shared/utils/files";
import DocumentDelete from "~/scenes/DocumentDelete";
import DocumentMove from "~/scenes/DocumentMove";
import DocumentPermanentDelete from "~/scenes/DocumentPermanentDelete";
import DocumentPublish from "~/scenes/DocumentPublish";
import DocumentTemplatizeDialog from "~/components/DocumentTemplatizeDialog";
import DuplicateDialog from "~/components/DuplicateDialog";
import { createAction } from "~/actions";
import { DocumentSection } from "~/actions/sections";
import env from "~/env";
import history from "~/utils/history";
import { homePath, newDocumentPath, searchPath } from "~/utils/routeHelpers";
import {
documentInsightsPath,
documentHistoryPath,
homePath,
newDocumentPath,
searchPath,
documentPath,
} from "~/utils/routeHelpers";
export const openDocument = createAction({
name: ({ t }) => t("Open document"),
analyticsName: "Open document",
section: DocumentSection,
shortcut: ["o", "d"],
keywords: "go to",
@@ -46,8 +64,11 @@ export const openDocument = createAction({
// cache if the document is renamed
id: path.url,
name: path.title,
icon: () =>
stores.documents.get(path.id)?.isStarred ? <StarredIcon /> : null,
icon: function _Icon() {
return stores.documents.get(path.id)?.isStarred ? (
<StarredIcon />
) : null;
},
section: DocumentSection,
perform: () => history.push(path.url),
}));
@@ -56,21 +77,63 @@ export const openDocument = createAction({
export const createDocument = createAction({
name: ({ t }) => t("New document"),
analyticsName: "New document",
section: DocumentSection,
icon: <NewDocumentIcon />,
keywords: "create",
visible: ({ activeCollectionId, stores }) =>
!!activeCollectionId &&
stores.policies.abilities(activeCollectionId).update,
visible: ({ currentTeamId, stores }) =>
!!currentTeamId && stores.policies.abilities(currentTeamId).createDocument,
perform: ({ activeCollectionId, inStarredSection }) =>
activeCollectionId &&
history.push(newDocumentPath(activeCollectionId), {
starred: inStarredSection,
}),
});
export const createDocumentFromTemplate = createAction({
name: ({ t }) => t("New from template"),
analyticsName: "New document",
section: DocumentSection,
icon: <NewDocumentIcon />,
keywords: "create",
visible: ({ currentTeamId, activeDocumentId, stores }) =>
!!currentTeamId &&
!!activeDocumentId &&
!!stores.documents.get(activeDocumentId)?.template &&
stores.policies.abilities(currentTeamId).createDocument,
perform: ({ activeCollectionId, activeDocumentId, inStarredSection }) =>
history.push(
newDocumentPath(activeCollectionId, { templateId: activeDocumentId }),
{
starred: inStarredSection,
}
),
});
export const createNestedDocument = createAction({
name: ({ t }) => t("New nested document"),
analyticsName: "New document",
section: DocumentSection,
icon: <NewDocumentIcon />,
keywords: "create",
visible: ({ currentTeamId, activeDocumentId, stores }) =>
!!currentTeamId &&
!!activeDocumentId &&
stores.policies.abilities(currentTeamId).createDocument &&
stores.policies.abilities(activeDocumentId).createChildDocument,
perform: ({ activeCollectionId, activeDocumentId, inStarredSection }) =>
history.push(
newDocumentPath(activeCollectionId, {
parentDocumentId: activeDocumentId,
}),
{
starred: inStarredSection,
}
),
});
export const starDocument = createAction({
name: ({ t }) => t("Star"),
analyticsName: "Star document",
section: DocumentSection,
icon: <StarredIcon />,
keywords: "favorite bookmark",
@@ -83,18 +146,19 @@ export const starDocument = createAction({
!document?.isStarred && stores.policies.abilities(activeDocumentId).star
);
},
perform: ({ activeDocumentId, stores }) => {
perform: async ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.star();
await document?.star();
},
});
export const unstarDocument = createAction({
name: ({ t }) => t("Unstar"),
analyticsName: "Unstar document",
section: DocumentSection,
icon: <UnstarredIcon />,
keywords: "unfavorite unbookmark",
@@ -108,18 +172,97 @@ export const unstarDocument = createAction({
stores.policies.abilities(activeDocumentId).unstar
);
},
perform: ({ activeDocumentId, stores }) => {
perform: async ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.unstar();
await document?.unstar();
},
});
export const publishDocument = createAction({
name: ({ t }) => t("Publish"),
analyticsName: "Publish document",
section: DocumentSection,
icon: <PublishIcon />,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!!document?.isDraft && stores.policies.abilities(activeDocumentId).update
);
},
perform: async ({ activeDocumentId, stores, t }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
if (document?.publishedAt) {
return;
}
if (document?.collectionId) {
await document.save(undefined, {
publish: true,
});
toast.success(
t("Published {{ documentName }}", {
documentName: document.noun,
})
);
} else if (document) {
stores.dialogs.openModal({
title: t("Publish document"),
isCentered: true,
content: <DocumentPublish document={document} />,
});
}
},
});
export const unpublishDocument = createAction({
name: ({ t }) => t("Unpublish"),
analyticsName: "Unpublish document",
section: DocumentSection,
icon: <UnpublishIcon />,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
return stores.policies.abilities(activeDocumentId).unpublish;
},
perform: async ({ activeDocumentId, stores, t }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
try {
await document.unpublish();
toast.success(
t("Unpublished {{ documentName }}", {
documentName: document.noun,
})
);
} catch (err) {
toast.error(err.message);
}
},
});
export const subscribeDocument = createAction({
name: ({ t }) => t("Subscribe"),
analyticsName: "Subscribe to document",
section: DocumentSection,
icon: <SubscribeIcon />,
visible: ({ activeDocumentId, stores }) => {
@@ -134,23 +277,22 @@ export const subscribeDocument = createAction({
stores.policies.abilities(activeDocumentId).subscribe
);
},
perform: ({ activeDocumentId, stores, t }) => {
perform: async ({ activeDocumentId, stores, t }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.subscribe();
await document?.subscribe();
stores.toasts.showToast(t("Subscribed to document notifications"), {
type: "success",
});
toast.success(t("Subscribed to document notifications"));
},
});
export const unsubscribeDocument = createAction({
name: ({ t }) => t("Unsubscribe"),
analyticsName: "Unsubscribe from document",
section: DocumentSection,
icon: <UnsubscribeIcon />,
visible: ({ activeDocumentId, stores }) => {
@@ -165,69 +307,99 @@ export const unsubscribeDocument = createAction({
stores.policies.abilities(activeDocumentId).unsubscribe
);
},
perform: ({ activeDocumentId, stores, currentUserId, t }) => {
perform: async ({ activeDocumentId, stores, currentUserId, t }) => {
if (!activeDocumentId || !currentUserId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.unsubscribe(currentUserId);
await document?.unsubscribe(currentUserId);
stores.toasts.showToast(t("Unsubscribed from document notifications"), {
type: "success",
});
toast.success(t("Unsubscribed from document notifications"));
},
});
export const downloadDocumentAsHTML = createAction({
name: ({ t }) => t("HTML"),
analyticsName: "Download document as HTML",
section: DocumentSection,
keywords: "html export",
icon: <DownloadIcon />,
iconInContextMenu: false,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).download,
perform: ({ activeDocumentId, stores }) => {
perform: async ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.download("text/html");
await document?.download(ExportContentType.Html);
},
});
export const downloadDocumentAsPDF = createAction({
name: ({ t }) => t("PDF"),
analyticsName: "Download document as PDF",
section: DocumentSection,
keywords: "export",
icon: <DownloadIcon />,
iconInContextMenu: false,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId &&
stores.policies.abilities(activeDocumentId).download &&
env.PDF_EXPORT_ENABLED,
perform: ({ activeDocumentId, t, stores }) => {
if (!activeDocumentId) {
return;
}
const id = toast.loading(`${t("Exporting")}`);
const document = stores.documents.get(activeDocumentId);
document
?.download(ExportContentType.Pdf)
.finally(() => id && toast.dismiss(id));
},
});
export const downloadDocumentAsMarkdown = createAction({
name: ({ t }) => t("Markdown"),
analyticsName: "Download document as Markdown",
section: DocumentSection,
keywords: "md markdown export",
icon: <DownloadIcon />,
iconInContextMenu: false,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).download,
perform: ({ activeDocumentId, stores }) => {
perform: async ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.download("text/markdown");
await document?.download(ExportContentType.Markdown);
},
});
export const downloadDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Download") : t("Download document"),
analyticsName: "Download document",
section: DocumentSection,
icon: <DownloadIcon />,
keywords: "export",
children: [downloadDocumentAsHTML, downloadDocumentAsMarkdown],
children: [
downloadDocumentAsHTML,
downloadDocumentAsPDF,
downloadDocumentAsMarkdown,
],
});
export const duplicateDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Duplicate") : t("Duplicate document"),
analyticsName: "Duplicate document",
section: DocumentSection,
icon: <DuplicateIcon />,
keywords: "copy",
@@ -240,11 +412,19 @@ export const duplicateDocument = createAction({
const document = stores.documents.get(activeDocumentId);
invariant(document, "Document must exist");
const duped = await document.duplicate();
// when duplicating, go straight to the duplicated document content
history.push(duped.url);
stores.toasts.showToast(t("Document duplicated"), {
type: "success",
stores.dialogs.openModal({
title: t("Copy document"),
isCentered: true,
content: (
<DuplicateDialog
document={document}
onSubmit={(response) => {
stores.dialogs.closeAllModals();
history.push(documentPath(response[0]));
}}
/>
),
});
},
});
@@ -254,7 +434,17 @@ export const duplicateDocument = createAction({
* of the collection for all collection members to see.
*/
export const pinDocumentToCollection = createAction({
name: ({ t }) => t("Pin to collection"),
name: ({ activeDocumentId = "", t, stores }) => {
const selectedDocument = stores.documents.get(activeDocumentId);
const collectionName = selectedDocument
? stores.documents.getCollectionForDocument(selectedDocument)?.name
: t("collection");
return t("Pin to {{collectionName}}", {
collectionName,
});
},
analyticsName: "Pin document to collection",
section: DocumentSection,
icon: <PinIcon />,
iconInContextMenu: false,
@@ -273,13 +463,17 @@ export const pinDocumentToCollection = createAction({
return;
}
const document = stores.documents.get(activeDocumentId);
await document?.pin(document.collectionId);
try {
const document = stores.documents.get(activeDocumentId);
await document?.pin(document.collectionId);
const collection = stores.collections.get(activeCollectionId);
const collection = stores.collections.get(activeCollectionId);
if (!collection || !location.pathname.startsWith(collection?.url)) {
stores.toasts.showToast(t("Pinned to collection"));
if (!collection || !location.pathname.startsWith(collection?.url)) {
toast.success(t("Pinned to collection"));
}
} catch (err) {
toast.error(err.message);
}
},
});
@@ -290,6 +484,7 @@ export const pinDocumentToCollection = createAction({
*/
export const pinDocumentToHome = createAction({
name: ({ t }) => t("Pin to home"),
analyticsName: "Pin document to home",
section: DocumentSection,
icon: <PinIcon />,
iconInContextMenu: false,
@@ -311,16 +506,21 @@ export const pinDocumentToHome = createAction({
}
const document = stores.documents.get(activeDocumentId);
await document?.pin();
try {
await document?.pin();
if (location.pathname !== homePath()) {
stores.toasts.showToast(t("Pinned to team home"));
if (location.pathname !== homePath()) {
toast.success(t("Pinned to home"));
}
} catch (err) {
toast.error(err.message);
}
},
});
export const pinDocument = createAction({
name: ({ t }) => t("Pin"),
analyticsName: "Pin document",
section: DocumentSection,
icon: <PinIcon />,
children: [pinDocumentToCollection, pinDocumentToHome],
@@ -329,16 +529,18 @@ export const pinDocument = createAction({
export const printDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Print") : t("Print document"),
analyticsName: "Print document",
section: DocumentSection,
icon: <PrintIcon />,
visible: ({ activeDocumentId }) => !!activeDocumentId,
visible: ({ activeDocumentId }) => !!(activeDocumentId && window.print),
perform: async () => {
window.print();
queueMicrotask(window.print);
},
});
export const importDocument = createAction({
name: ({ t }) => t("Import document"),
analyticsName: "Import document",
section: DocumentSection,
icon: <ImportIcon />,
keywords: "upload",
@@ -354,7 +556,7 @@ export const importDocument = createAction({
return false;
},
perform: ({ activeCollectionId, activeDocumentId, stores }) => {
const { documents, toasts } = stores;
const { documents } = stores;
const input = document.createElement("input");
input.type = "file";
input.accept = documents.importFileTypes.join(", ");
@@ -374,9 +576,7 @@ export const importDocument = createAction({
);
history.push(document.url);
} catch (err) {
toasts.showToast(err.message, {
type: "error",
});
toast.error(err.message);
throw err;
}
};
@@ -387,6 +587,7 @@ export const importDocument = createAction({
export const createTemplate = createAction({
name: ({ t }) => t("Templatize"),
analyticsName: "Templatize document",
section: DocumentSection,
icon: <ShapesIcon />,
keywords: "new create template",
@@ -419,8 +620,9 @@ export const createTemplate = createAction({
export const openRandomDocument = createAction({
id: "random",
section: DocumentSection,
name: ({ t }) => t(`Open random document`),
analyticsName: "Open random document",
section: DocumentSection,
icon: <ShuffleIcon />,
perform: ({ stores, activeDocumentId }) => {
const documentPaths = stores.collections.pathsToDocuments.filter(
@@ -438,9 +640,10 @@ export const openRandomDocument = createAction({
export const searchDocumentsForQuery = (searchQuery: string) =>
createAction({
id: "search",
section: DocumentSection,
name: ({ t }) =>
t(`Search documents for "{{searchQuery}}"`, { searchQuery }),
analyticsName: "Search documents",
section: DocumentSection,
icon: <SearchIcon />,
perform: () => history.push(searchPath(searchQuery)),
visible: ({ location }) => location.pathname !== searchPath(),
@@ -448,6 +651,7 @@ export const searchDocumentsForQuery = (searchQuery: string) =>
export const moveDocument = createAction({
name: ({ t }) => t("Move"),
analyticsName: "Move document",
section: DocumentSection,
icon: <MoveIcon />,
visible: ({ activeDocumentId, stores }) => {
@@ -464,15 +668,11 @@ export const moveDocument = createAction({
}
stores.dialogs.openModal({
title: t("Move {{ documentName }}", {
documentName: document.noun,
title: t("Move {{ documentType }}", {
documentType: document.noun,
}),
content: (
<DocumentMove
document={document}
onRequestClose={stores.dialogs.closeAllModals}
/>
),
isCentered: true,
content: <DocumentMove document={document} />,
});
}
},
@@ -480,6 +680,7 @@ export const moveDocument = createAction({
export const archiveDocument = createAction({
name: ({ t }) => t("Archive"),
analyticsName: "Archive document",
section: DocumentSection,
icon: <ArchiveIcon />,
visible: ({ activeDocumentId, stores }) => {
@@ -496,15 +697,14 @@ export const archiveDocument = createAction({
}
await document.archive();
stores.toasts.showToast(t("Document archived"), {
type: "success",
});
toast.success(t("Document archived"));
}
},
});
export const deleteDocument = createAction({
name: ({ t }) => t("Delete"),
analyticsName: "Delete document",
section: DocumentSection,
icon: <TrashIcon />,
dangerous: true,
@@ -539,6 +739,7 @@ export const deleteDocument = createAction({
export const permanentlyDeleteDocument = createAction({
name: ({ t }) => t("Permanently delete"),
analyticsName: "Permanently delete document",
section: DocumentSection,
icon: <CrossIcon />,
dangerous: true,
@@ -571,6 +772,79 @@ export const permanentlyDeleteDocument = createAction({
},
});
export const openDocumentComments = createAction({
name: ({ t }) => t("Comments"),
analyticsName: "Open comments",
section: DocumentSection,
icon: <CommentIcon />,
visible: ({ activeDocumentId, stores }) => {
const can = stores.policies.abilities(activeDocumentId ?? "");
return (
!!activeDocumentId &&
can.comment &&
!!stores.auth.team?.getPreference(TeamPreference.Commenting)
);
},
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
stores.ui.toggleComments(activeDocumentId);
},
});
export const openDocumentHistory = createAction({
name: ({ t }) => t("History"),
analyticsName: "Open document history",
section: DocumentSection,
icon: <HistoryIcon />,
visible: ({ activeDocumentId, stores }) => {
const can = stores.policies.abilities(activeDocumentId ?? "");
return !!activeDocumentId && can.read && !can.restore;
},
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
history.push(documentHistoryPath(document));
},
});
export const openDocumentInsights = createAction({
name: ({ t }) => t("Insights"),
analyticsName: "Open document insights",
section: DocumentSection,
icon: <LightBulbIcon />,
visible: ({ activeDocumentId, stores }) => {
const can = stores.policies.abilities(activeDocumentId ?? "");
const document = activeDocumentId
? stores.documents.get(activeDocumentId)
: undefined;
return (
!!activeDocumentId &&
can.read &&
!document?.isTemplate &&
!document?.isDeleted
);
},
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
history.push(documentInsightsPath(document));
},
});
export const rootDocumentActions = [
openDocument,
archiveDocument,
@@ -581,6 +855,8 @@ export const rootDocumentActions = [
downloadDocument,
starDocument,
unstarDocument,
publishDocument,
unpublishDocument,
subscribeDocument,
unsubscribeDocument,
duplicateDocument,
@@ -590,4 +866,7 @@ export const rootDocumentActions = [
printDocument,
pinDocumentToCollection,
pinDocumentToHome,
openDocumentComments,
openDocumentHistory,
openDocumentInsights,
];
+66 -17
View File
@@ -6,13 +6,15 @@ import {
EditIcon,
OpenIcon,
SettingsIcon,
ShapesIcon,
KeyboardIcon,
EmailIcon,
LogoutIcon,
ProfileIcon,
BrowserIcon,
ShapesIcon,
} from "outline-icons";
import * as React from "react";
import { isMac } from "@shared/utils/browser";
import {
developersUrl,
changelogUrl,
@@ -24,21 +26,21 @@ import SearchQuery from "~/models/SearchQuery";
import KeyboardShortcuts from "~/scenes/KeyboardShortcuts";
import { createAction } from "~/actions";
import { NavigationSection, RecentSearchesSection } from "~/actions/sections";
import Desktop from "~/utils/Desktop";
import history from "~/utils/history";
import isCloudHosted from "~/utils/isCloudHosted";
import {
organizationSettingsPath,
profileSettingsPath,
accountPreferencesPath,
homePath,
searchPath,
draftsPath,
templatesPath,
archivePath,
trashPath,
settingsPath,
} from "~/utils/routeHelpers";
export const navigateToHome = createAction({
name: ({ t }) => t("Home"),
analyticsName: "Navigate to home",
section: NavigationSection,
shortcut: ["d"],
icon: <HomeIcon />,
@@ -50,28 +52,23 @@ export const navigateToRecentSearchQuery = (searchQuery: SearchQuery) =>
createAction({
section: RecentSearchesSection,
name: searchQuery.query,
analyticsName: "Navigate to recent search query",
icon: <SearchIcon />,
perform: () => history.push(searchPath(searchQuery.query)),
});
export const navigateToDrafts = createAction({
name: ({ t }) => t("Drafts"),
analyticsName: "Navigate to drafts",
section: NavigationSection,
icon: <EditIcon />,
perform: () => history.push(draftsPath()),
visible: ({ location }) => location.pathname !== draftsPath(),
});
export const navigateToTemplates = createAction({
name: ({ t }) => t("Templates"),
section: NavigationSection,
icon: <ShapesIcon />,
perform: () => history.push(templatesPath()),
visible: ({ location }) => location.pathname !== templatesPath(),
});
export const navigateToArchive = createAction({
name: ({ t }) => t("Archive"),
analyticsName: "Navigate to archive",
section: NavigationSection,
shortcut: ["g", "a"],
icon: <ArchiveIcon />,
@@ -81,6 +78,7 @@ export const navigateToArchive = createAction({
export const navigateToTrash = createAction({
name: ({ t }) => t("Trash"),
analyticsName: "Navigate to trash",
section: NavigationSection,
icon: <TrashIcon />,
perform: () => history.push(trashPath()),
@@ -89,40 +87,71 @@ export const navigateToTrash = createAction({
export const navigateToSettings = createAction({
name: ({ t }) => t("Settings"),
analyticsName: "Navigate to settings",
section: NavigationSection,
shortcut: ["g", "s"],
icon: <SettingsIcon />,
visible: ({ stores }) =>
stores.policies.abilities(stores.auth.team?.id || "").update,
perform: () => history.push(organizationSettingsPath()),
perform: () => history.push(settingsPath()),
});
export const navigateToProfileSettings = createAction({
name: ({ t }) => t("Profile"),
analyticsName: "Navigate to profile settings",
section: NavigationSection,
iconInContextMenu: false,
icon: <ProfileIcon />,
perform: () => history.push(profileSettingsPath()),
perform: () => history.push(settingsPath()),
});
export const navigateToTemplateSettings = createAction({
name: ({ t }) => t("Templates"),
analyticsName: "Navigate to template settings",
section: NavigationSection,
iconInContextMenu: false,
icon: <ShapesIcon />,
perform: () => history.push(settingsPath("templates")),
});
export const navigateToNotificationSettings = createAction({
name: ({ t }) => t("Notifications"),
analyticsName: "Navigate to notification settings",
section: NavigationSection,
iconInContextMenu: false,
icon: <EmailIcon />,
perform: () => history.push(settingsPath("notifications")),
});
export const navigateToAccountPreferences = createAction({
name: ({ t }) => t("Preferences"),
analyticsName: "Navigate to account preferences",
section: NavigationSection,
iconInContextMenu: false,
icon: <SettingsIcon />,
perform: () => history.push(accountPreferencesPath()),
perform: () => history.push(settingsPath("preferences")),
});
export const openAPIDocumentation = createAction({
name: ({ t }) => t("API documentation"),
analyticsName: "Open API documentation",
section: NavigationSection,
iconInContextMenu: false,
icon: <OpenIcon />,
perform: () => window.open(developersUrl()),
});
export const toggleSidebar = createAction({
name: ({ t }) => t("Toggle sidebar"),
analyticsName: "Toggle sidebar",
keywords: "hide show navigation",
section: NavigationSection,
perform: ({ stores }) => stores.ui.toggleCollapsedSidebar(),
});
export const openFeedbackUrl = createAction({
name: ({ t }) => t("Send us feedback"),
analyticsName: "Open feedback",
section: NavigationSection,
iconInContextMenu: false,
icon: <EmailIcon />,
@@ -131,12 +160,14 @@ export const openFeedbackUrl = createAction({
export const openBugReportUrl = createAction({
name: ({ t }) => t("Report a bug"),
analyticsName: "Open bug report",
section: NavigationSection,
perform: () => window.open(githubIssuesUrl()),
});
export const openChangelog = createAction({
name: ({ t }) => t("Changelog"),
analyticsName: "Open changelog",
section: NavigationSection,
iconInContextMenu: false,
icon: <OpenIcon />,
@@ -145,6 +176,7 @@ export const openChangelog = createAction({
export const openKeyboardShortcuts = createAction({
name: ({ t }) => t("Keyboard shortcuts"),
analyticsName: "Open keyboard shortcuts",
section: NavigationSection,
shortcut: ["?"],
iconInContextMenu: false,
@@ -157,8 +189,24 @@ export const openKeyboardShortcuts = createAction({
},
});
export const downloadApp = createAction({
name: ({ t }) =>
t("Download {{ platform }} app", {
platform: isMac() ? "macOS" : "Windows",
}),
analyticsName: "Download app",
section: NavigationSection,
iconInContextMenu: false,
icon: <BrowserIcon />,
visible: () => !Desktop.isElectron() && isMac() && isCloudHosted,
perform: () => {
window.open("https://desktop.getoutline.com");
},
});
export const logout = createAction({
name: ({ t }) => t("Log out"),
analyticsName: "Log out",
section: NavigationSection,
icon: <LogoutIcon />,
perform: () => stores.auth.logout(),
@@ -167,13 +215,14 @@ export const logout = createAction({
export const rootNavigationActions = [
navigateToHome,
navigateToDrafts,
navigateToTemplates,
navigateToArchive,
navigateToTrash,
downloadApp,
openAPIDocumentation,
openFeedbackUrl,
openBugReportUrl,
openChangelog,
openKeyboardShortcuts,
toggleSidebar,
logout,
];
+16
View File
@@ -0,0 +1,16 @@
import { MarkAsReadIcon } from "outline-icons";
import * as React from "react";
import { createAction } from "..";
import { NotificationSection } from "../sections";
export const markNotificationsAsRead = createAction({
name: ({ t }) => t("Mark notifications as read"),
analyticsName: "Mark notifications as read",
section: NotificationSection,
icon: <MarkAsReadIcon />,
shortcut: ["Shift+Escape"],
perform: ({ stores }) => stores.notifications.markAllAsRead(),
visible: ({ stores }) => stores.notifications.approximateUnreadCount > 0,
});
export const rootNotificationActions = [markNotificationsAsRead];
+14 -21
View File
@@ -2,19 +2,24 @@ import copy from "copy-to-clipboard";
import { LinkIcon, RestoreIcon } from "outline-icons";
import * as React from "react";
import { matchPath } from "react-router-dom";
import { toast } from "sonner";
import stores from "~/stores";
import { createAction } from "~/actions";
import { RevisionSection } from "~/actions/sections";
import history from "~/utils/history";
import { documentHistoryUrl, matchDocumentHistory } from "~/utils/routeHelpers";
import {
documentHistoryPath,
matchDocumentHistory,
} from "~/utils/routeHelpers";
export const restoreRevision = createAction({
name: ({ t }) => t("Restore revision"),
analyticsName: "Restore revision",
icon: <RestoreIcon />,
section: RevisionSection,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).update,
perform: async ({ t, event, location, activeDocumentId }) => {
perform: async ({ event, location, activeDocumentId }) => {
event?.preventDefault();
if (!activeDocumentId) {
return;
@@ -25,31 +30,21 @@ export const restoreRevision = createAction({
});
const revisionId = match?.params.revisionId;
const { team } = stores.auth;
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
if (team?.collaborativeEditing) {
history.push(document.url, {
restore: true,
revisionId,
});
} else {
await document.restore({
revisionId,
});
stores.toasts.showToast(t("Document restored"), {
type: "success",
});
history.push(document.url);
}
history.push(document.url, {
restore: true,
revisionId,
});
},
});
export const copyLinkToRevision = createAction({
name: ({ t }) => t("Copy link"),
analyticsName: "Copy link to revision",
icon: <LinkIcon />,
section: RevisionSection,
perform: async ({ activeDocumentId, stores, t }) => {
@@ -66,7 +61,7 @@ export const copyLinkToRevision = createAction({
return;
}
const url = `${window.location.origin}${documentHistoryUrl(
const url = `${window.location.origin}${documentHistoryPath(
document,
revisionId
)}`;
@@ -74,9 +69,7 @@ export const copyLinkToRevision = createAction({
copy(url, {
format: "text/plain",
onCopy: () => {
stores.toasts.showToast(t("Link copied"), {
type: "info",
});
toast.message(t("Link copied"));
},
});
},
+7 -2
View File
@@ -7,6 +7,7 @@ import { SettingsSection } from "~/actions/sections";
export const changeToDarkTheme = createAction({
name: ({ t }) => t("Dark"),
analyticsName: "Change to dark theme",
icon: <MoonIcon />,
iconInContextMenu: false,
keywords: "theme dark night",
@@ -17,6 +18,7 @@ export const changeToDarkTheme = createAction({
export const changeToLightTheme = createAction({
name: ({ t }) => t("Light"),
analyticsName: "Change to light theme",
icon: <SunIcon />,
iconInContextMenu: false,
keywords: "theme light day",
@@ -27,6 +29,7 @@ export const changeToLightTheme = createAction({
export const changeToSystemTheme = createAction({
name: ({ t }) => t("System"),
analyticsName: "Change to system theme",
icon: <BrowserIcon />,
iconInContextMenu: false,
keywords: "theme system default",
@@ -38,9 +41,11 @@ export const changeToSystemTheme = createAction({
export const changeTheme = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Appearance") : t("Change theme"),
analyticsName: "Change theme",
placeholder: ({ t }) => t("Change theme to"),
icon: () =>
stores.ui.resolvedTheme === "light" ? <SunIcon /> : <MoonIcon />,
icon: function _Icon() {
return stores.ui.resolvedTheme === "light" ? <SunIcon /> : <MoonIcon />;
},
keywords: "appearance display",
section: SettingsSection,
children: [changeToLightTheme, changeToDarkTheme, changeToSystemTheme],
+34 -25
View File
@@ -1,40 +1,58 @@
import { PlusIcon } from "outline-icons";
import * as React from "react";
import styled from "styled-components";
import { stringToColor } from "@shared/utils/color";
import RootStore from "~/stores/RootStore";
import TeamNew from "~/scenes/TeamNew";
import TeamLogo from "~/components/TeamLogo";
import { createAction } from "~/actions";
import { loadSessionsFromCookie } from "~/hooks/useSessions";
import { ActionContext } from "~/types";
import { TeamSection } from "../sections";
export const switchTeamList = getSessions().map((session) => {
return createAction({
export const createTeamsList = ({ stores }: { stores: RootStore }) =>
stores.auth.availableTeams?.map((session) => ({
id: `switch-${session.id}`,
name: session.name,
analyticsName: "Switch workspace",
section: TeamSection,
keywords: "change switch workspace organization team",
icon: () => <Logo alt={session.name} src={session.logoUrl} />,
visible: ({ currentTeamId }) => currentTeamId !== session.teamId,
icon: function _Icon() {
return (
<StyledTeamLogo
alt={session.name}
model={{
initial: session.name[0],
avatarUrl: session.avatarUrl,
id: session.id,
color: stringToColor(session.id),
}}
size={24}
/>
);
},
visible: ({ currentTeamId }: ActionContext) => currentTeamId !== session.id,
perform: () => (window.location.href = session.url),
});
});
})) ?? [];
const switchTeam = createAction({
export const switchTeam = createAction({
name: ({ t }) => t("Switch workspace"),
placeholder: ({ t }) => t("Select a workspace"),
analyticsName: "Switch workspace",
keywords: "change switch workspace organization team",
section: TeamSection,
visible: ({ currentTeamId }) =>
getSessions({ exclude: currentTeamId }).length > 0,
children: switchTeamList,
visible: ({ stores }) =>
!!stores.auth.availableTeams && stores.auth.availableTeams?.length > 1,
children: createTeamsList,
});
export const createTeam = createAction({
name: ({ t }) => `${t("New workspace")}`,
analyticsName: "New workspace",
keywords: "create change switch workspace organization team",
section: TeamSection,
icon: <PlusIcon />,
visible: ({ stores, currentTeamId }) => {
return stores.policies.abilities(currentTeamId ?? "").createTeam;
},
visible: ({ stores, currentTeamId }) =>
stores.policies.abilities(currentTeamId ?? "").createTeam,
perform: ({ t, event, stores }) => {
event?.preventDefault();
event?.stopPropagation();
@@ -47,18 +65,9 @@ export const createTeam = createAction({
},
});
function getSessions(params?: { exclude?: string }) {
const sessions = loadSessionsFromCookie();
const otherSessions = sessions.filter(
(session) => session.teamId !== params?.exclude
);
return otherSessions;
}
const Logo = styled("img")`
const StyledTeamLogo = styled(TeamLogo)`
border-radius: 2px;
width: 24px;
height: 24px;
border: 0;
`;
export const rootTeamActions = [switchTeam, createTeam];
+29
View File
@@ -2,11 +2,13 @@ import { PlusIcon } from "outline-icons";
import * as React from "react";
import stores from "~/stores";
import Invite from "~/scenes/Invite";
import { UserDeleteDialog } from "~/components/UserDialogs";
import { createAction } from "~/actions";
import { UserSection } from "~/actions/sections";
export const inviteUser = createAction({
name: ({ t }) => `${t("Invite people")}`,
analyticsName: "Invite people",
icon: <PlusIcon />,
keywords: "team member workspace user",
section: UserSection,
@@ -20,4 +22,31 @@ export const inviteUser = createAction({
},
});
export const deleteUserActionFactory = (userId: string) =>
createAction({
name: ({ t }) => `${t("Delete user")}`,
analyticsName: "Delete user",
keywords: "leave",
dangerous: true,
section: UserSection,
visible: ({ stores }) => stores.policies.abilities(userId).delete,
perform: ({ t }) => {
const user = stores.users.get(userId);
if (!user) {
return;
}
stores.dialogs.openModal({
title: t("Delete user"),
isCentered: true,
content: (
<UserDeleteDialog
user={user}
onSubmit={stores.dialogs.closeAllModals}
/>
),
});
},
});
export const rootUserActions = [inviteUser];
+33 -9
View File
@@ -1,5 +1,6 @@
import { flattenDeep } from "lodash";
import flattenDeep from "lodash/flattenDeep";
import * as React from "react";
import { toast } from "sonner";
import { Optional } from "utility-types";
import { v4 as uuidv4 } from "uuid";
import {
@@ -9,6 +10,7 @@ import {
MenuItemButton,
MenuItemWithChildren,
} from "~/types";
import Analytics from "~/utils/Analytics";
function resolve<T>(value: any, context: ActionContext): T {
return typeof value === "function" ? value(context) : value;
@@ -17,7 +19,24 @@ function resolve<T>(value: any, context: ActionContext): T {
export function createAction(definition: Optional<Action, "id">): Action {
return {
...definition,
id: uuidv4(),
perform: definition.perform
? (context) => {
// We muse use the specific analytics name here as the action name is
// translated and potentially contains user strings.
if (definition.analyticsName) {
Analytics.track("perform_action", definition.analyticsName, {
context: context.isButton
? "button"
: context.isCommandBar
? "commandbar"
: "contextmenu",
});
}
return definition.perform?.(context);
}
: undefined,
id: definition.id ?? uuidv4(),
};
}
@@ -31,9 +50,7 @@ export function actionToMenuItem(
const title = resolve<string>(action.name, context);
const icon =
resolvedIcon && action.iconInContextMenu !== false
? React.cloneElement(resolvedIcon, {
color: "currentColor",
})
? resolvedIcon
: undefined;
if (resolvedChildren) {
@@ -57,8 +74,14 @@ export function actionToMenuItem(
icon,
visible,
dangerous: action.dangerous,
onClick: () => action.perform && action.perform(context),
selected: action.selected ? action.selected(context) : undefined,
onClick: () => {
try {
action.perform?.(context);
} catch (err) {
toast.error(err.message);
}
},
selected: action.selected?.(context),
};
}
@@ -70,7 +93,7 @@ export function actionToKBar(
return [];
}
const resolvedIcon = resolve<React.ReactElement<any>>(action.icon, context);
const resolvedIcon = resolve<React.ReactElement>(action.icon, context);
const resolvedChildren = resolve<Action[]>(action.children, context);
const resolvedSection = resolve<string>(action.section, context);
const resolvedName = resolve<string>(action.name, context);
@@ -85,12 +108,13 @@ export function actionToKBar(
{
id: action.id,
name: resolvedName,
analyticsName: action.analyticsName,
section: resolvedSection,
placeholder: resolvedPlaceholder,
keywords: action.keywords ?? "",
shortcut: action.shortcut || [],
icon: resolvedIcon,
perform: action.perform ? () => action?.perform?.(context) : undefined,
perform: action.perform ? () => action.perform?.(context) : undefined,
},
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
].concat(children.map((child) => ({ ...child, parent: action.id })));
+2
View File
@@ -2,6 +2,7 @@ import { rootCollectionActions } from "./definitions/collections";
import { rootDeveloperActions } from "./definitions/developer";
import { rootDocumentActions } from "./definitions/documents";
import { rootNavigationActions } from "./definitions/navigation";
import { rootNotificationActions } from "./definitions/notifications";
import { rootRevisionActions } from "./definitions/revisions";
import { rootSettingsActions } from "./definitions/settings";
import { rootTeamActions } from "./definitions/teams";
@@ -12,6 +13,7 @@ export default [
...rootDocumentActions,
...rootUserActions,
...rootNavigationActions,
...rootNotificationActions,
...rootRevisionActions,
...rootSettingsActions,
...rootDeveloperActions,
+2
View File
@@ -12,6 +12,8 @@ export const SettingsSection = ({ t }: ActionContext) => t("Settings");
export const NavigationSection = ({ t }: ActionContext) => t("Navigation");
export const NotificationSection = ({ t }: ActionContext) => t("Notification");
export const UserSection = ({ t }: ActionContext) => t("People");
export const TeamSection = ({ t }: ActionContext) => t("Workspace");
+26 -15
View File
@@ -1,3 +1,4 @@
/* eslint-disable react/prop-types */
import * as React from "react";
import Tooltip, { Props as TooltipProps } from "~/components/Tooltip";
import { Action, ActionContext } from "~/types";
@@ -18,42 +19,52 @@ export type Props = React.HTMLAttributes<HTMLButtonElement> & {
/**
* Button that can be used to trigger an action definition.
*/
const ActionButton = React.forwardRef(
(
{
action,
context,
tooltip,
hideOnActionDisabled,
...rest
}: Props & React.HTMLAttributes<HTMLButtonElement>,
const ActionButton = React.forwardRef<HTMLButtonElement, Props>(
function _ActionButton(
{ action, context, tooltip, hideOnActionDisabled, ...rest }: Props,
ref: React.Ref<HTMLButtonElement>
) => {
) {
const [executing, setExecuting] = React.useState(false);
const disabled = rest.disabled;
if (action && !context) {
throw new Error("Context must be provided with action");
}
if (!context || !action) {
return <button {...rest} ref={ref} />;
}
if (action?.visible && !action.visible(context) && hideOnActionDisabled) {
const actionContext = { ...context, isButton: true };
if (
action?.visible &&
!action.visible(actionContext) &&
hideOnActionDisabled
) {
return null;
}
const label =
typeof action.name === "function" ? action.name(context) : action.name;
typeof action.name === "function"
? action.name(actionContext)
: action.name;
const button = (
<button
{...rest}
aria-label={label}
disabled={disabled}
disabled={disabled || executing}
ref={ref}
onClick={
action?.perform && context
action?.perform && actionContext
? (ev) => {
ev.preventDefault();
ev.stopPropagation();
action.perform?.(context);
const response = action.perform?.(actionContext);
if (response?.finally) {
setExecuting(true);
response.finally(() => setExecuting(false));
}
}
: rest.onClick
}
+4 -3
View File
@@ -1,5 +1,6 @@
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { s } from "@shared/styles";
import Flex from "~/components/Flex";
export const Action = styled(Flex)`
@@ -20,7 +21,7 @@ export const Separator = styled.div`
margin-left: 12px;
width: 1px;
height: 28px;
background: ${(props) => props.theme.divider};
background: ${s("divider")};
`;
const Actions = styled(Flex)`
@@ -29,8 +30,8 @@ const Actions = styled(Flex)`
right: 0;
left: 0;
border-radius: 3px;
background: ${(props) => props.theme.background};
transition: ${(props) => props.theme.backgroundTransition};
background: ${s("background")};
transition: ${s("backgroundTransition")};
padding: 12px;
backdrop-filter: blur(20px);
+47 -7
View File
@@ -1,10 +1,18 @@
/* eslint-disable prefer-rest-params */
/* global ga */
import escape from "lodash/escape";
import * as React from "react";
import { IntegrationService } from "@shared/types";
import env from "~/env";
const Analytics: React.FC = ({ children }) => {
type Props = {
children?: React.ReactNode;
};
const Analytics: React.FC = ({ children }: Props) => {
// Google Analytics 3
React.useEffect(() => {
if (!env.GOOGLE_ANALYTICS_ID) {
if (!env.GOOGLE_ANALYTICS_ID?.startsWith("UA-")) {
return;
}
@@ -17,11 +25,9 @@ const Analytics: React.FC = ({ children }) => {
ga.l = +new Date();
ga("create", env.GOOGLE_ANALYTICS_ID, "auto");
ga("set", {
dimension1: "true",
});
ga("send", "pageview");
const script = document.createElement("script");
script.type = "text/javascript";
script.src = "https://www.google-analytics.com/analytics.js";
script.async = true;
@@ -30,9 +36,43 @@ const Analytics: React.FC = ({ children }) => {
ga("send", "event", "pwa", "install");
});
if (document.body) {
document.body.appendChild(script);
document.getElementsByTagName("head")[0]?.appendChild(script);
}, []);
// Google Analytics 4
React.useEffect(() => {
const measurementIds = [];
if (env.analytics.service === IntegrationService.GoogleAnalytics) {
measurementIds.push(escape(env.analytics.settings?.measurementId));
}
if (env.GOOGLE_ANALYTICS_ID?.startsWith("G-")) {
measurementIds.push(env.GOOGLE_ANALYTICS_ID);
}
if (measurementIds.length === 0) {
return;
}
const params = {
allow_google_signals: false,
restricted_data_processing: true,
};
window.dataLayer = window.dataLayer || [];
window.gtag = function () {
window.dataLayer.push(arguments);
};
window.gtag("js", new Date());
for (const measurementId of measurementIds) {
window.gtag("config", measurementId, params);
}
const script = document.createElement("script");
script.type = "text/javascript";
script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementIds[0]}`;
script.async = true;
document.getElementsByTagName("head")[0]?.appendChild(script);
}, []);
return <>{children}</>;
+3 -9
View File
@@ -6,17 +6,11 @@ export default function Arrow() {
width="13"
height="30"
viewBox="0 0 13 30"
fill="none"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill="currentColor"
d="M7.40242 1.48635C8.23085 0.0650039 10.0656 -0.421985 11.5005 0.39863C12.9354 1.21924 13.427 3.03671 12.5986 4.45806L5.59858 16.4681C4.77015 17.8894 2.93538 18.3764 1.5005 17.5558C0.065623 16.7352 -0.426002 14.9177 0.402425 13.4964L7.40242 1.48635Z"
/>
<path
fill="currentColor"
d="M12.5986 25.5419C13.427 26.9633 12.9354 28.7808 11.5005 29.6014C10.0656 30.422 8.23087 29.935 7.40244 28.5136L0.402438 16.5036C-0.425989 15.0823 0.0656365 13.2648 1.50051 12.4442C2.93539 11.6236 4.77016 12.1106 5.59859 13.5319L12.5986 25.5419Z"
/>
<path d="M7.40242 1.48635C8.23085 0.0650039 10.0656 -0.421985 11.5005 0.39863C12.9354 1.21924 13.427 3.03671 12.5986 4.45806L5.59858 16.4681C4.77015 17.8894 2.93538 18.3764 1.5005 17.5558C0.065623 16.7352 -0.426002 14.9177 0.402425 13.4964L7.40242 1.48635Z" />
<path d="M12.5986 25.5419C13.427 26.9633 12.9354 28.7808 11.5005 29.6014C10.0656 30.422 8.23087 29.935 7.40244 28.5136L0.402438 16.5036C-0.425989 15.0823 0.0656365 13.2648 1.50051 12.4442C2.93539 11.6236 4.77016 12.1106 5.59859 13.5319L12.5986 25.5419Z" />
</svg>
);
}
+4
View File
@@ -20,6 +20,10 @@ function ArrowKeyNavigation(
const handleKeyDown = React.useCallback(
(ev) => {
if (onEscape) {
if (ev.nativeEvent.isComposing) {
return;
}
if (ev.key === "Escape") {
onEscape(ev);
}
-26
View File
@@ -1,26 +0,0 @@
import * as React from "react";
type Props = {
size?: number;
fill?: string;
className?: string;
};
function GoogleLogo({ size = 34, fill = "#FFF", className }: Props) {
return (
<svg
fill={fill}
width={size}
height={size}
viewBox="0 0 34 34"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<g>
<path d="M32.6162791,13.9090909 L16.8837209,13.9090909 L16.8837209,20.4772727 L25.9395349,20.4772727 C25.0953488,24.65 21.5651163,27.0454545 16.8837209,27.0454545 C11.3581395,27.0454545 6.90697674,22.5636364 6.90697674,17 C6.90697674,11.4363636 11.3581395,6.95454545 16.8837209,6.95454545 C19.2627907,6.95454545 21.4116279,7.80454545 23.1,9.19545455 L28.0116279,4.25 C25.0186047,1.62272727 21.1813953,0 16.8837209,0 C7.52093023,0 0,7.57272727 0,17 C0,26.4272727 7.52093023,34 16.8837209,34 C25.3255814,34 33,27.8181818 33,17 C33,15.9954545 32.8465116,14.9136364 32.6162791,13.9090909 Z" />
</g>
</svg>
);
}
export default GoogleLogo;
-43
View File
@@ -1,43 +0,0 @@
import * as React from "react";
type Props = {
size?: number;
fill?: string;
className?: string;
};
function MicrosoftLogo({ size = 34, fill = "#FFF", className }: Props) {
return (
<svg
fill={fill}
width={size}
height={size}
viewBox="0 0 34 34"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M18.0002 1H33.9998C33.9998 5.8172 34.0007 10.6344 33.9988 15.4516C28.6666 15.4508 23.3334 15.4516 18.0012 15.4516C17.9993 10.6344 18.0002 5.8172 18.0002 1Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M18.0009 17.5173C23.3333 17.5155 28.6667 17.5164 34 17.5164V33H18C18.0009 27.8388 17.9991 22.6776 18.0009 17.5173V17.5173Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0 1H16L15.9988 15.4516H0V1Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0 17.5161C5.3332 17.5179 10.6664 17.5155 15.9996 17.5179C16.0005 22.6789 15.9996 27.839 15.9996 33H0V17.5161Z"
/>
</svg>
);
}
export default MicrosoftLogo;
-41
View File
@@ -1,41 +0,0 @@
import * as React from "react";
type Props = {
size?: number;
fill?: string;
className?: string;
};
function SlackLogo({ size = 34, fill = "#FFF", className }: Props) {
return (
<svg
fill={fill}
width={size}
height={size}
viewBox="0 0 34 34"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<g stroke="none" strokeWidth="1" fillRule="evenodd">
<g transform="translate(0.000000, 17.822581)">
<path d="M7.23870968,3.61935484 C7.23870968,5.56612903 5.6483871,7.15645161 3.7016129,7.15645161 C1.75483871,7.15645161 0.164516129,5.56612903 0.164516129,3.61935484 C0.164516129,1.67258065 1.75483871,0.0822580645 3.7016129,0.0822580645 L7.23870968,0.0822580645 L7.23870968,3.61935484 Z" />
<path d="M9.02096774,3.61935484 C9.02096774,1.67258065 10.6112903,0.0822580645 12.5580645,0.0822580645 C14.5048387,0.0822580645 16.0951613,1.67258065 16.0951613,3.61935484 L16.0951613,12.4758065 C16.0951613,14.4225806 14.5048387,16.0129032 12.5580645,16.0129032 C10.6112903,16.0129032 9.02096774,14.4225806 9.02096774,12.4758065 C9.02096774,12.4758065 9.02096774,3.61935484 9.02096774,3.61935484 Z" />
</g>
<g>
<path d="M12.5580645,7.23870968 C10.6112903,7.23870968 9.02096774,5.6483871 9.02096774,3.7016129 C9.02096774,1.75483871 10.6112903,0.164516129 12.5580645,0.164516129 C14.5048387,0.164516129 16.0951613,1.75483871 16.0951613,3.7016129 L16.0951613,7.23870968 L12.5580645,7.23870968 Z" />
<path d="M12.5580645,9.02096774 C14.5048387,9.02096774 16.0951613,10.6112903 16.0951613,12.5580645 C16.0951613,14.5048387 14.5048387,16.0951613 12.5580645,16.0951613 L3.7016129,16.0951613 C1.75483871,16.0951613 0.164516129,14.5048387 0.164516129,12.5580645 C0.164516129,10.6112903 1.75483871,9.02096774 3.7016129,9.02096774 C3.7016129,9.02096774 12.5580645,9.02096774 12.5580645,9.02096774 Z" />
</g>
<g transform="translate(17.822581, 0.000000)">
<path d="M8.93870968,12.5580645 C8.93870968,10.6112903 10.5290323,9.02096774 12.4758065,9.02096774 C14.4225806,9.02096774 16.0129032,10.6112903 16.0129032,12.5580645 C16.0129032,14.5048387 14.4225806,16.0951613 12.4758065,16.0951613 L8.93870968,16.0951613 L8.93870968,12.5580645 Z" />
<path d="M7.15645161,12.5580645 C7.15645161,14.5048387 5.56612903,16.0951613 3.61935484,16.0951613 C1.67258065,16.0951613 0.0822580645,14.5048387 0.0822580645,12.5580645 L0.0822580645,3.7016129 C0.0822580645,1.75483871 1.67258065,0.164516129 3.61935484,0.164516129 C5.56612903,0.164516129 7.15645161,1.75483871 7.15645161,3.7016129 L7.15645161,12.5580645 Z" />
</g>
<g transform="translate(17.822581, 17.822581)">
<path d="M3.61935484,8.93870968 C5.56612903,8.93870968 7.15645161,10.5290323 7.15645161,12.4758065 C7.15645161,14.4225806 5.56612903,16.0129032 3.61935484,16.0129032 C1.67258065,16.0129032 0.0822580645,14.4225806 0.0822580645,12.4758065 L0.0822580645,8.93870968 L3.61935484,8.93870968 Z" />
<path d="M3.61935484,7.15645161 C1.67258065,7.15645161 0.0822580645,5.56612903 0.0822580645,3.61935484 C0.0822580645,1.67258065 1.67258065,0.0822580645 3.61935484,0.0822580645 L12.4758065,0.0822580645 C14.4225806,0.0822580645 16.0129032,1.67258065 16.0129032,3.61935484 C16.0129032,5.56612903 14.4225806,7.15645161 12.4758065,7.15645161 L3.61935484,7.15645161 Z" />
</g>
</g>
</svg>
);
}
export default SlackLogo;
-48
View File
@@ -1,48 +0,0 @@
import * as React from "react";
import styled from "styled-components";
import GoogleLogo from "./GoogleLogo";
import MicrosoftLogo from "./MicrosoftLogo";
import SlackLogo from "./SlackLogo";
type Props = {
providerName: string;
size?: number;
};
function AuthLogo({ providerName, size = 16 }: Props) {
switch (providerName) {
case "slack":
return (
<Logo>
<SlackLogo size={size} />
</Logo>
);
case "google":
return (
<Logo>
<GoogleLogo size={size} />
</Logo>
);
case "azure":
return (
<Logo>
<MicrosoftLogo size={size} />
</Logo>
);
default:
return null;
}
}
const Logo = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
`;
export default AuthLogo;
+12 -12
View File
@@ -2,9 +2,10 @@ import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Redirect } from "react-router-dom";
import LoadingIndicator from "~/components/LoadingIndicator";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
import { changeLanguage } from "~/utils/language";
import LoadingIndicator from "./LoadingIndicator";
type Props = {
children: JSX.Element;
@@ -13,25 +14,24 @@ type Props = {
const Authenticated = ({ children }: Props) => {
const { auth } = useStores();
const { i18n } = useTranslation();
const language = auth.user?.language;
const user = useCurrentUser({ rejectOnEmpty: false });
const language = user?.language;
// Watching for language changes here as this is the earliest point we have
// the user available and means we can start loading translations faster
// Watching for language changes here as this is the earliest point we might have the user
// available and means we can start loading translations faster
React.useEffect(() => {
changeLanguage(language, i18n);
void changeLanguage(language, i18n);
}, [i18n, language]);
if (auth.authenticated) {
const { user, team } = auth;
if (!team || !user) {
return <LoadingIndicator />;
}
return children;
}
auth.logout(true);
if (auth.isFetching) {
return <LoadingIndicator />;
}
void auth.logout(true);
return <Redirect to="/" />;
};
+73 -48
View File
@@ -1,44 +1,58 @@
import { AnimatePresence } from "framer-motion";
import { observer } from "mobx-react";
import { observer, useLocalStore } from "mobx-react";
import * as React from "react";
import { Switch, Route, useLocation, matchPath } from "react-router-dom";
import { TeamPreference } from "@shared/types";
import ErrorSuspended from "~/scenes/ErrorSuspended";
import DocumentContext from "~/components/DocumentContext";
import type { DocumentContextValue } from "~/components/DocumentContext";
import Layout from "~/components/Layout";
import RegisterKeyDown from "~/components/RegisterKeyDown";
import Sidebar from "~/components/Sidebar";
import SidebarRight from "~/components/Sidebar/Right";
import SettingsSidebar from "~/components/Sidebar/Settings";
import type { Editor as TEditor } from "~/editor";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores";
import history from "~/utils/history";
import lazyWithRetry from "~/utils/lazyWithRetry";
import {
searchPath,
matchDocumentSlug as slug,
newDocumentPath,
settingsPath,
matchDocumentHistory,
matchDocumentSlug as slug,
matchDocumentInsights,
} from "~/utils/routeHelpers";
import Fade from "./Fade";
const DocumentHistory = React.lazy(
() =>
import(
/* webpackChunkName: "document-history" */
"~/components/DocumentHistory"
)
const DocumentComments = lazyWithRetry(
() => import("~/scenes/Document/components/Comments")
);
const CommandBar = React.lazy(
() =>
import(
/* webpackChunkName: "command-bar" */
"~/components/CommandBar"
)
const DocumentHistory = lazyWithRetry(
() => import("~/scenes/Document/components/History")
);
const DocumentInsights = lazyWithRetry(
() => import("~/scenes/Document/components/Insights")
);
const CommandBar = lazyWithRetry(() => import("~/components/CommandBar"));
const AuthenticatedLayout: React.FC = ({ children }) => {
type Props = {
children?: React.ReactNode;
};
const AuthenticatedLayout: React.FC = ({ children }: Props) => {
const { ui, auth } = useStores();
const location = useLocation();
const can = usePolicy(ui.activeCollectionId);
const { user, team } = auth;
const team = useCurrentTeam();
const documentContext = useLocalStore<DocumentContextValue>(() => ({
editor: null,
setEditor: (editor: TEditor) => {
documentContext.editor = editor;
},
}));
const goToSearch = (ev: KeyboardEvent) => {
if (!ev.metaKey && !ev.ctrlKey) {
@@ -53,7 +67,7 @@ const AuthenticatedLayout: React.FC = ({ children }) => {
return;
}
const { activeCollectionId } = ui;
if (!activeCollectionId || !can.update) {
if (!activeCollectionId || !can.createDocument) {
return;
}
history.push(newDocumentPath(activeCollectionId));
@@ -63,48 +77,59 @@ const AuthenticatedLayout: React.FC = ({ children }) => {
return <ErrorSuspended />;
}
const showSidebar = auth.authenticated && user && team;
const sidebar = showSidebar ? (
const sidebar = (
<Fade>
<Switch>
<Route path={settingsPath()} component={SettingsSidebar} />
<Route component={Sidebar} />
</Switch>
</Fade>
) : undefined;
);
const showHistory = !!matchPath(location.pathname, {
path: matchDocumentHistory,
});
const showInsights = !!matchPath(location.pathname, {
path: matchDocumentInsights,
});
const showComments =
!showInsights &&
!showHistory &&
ui.activeDocumentId &&
ui.commentsExpanded.includes(ui.activeDocumentId) &&
team.getPreference(TeamPreference.Commenting);
const sidebarRight = (
<React.Suspense fallback={null}>
<AnimatePresence key={ui.activeDocumentId}>
<Switch
location={location}
key={
matchPath(location.pathname, {
path: matchDocumentHistory,
})
? "history"
: ""
}
>
<Route
key="document-history"
path={`/doc/${slug}/history/:revisionId?`}
component={DocumentHistory}
/>
</Switch>
</AnimatePresence>
</React.Suspense>
<AnimatePresence
initial={false}
key={ui.activeDocumentId ? "active" : "inactive"}
>
{(showHistory || showInsights || showComments) && (
<Route path={`/doc/${slug}`}>
<SidebarRight>
<React.Suspense fallback={null}>
{showHistory && <DocumentHistory />}
{showInsights && <DocumentInsights />}
{showComments && <DocumentComments />}
</React.Suspense>
</SidebarRight>
</Route>
)}
</AnimatePresence>
);
return (
<Layout title={team?.name} sidebar={sidebar} sidebarRight={sidebarRight}>
<RegisterKeyDown trigger="n" handler={goToNewDocument} />
<RegisterKeyDown trigger="t" handler={goToSearch} />
<RegisterKeyDown trigger="/" handler={goToSearch} />
{children}
<CommandBar />
</Layout>
<DocumentContext.Provider value={documentContext}>
<Layout title={team.name} sidebar={sidebar} sidebarRight={sidebarRight}>
<RegisterKeyDown trigger="n" handler={goToNewDocument} />
<RegisterKeyDown trigger="t" handler={goToSearch} />
<RegisterKeyDown trigger="/" handler={goToSearch} />
{children}
<React.Suspense fallback={null}>
<CommandBar />
</React.Suspense>
</Layout>
</DocumentContext.Provider>
);
};
+52 -46
View File
@@ -1,64 +1,68 @@
import { observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import styled from "styled-components";
import User from "~/models/User";
import placeholder from "./placeholder.png";
import useBoolean from "~/hooks/useBoolean";
import Initials from "./Initials";
export enum AvatarSize {
Small = 16,
Toast = 18,
Medium = 24,
Large = 32,
XLarge = 48,
XXLarge = 64,
}
export interface IAvatar {
avatarUrl: string | null;
color?: string;
initial?: string;
id?: string;
}
type Props = {
src: string;
size: number;
icon?: React.ReactNode;
user?: User;
size: AvatarSize;
src?: string;
model?: IAvatar;
alt?: string;
showBorder?: boolean;
onClick?: React.MouseEventHandler<HTMLImageElement>;
className?: string;
style?: React.CSSProperties;
};
@observer
class Avatar extends React.Component<Props> {
@observable
error: boolean;
function Avatar(props: Props) {
const { showBorder, model, style, ...rest } = props;
const src = props.src || model?.avatarUrl;
const [error, handleError] = useBoolean(false);
static defaultProps = {
size: 24,
};
handleError = () => {
this.error = true;
};
render() {
const { src, icon, showBorder, ...rest } = this.props;
return (
<AvatarWrapper>
return (
<Relative style={style}>
{src && !error ? (
<CircleImg
onError={this.handleError}
src={this.error ? placeholder : src}
onError={handleError}
src={src}
$showBorder={showBorder}
{...rest}
/>
{icon && <IconWrapper>{icon}</IconWrapper>}
</AvatarWrapper>
);
}
) : model ? (
<Initials color={model.color} $showBorder={showBorder} {...rest}>
{model.initial}
</Initials>
) : (
<Initials $showBorder={showBorder} {...rest} />
)}
</Relative>
);
}
const AvatarWrapper = styled.div`
position: relative;
`;
Avatar.defaultProps = {
size: AvatarSize.Medium,
};
const IconWrapper = styled.div`
display: flex;
position: absolute;
bottom: -2px;
right: -2px;
background: ${(props) => props.theme.primary};
border: 2px solid ${(props) => props.theme.background};
border-radius: 100%;
width: 20px;
height: 20px;
const Relative = styled.div`
position: relative;
user-select: none;
flex-shrink: 0;
`;
const CircleImg = styled.img<{ size: number; $showBorder?: boolean }>`
@@ -66,10 +70,12 @@ const CircleImg = styled.img<{ size: number; $showBorder?: boolean }>`
width: ${(props) => props.size}px;
height: ${(props) => props.size}px;
border-radius: 50%;
border: 2px solid
${(props) =>
props.$showBorder === false ? "transparent" : props.theme.background};
border: ${(props) =>
props.$showBorder === false
? "none"
: `2px solid ${props.theme.background}`};
flex-shrink: 0;
overflow: hidden;
`;
export default Avatar;
+3 -2
View File
@@ -2,6 +2,7 @@ import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled, { css } from "styled-components";
import { s } from "@shared/styles";
import User from "~/models/User";
import Avatar from "~/components/Avatar";
import Tooltip from "~/components/Tooltip";
@@ -51,7 +52,7 @@ function AvatarWithPresence({
$isObserving={isObserving}
$color={user.color}
>
<Avatar src={user.avatarUrl} onClick={onClick} size={32} />
<Avatar model={user} onClick={onClick} size={32} />
</AvatarWrapper>
</Tooltip>
</>
@@ -106,7 +107,7 @@ const AvatarWrapper = styled.div<AvatarWrapperProps>`
&:hover:after {
border: 2px solid ${(props) => props.$color};
box-shadow: inset 0 0 0 2px ${(props) => props.theme.background};
box-shadow: inset 0 0 0 2px ${s("background")};
}
`}
`;
+27
View File
@@ -0,0 +1,27 @@
import styled from "styled-components";
import Flex from "~/components/Flex";
const Initials = styled(Flex)<{
color?: string;
size: number;
$showBorder?: boolean;
}>`
align-items: center;
justify-content: center;
border-radius: 50%;
width: 100%;
height: 100%;
color: #fff;
background-color: ${(props) => props.color};
width: ${(props) => props.size}px;
height: ${(props) => props.size}px;
border-radius: 50%;
border: 2px solid
${(props) =>
props.$showBorder === false ? "transparent" : props.theme.background};
flex-shrink: 0;
font-size: ${(props) => props.size / 2}px;
font-weight: 500;
`;
export default Initials;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 564 B

+6 -2
View File
@@ -5,9 +5,13 @@ const Badge = styled.span<{ yellow?: boolean; primary?: boolean }>`
margin-left: 10px;
padding: 1px 5px 2px;
background-color: ${({ yellow, primary, theme }) =>
yellow ? theme.yellow : primary ? theme.primary : "transparent"};
yellow ? theme.yellow : primary ? theme.accent : "transparent"};
color: ${({ primary, yellow, theme }) =>
primary ? theme.white : yellow ? theme.almostBlack : theme.textTertiary};
primary
? theme.accentText
: yellow
? theme.almostBlack
: theme.textTertiary};
border: 1px solid
${({ primary, yellow, theme }) =>
primary || yellow
+7 -7
View File
@@ -1,9 +1,9 @@
import * as React from "react";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { depths } from "@shared/styles";
import { depths, s } from "@shared/styles";
import env from "~/env";
import OutlineLogo from "./OutlineLogo";
import OutlineIcon from "./Icons/OutlineIcon";
type Props = {
href?: string;
@@ -12,8 +12,8 @@ type Props = {
function Branding({ href = env.URL }: Props) {
return (
<Link href={href}>
<OutlineLogo size={16} />
&nbsp;Outline
<OutlineIcon size={20} />
&nbsp;{env.APP_NAME}
</Link>
);
}
@@ -26,16 +26,16 @@ const Link = styled.a`
font-size: 14px;
text-decoration: none;
border-top-right-radius: 2px;
color: ${(props) => props.theme.text};
color: ${s("text")};
display: flex;
align-items: center;
svg {
fill: ${(props) => props.theme.text};
fill: ${s("text")};
}
&:hover {
background: ${(props) => props.theme.sidebarBackground};
background: ${s("sidebarBackground")};
}
${breakpoint("tablet")`
+4 -5
View File
@@ -2,6 +2,7 @@ import { GoToIcon } from "outline-icons";
import * as React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import { s, ellipsis } from "@shared/styles";
import Flex from "~/components/Flex";
import BreadcrumbMenu from "~/menus/BreadcrumbMenu";
import { MenuInternalLink } from "~/types";
@@ -60,20 +61,18 @@ function Breadcrumb({
const Slash = styled(GoToIcon)`
flex-shrink: 0;
fill: ${(props) => props.theme.divider};
fill: ${s("divider")};
`;
const Item = styled(Link)<{ $highlight: boolean; $withIcon: boolean }>`
${ellipsis()}
display: flex;
flex-shrink: 1;
min-width: 0;
cursor: var(--pointer);
color: ${(props) => props.theme.text};
color: ${s("text")};
font-size: 15px;
height: 24px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-weight: ${(props) => (props.$highlight ? "500" : "inherit")};
margin-left: ${(props) => (props.$withIcon ? "4px" : "0")};
+40 -40
View File
@@ -1,28 +1,29 @@
import { LocationDescriptor } from "history";
import { ExpandedIcon } from "outline-icons";
import { darken, lighten } from "polished";
import { darken, lighten, transparentize } from "polished";
import * as React from "react";
import styled from "styled-components";
import { s } from "@shared/styles";
import ActionButton, {
Props as ActionButtonProps,
} from "~/components/ActionButton";
import { undraggableOnDesktop } from "~/styles";
type RealProps = {
fullwidth?: boolean;
borderOnHover?: boolean;
$fullwidth?: boolean;
$borderOnHover?: boolean;
$neutral?: boolean;
danger?: boolean;
iconColor?: string;
$danger?: boolean;
};
const RealButton = styled(ActionButton)<RealProps>`
display: ${(props) => (props.fullwidth ? "block" : "inline-block")};
width: ${(props) => (props.fullwidth ? "100%" : "auto")};
display: ${(props) => (props.$fullwidth ? "block" : "inline-block")};
width: ${(props) => (props.$fullwidth ? "100%" : "auto")};
margin: 0;
padding: 0;
border: 0;
background: ${(props) => props.theme.buttonBackground};
color: ${(props) => props.theme.buttonText};
background: ${s("accent")};
color: ${s("accentText")};
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px;
border-radius: 4px;
font-size: 14px;
@@ -33,14 +34,7 @@ const RealButton = styled(ActionButton)<RealProps>`
cursor: var(--pointer);
user-select: none;
appearance: none !important;
${(props) =>
!props.borderOnHover &&
`
svg {
fill: ${props.iconColor || "currentColor"};
}
`}
${undraggableOnDesktop()}
&::-moz-focus-inner {
padding: 0;
@@ -49,14 +43,14 @@ const RealButton = styled(ActionButton)<RealProps>`
&:hover:not(:disabled),
&[aria-expanded="true"] {
background: ${(props) => darken(0.05, props.theme.buttonBackground)};
background: ${(props) => darken(0.05, props.theme.accent)};
}
&:disabled {
cursor: default;
pointer-events: none;
color: ${(props) => props.theme.white50};
background: ${(props) => lighten(0.2, props.theme.buttonBackground)};
color: ${(props) => transparentize(0.5, props.theme.accentText)};
background: ${(props) => lighten(0.2, props.theme.accent)};
svg {
fill: ${(props) => props.theme.white50};
@@ -66,27 +60,18 @@ const RealButton = styled(ActionButton)<RealProps>`
${(props) =>
props.$neutral &&
`
background: ${props.theme.buttonNeutralBackground};
background: inherit;
color: ${props.theme.buttonNeutralText};
box-shadow: ${
props.borderOnHover
props.$borderOnHover
? "none"
: `rgba(0, 0, 0, 0.07) 0px 1px 2px, ${props.theme.buttonNeutralBorder} 0 0 0 1px inset`
};
${
props.borderOnHover
? ""
: `svg {
fill: ${props.iconColor || "currentColor"};
}`
}
&:hover:not(:disabled),
&[aria-expanded="true"] {
background: ${
props.borderOnHover
props.$borderOnHover
? props.theme.buttonNeutralBackground
: darken(0.05, props.theme.buttonNeutralBackground)
};
@@ -106,7 +91,7 @@ const RealButton = styled(ActionButton)<RealProps>`
`}
${(props) =>
props.danger &&
props.$danger &&
`
background: ${props.theme.danger};
color: ${props.theme.white};
@@ -153,16 +138,15 @@ export const Inner = styled.span<{
export type Props<T> = ActionButtonProps & {
icon?: React.ReactNode;
iconColor?: string;
children?: React.ReactNode;
disclosure?: boolean;
neutral?: boolean;
danger?: boolean;
primary?: boolean;
fullwidth?: boolean;
as?: T;
to?: LocationDescriptor;
borderOnHover?: boolean;
hideIcon?: boolean;
href?: string;
"data-on"?: string;
"data-event-category"?: string;
@@ -173,10 +157,23 @@ const Button = <T extends React.ElementType = "button">(
props: Props<T> & React.ComponentPropsWithoutRef<T>,
ref: React.Ref<HTMLButtonElement>
) => {
const { type, children, value, disclosure, neutral, action, ...rest } = props;
const {
type,
children,
value,
disclosure,
neutral,
action,
icon,
borderOnHover,
hideIcon,
fullwidth,
danger,
...rest
} = props;
const hasText = children !== undefined || value !== undefined;
const icon = action?.icon ?? rest.icon;
const hasIcon = icon !== undefined;
const ic = hideIcon ? undefined : action?.icon ?? icon;
const hasIcon = ic !== undefined;
return (
<RealButton
@@ -184,12 +181,15 @@ const Button = <T extends React.ElementType = "button">(
ref={ref}
$neutral={neutral}
action={action}
$danger={danger}
$fullwidth={fullwidth}
$borderOnHover={borderOnHover}
{...rest}
>
<Inner hasIcon={hasIcon} hasText={hasText} disclosure={disclosure}>
{hasIcon && icon}
{hasIcon && ic}
{hasText && <Label hasIcon={hasIcon}>{children || value}</Label>}
{disclosure && <ExpandedIcon color="currentColor" />}
{disclosure && <ExpandedIcon />}
</Inner>
</RealButton>
);
+15
View File
@@ -0,0 +1,15 @@
import styled from "styled-components";
import Button, { Inner } from "./Button";
const ButtonSmall = styled(Button)`
font-size: 13px;
height: 26px;
${Inner} {
padding: 0 6px;
line-height: 26px;
min-height: 26px;
}
`;
export default ButtonSmall;
+6 -7
View File
@@ -3,6 +3,7 @@ import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
type Props = {
children?: React.ReactNode;
withStickyHeader?: boolean;
};
@@ -26,12 +27,10 @@ const Content = styled.div`
`};
`;
const CenteredContent: React.FC<Props> = ({ children, ...rest }) => {
return (
<Container {...rest}>
<Content>{children}</Content>
</Container>
);
};
const CenteredContent: React.FC<Props> = ({ children, ...rest }: Props) => (
<Container {...rest}>
<Content>{children}</Content>
</Container>
);
export default CenteredContent;
+17
View File
@@ -0,0 +1,17 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import { changeLanguage } from "~/utils/language";
type Props = {
locale: string;
};
export default function ChangeLanguage({ locale }: Props) {
const { i18n } = useTranslation();
React.useEffect(() => {
void changeLanguage(locale, i18n);
}, [locale, i18n]);
return null;
}
+2 -2
View File
@@ -42,7 +42,7 @@ const Circle = ({
style={{
transition: "stroke-dashoffset 0.6s ease 0s",
}}
></circle>
/>
);
};
@@ -63,7 +63,7 @@ const CircularProgressBar = ({
<Circle color={theme.progressBarBackground} offset={offset} />
{percentage > 0 && (
<Circle
color={theme.primary}
color={theme.accent}
percentage={percentage}
offset={offset}
/>
+7 -4
View File
@@ -1,9 +1,12 @@
import styled from "styled-components";
const ClickablePadding = styled.div<{ grow?: boolean }>`
min-height: 10em;
cursor: ${({ onClick }) => (onClick ? "text" : "default")};
${({ grow }) => grow && `flex-grow: 100;`};
const ClickablePadding = styled.div<{
grow?: boolean;
minHeight?: React.CSSProperties["paddingBottom"];
}>`
min-height: ${(props) => props.minHeight || "50vh"};
flex-grow: 100;
cursor: text;
`;
export default ClickablePadding;
+7 -7
View File
@@ -1,15 +1,17 @@
import { sortBy, filter, uniq, isEqual } from "lodash";
import filter from "lodash/filter";
import isEqual from "lodash/isEqual";
import sortBy from "lodash/sortBy";
import uniq from "lodash/uniq";
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { usePopoverState, PopoverDisclosure } from "reakit/Popover";
import Document from "~/models/Document";
import { AvatarWithPresence } from "~/components/Avatar";
import AvatarWithPresence from "~/components/Avatar/AvatarWithPresence";
import DocumentViews from "~/components/DocumentViews";
import Facepile from "~/components/Facepile";
import NudeButton from "~/components/NudeButton";
import Popover from "~/components/Popover";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
@@ -20,7 +22,6 @@ type Props = {
function Collaborators(props: Props) {
const { t } = useTranslation();
const user = useCurrentUser();
const team = useCurrentTeam();
const currentUserId = user?.id;
const [requestedUserIds, setRequestedUserIds] = React.useState<string[]>([]);
const { users, presence, ui } = useStores();
@@ -59,7 +60,7 @@ function Collaborators(props: Props) {
if (!isEqual(requestedUserIds, ids) && ids.length > 0) {
setRequestedUserIds(ids);
users.fetchPage({ ids, limit: 100 });
void users.fetchPage({ ids, limit: 100 });
}
}, [document, users, presentIds, document.collaboratorIds, requestedUserIds]);
@@ -79,8 +80,7 @@ function Collaborators(props: Props) {
const isPresent = presentIds.includes(collaborator.id);
const isEditing = editingIds.includes(collaborator.id);
const isObserving = ui.observingUserId === collaborator.id;
const isObservable =
team.collaborativeEditing && collaborator.id !== user.id;
const isObservable = collaborator.id !== user.id;
return (
<AvatarWithPresence
+7 -3
View File
@@ -2,6 +2,7 @@ import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import { useHistory } from "react-router-dom";
import { toast } from "sonner";
import Collection from "~/models/Collection";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import Text from "~/components/Text";
@@ -22,11 +23,14 @@ function CollectionDeleteDialog({ collection, onSubmit }: Props) {
const handleSubmit = async () => {
const redirect = collection.id === ui.activeCollectionId;
await collection.delete();
onSubmit();
if (redirect) {
history.push(homePath());
}
await collection.delete();
onSubmit();
toast.success(t("Collection deleted"));
};
return (
@@ -39,7 +43,7 @@ function CollectionDeleteDialog({ collection, onSubmit }: Props) {
<>
<Text type="secondary">
<Trans
defaults="Are you sure about that? Deleting the <em>{{collectionName}}</em> collection is permanent and cannot be restored, however documents within will be moved to the trash."
defaults="Are you sure about that? Deleting the <em>{{collectionName}}</em> collection is permanent and cannot be restored, however all published documents within will be moved to the trash."
values={{
collectionName: collection.name,
}}
+26 -18
View File
@@ -3,16 +3,28 @@ import { observer } from "mobx-react";
import { transparentize } from "polished";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import styled from "styled-components";
import { richExtensions } from "@shared/editor/nodes";
import { s } from "@shared/styles";
import Collection from "~/models/Collection";
import Arrow from "~/components/Arrow";
import ButtonLink from "~/components/ButtonLink";
import Editor from "~/components/Editor";
import LoadingIndicator from "~/components/LoadingIndicator";
import NudeButton from "~/components/NudeButton";
import BlockMenuExtension from "~/editor/extensions/BlockMenu";
import EmojiMenuExtension from "~/editor/extensions/EmojiMenu";
import HoverPreviewsExtension from "~/editor/extensions/HoverPreviews";
import usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
const extensions = [
...richExtensions,
BlockMenuExtension,
EmojiMenuExtension,
HoverPreviewsExtension,
];
type Props = {
collection: Collection;
@@ -20,7 +32,6 @@ type Props = {
function CollectionDescription({ collection }: Props) {
const { collections } = useStores();
const { showToast } = useToasts();
const { t } = useTranslation();
const [isExpanded, setExpanded] = React.useState(false);
const [isEditing, setEditing] = React.useState(false);
@@ -58,21 +69,17 @@ function CollectionDescription({ collection }: Props) {
});
setDirty(false);
} catch (err) {
showToast(
t("Sorry, an error occurred saving the collection", {
type: "error",
})
);
toast.error(t("Sorry, an error occurred saving the collection"));
throw err;
}
}, 1000),
[collection, showToast, t]
[collection, t]
);
const handleChange = React.useCallback(
(getValue) => {
async (getValue) => {
setDirty(true);
handleSave(getValue);
await handleSave(getValue);
},
[handleSave]
);
@@ -108,9 +115,10 @@ function CollectionDescription({ collection }: Props) {
readOnly={!isEditing}
autoFocus={isEditing}
onBlur={handleStopEditing}
extensions={extensions}
maxLength={1000}
embedsDisabled
readOnlyWriteCheckboxes
canUpdate
/>
</React.Suspense>
) : (
@@ -141,7 +149,7 @@ function CollectionDescription({ collection }: Props) {
const Disclosure = styled(NudeButton)`
opacity: 0;
color: ${(props) => props.theme.divider};
color: ${s("divider")};
position: absolute;
top: calc(25vh - 50px);
left: 50%;
@@ -155,12 +163,12 @@ const Disclosure = styled(NudeButton)`
}
&:active {
color: ${(props) => props.theme.sidebarText};
color: ${s("sidebarText")};
}
`;
const Placeholder = styled(ButtonLink)`
color: ${(props) => props.theme.placeholder};
color: ${s("placeholder")};
cursor: text;
min-height: 27px;
`;
@@ -169,7 +177,7 @@ const MaxHeight = styled.div`
position: relative;
max-height: 25vh;
overflow: hidden;
margin: -12px -8px -8px;
margin: 8px -8px -8px;
padding: 8px;
&[data-editing="true"],
@@ -193,7 +201,7 @@ const Input = styled.div`
margin: -8px;
padding: 8px;
border-radius: 8px;
transition: ${(props) => props.theme.backgroundTransition};
transition: ${s("backgroundTransition")};
&:after {
content: "";
@@ -206,7 +214,7 @@ const Input = styled.div`
background: linear-gradient(
180deg,
${(props) => transparentize(1, props.theme.background)} 0%,
${(props) => props.theme.background} 100%
${s("background")} 100%
);
}
@@ -218,7 +226,7 @@ const Input = styled.div`
}
&[data-editing="true"] {
background: ${(props) => props.theme.secondaryBackground};
background: ${s("secondaryBackground")};
}
.block-menu-trigger,
+17 -52
View File
@@ -1,66 +1,37 @@
import { useKBar, KBarPositioner, KBarAnimator, KBarSearch } from "kbar";
import { observer } from "mobx-react";
import { QuestionMarkIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Portal } from "react-portal";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { depths } from "@shared/styles";
import { depths, s } from "@shared/styles";
import CommandBarResults from "~/components/CommandBarResults";
import SearchActions from "~/components/SearchActions";
import rootActions from "~/actions/root";
import useCommandBarActions from "~/hooks/useCommandBarActions";
import useSettingsActions from "~/hooks/useSettingsAction";
import useStores from "~/hooks/useStores";
import { CommandBarAction } from "~/types";
import { metaDisplay } from "~/utils/keyboard";
import Text from "./Text";
import useSettingsActions from "~/hooks/useSettingsActions";
import useTemplateActions from "~/hooks/useTemplateActions";
function CommandBar() {
const { t } = useTranslation();
const { ui } = useStores();
const settingsActions = useSettingsActions();
const templateActions = useTemplateActions();
const commandBarActions = React.useMemo(
() => [...rootActions, settingsActions],
[settingsActions]
() => [...rootActions, templateActions, settingsActions],
[settingsActions, templateActions]
);
useCommandBarActions(commandBarActions);
const { rootAction } = useKBar((state) => ({
rootAction: state.currentRootActionId
? ((state.actions[
state.currentRootActionId
] as unknown) as CommandBarAction)
: undefined,
}));
return (
<>
<KBarPortal>
<Positioner>
<Animator>
<SearchActions />
<SearchInput
placeholder={`${
rootAction?.placeholder ||
rootAction?.name ||
t("Type a command or search")
}`}
/>
<SearchInput defaultPlaceholder={t("Type a command or search")} />
<CommandBarResults />
{ui.commandBarOpenedFromSidebar && (
<Hint size="small" type="tertiary">
<QuestionMarkIcon size={18} color="currentColor" />
{t(
"Open search from anywhere with the {{ shortcut }} shortcut",
{
shortcut: `${metaDisplay} + k`,
}
)}
</Hint>
)}
</Animator>
</Positioner>
</KBarPortal>
@@ -68,7 +39,11 @@ function CommandBar() {
);
}
const KBarPortal: React.FC = ({ children }) => {
type Props = {
children?: React.ReactNode;
};
const KBarPortal: React.FC = ({ children }: Props) => {
const { showing } = useKBar((state) => ({
showing: state.visualState !== "hidden",
}));
@@ -80,16 +55,6 @@ const KBarPortal: React.FC = ({ children }) => {
return <Portal>{children}</Portal>;
};
const Hint = styled(Text)`
display: flex;
align-items: center;
gap: 4px;
border-top: 1px solid ${(props) => props.theme.background};
margin: 1px 0 0;
padding: 6px 16px;
width: 100%;
`;
const Positioner = styled(KBarPositioner)`
z-index: ${depths.commandBar};
`;
@@ -99,12 +64,12 @@ const SearchInput = styled(KBarSearch)`
width: 100%;
outline: none;
border: none;
background: ${(props) => props.theme.menuBackground};
color: ${(props) => props.theme.text};
background: ${s("menuBackground")};
color: ${s("text")};
&:disabled,
&::placeholder {
color: ${(props) => props.theme.placeholder};
color: ${s("placeholder")};
}
`;
@@ -112,8 +77,8 @@ const Animator = styled(KBarAnimator)`
max-width: 600px;
max-height: 75vh;
width: 90vw;
background: ${(props) => props.theme.menuBackground};
color: ${(props) => props.theme.text};
background: ${s("menuBackground")};
color: ${s("text")};
border-radius: 8px;
overflow: hidden;
box-shadow: rgb(0 0 0 / 40%) 0px 16px 60px;
+36 -21
View File
@@ -2,8 +2,10 @@ import { ActionImpl } from "kbar";
import { ArrowIcon, BackIcon } from "outline-icons";
import * as React from "react";
import styled, { css, useTheme } from "styled-components";
import { s, ellipsis } from "@shared/styles";
import Flex from "~/components/Flex";
import Key from "~/components/Key";
import Text from "./Text";
type Props = {
action: ActionImpl;
@@ -38,10 +40,9 @@ function CommandBarItem(
// @ts-expect-error no icon on ActionImpl
React.cloneElement(action.icon, {
size: 22,
color: "currentColor",
})
) : (
<ArrowIcon color="currentColor" />
<ArrowIcon />
)}
</Icon>
@@ -55,44 +56,59 @@ function CommandBarItem(
{action.children?.length ? "…" : ""}
</Content>
{action.shortcut?.length ? (
<div
style={{
display: "grid",
gridAutoFlow: "column",
gap: "4px",
}}
>
{action.shortcut.map((sc: string) => (
<Key key={sc}>{sc}</Key>
<Shortcut>
{action.shortcut.map((sc: string, index) => (
<React.Fragment key={sc}>
{index > 0 ? (
<>
{" "}
<Text size="xsmall" as="span" type="secondary">
then
</Text>{" "}
</>
) : (
""
)}
{sc.split("+").map((s) => (
<Key key={s}>{s}</Key>
))}
</React.Fragment>
))}
</div>
</Shortcut>
) : null}
</Item>
);
}
const Shortcut = styled.div`
display: grid;
grid-auto-flow: column;
gap: 4px;
`;
const Icon = styled(Flex)`
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
color: ${(props) => props.theme.textSecondary};
color: ${s("textSecondary")};
flex-shrink: 0;
`;
const Ancestor = styled.span`
color: ${(props) => props.theme.textSecondary};
color: ${s("textSecondary")};
`;
const Content = styled(Flex)`
overflow: hidden;
text-overflow: ellipsis;
${ellipsis()}
flex-shrink: 1;
`;
const Item = styled.div<{ active?: boolean }>`
font-size: 15px;
padding: 10px 16px;
font-size: 14px;
padding: 9px 12px;
margin: 0 8px;
border-radius: 4px;
background: ${(props) =>
props.active ? props.theme.menuItemSelected : "none"};
display: flex;
@@ -100,9 +116,8 @@ const Item = styled.div<{ active?: boolean }>`
justify-content: space-between;
cursor: var(--pointer);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
${ellipsis()}
user-select: none;
min-width: 0;
${(props) =>
+26 -16
View File
@@ -1,35 +1,45 @@
import { useMatches, KBarResults } from "kbar";
import * as React from "react";
import styled from "styled-components";
import { s } from "@shared/styles";
import CommandBarItem from "~/components/CommandBarItem";
export default function CommandBarResults() {
const { results, rootActionId } = useMatches();
return (
<KBarResults
items={results}
maxHeight={400}
onRender={({ item, active }) =>
typeof item === "string" ? (
<Header>{item}</Header>
) : (
<CommandBarItem
action={item}
active={active}
currentRootActionId={rootActionId}
/>
)
}
/>
<Container>
<KBarResults
items={results}
maxHeight={400}
onRender={({ item, active }) =>
typeof item === "string" ? (
<Header>{item}</Header>
) : (
<CommandBarItem
action={item}
active={active}
currentRootActionId={rootActionId}
/>
)
}
/>
</Container>
);
}
// Cannot style KBarResults unfortunately, so we must wrap and target the inner
const Container = styled.div`
> div {
padding-bottom: 8px;
}
`;
const Header = styled.h3`
font-size: 13px;
letter-spacing: 0.04em;
margin: 0;
padding: 16px 0 4px 20px;
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
height: 36px;
`;
+52
View File
@@ -0,0 +1,52 @@
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import { toast } from "sonner";
import Comment from "~/models/Comment";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import Text from "~/components/Text";
import useStores from "~/hooks/useStores";
type Props = {
comment: Comment;
onSubmit?: () => void;
};
function CommentDeleteDialog({ comment, onSubmit }: Props) {
const { comments } = useStores();
const { t } = useTranslation();
const hasChildComments = comments.inThread(comment.id).length > 1;
const handleSubmit = async () => {
try {
await comment.delete();
onSubmit?.();
} catch (err) {
toast.error(err.message);
}
};
return (
<ConfirmationDialog
onSubmit={handleSubmit}
submitText={t("Im sure Delete")}
savingText={`${t("Deleting")}`}
danger
>
<Text type="secondary">
{hasChildComments ? (
<Trans>
Are you sure you want to permanently delete this entire comment
thread?
</Trans>
) : (
<Trans>
Are you sure you want to permanently delete this comment?
</Trans>
)}
</Text>
</ConfirmationDialog>
);
}
export default observer(CommentDeleteDialog);
+15 -9
View File
@@ -1,10 +1,10 @@
import { observer } from "mobx-react";
import * as React from "react";
import { toast } from "sonner";
import Button from "~/components/Button";
import Flex from "~/components/Flex";
import Text from "~/components/Text";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
type Props = {
/** Callback when the dialog is submitted */
@@ -15,6 +15,9 @@ type Props = {
savingText?: string;
/** If true, the submit button will be a dangerous red */
danger?: boolean;
/** Keep the submit button disabled */
disabled?: boolean;
children?: React.ReactNode;
};
const ConfirmationDialog: React.FC<Props> = ({
@@ -23,10 +26,10 @@ const ConfirmationDialog: React.FC<Props> = ({
submitText,
savingText,
danger,
}) => {
disabled = false,
}: Props) => {
const [isSaving, setIsSaving] = React.useState(false);
const { dialogs } = useStores();
const { showToast } = useToasts();
const handleSubmit = React.useCallback(
async (ev: React.SyntheticEvent) => {
@@ -36,22 +39,25 @@ const ConfirmationDialog: React.FC<Props> = ({
await onSubmit();
dialogs.closeAllModals();
} catch (err) {
showToast(err.message, {
type: "error",
});
toast.error(err.message);
} finally {
setIsSaving(false);
}
},
[onSubmit, dialogs, showToast]
[onSubmit, dialogs]
);
return (
<Flex column>
<form onSubmit={handleSubmit}>
<Text type="secondary">{children}</Text>
<Button type="submit" disabled={isSaving} danger={danger} autoFocus>
{isSaving ? savingText : submitText}
<Button
type="submit"
disabled={isSaving || disabled}
danger={danger}
autoFocus
>
{isSaving && savingText ? savingText : submitText}
</Button>
</form>
</Flex>
+39 -6
View File
@@ -14,15 +14,48 @@ function ConnectionStatus() {
const theme = useTheme();
const { t } = useTranslation();
const codeToMessage = {
1009: {
title: t("Document is too large"),
body: t(
"This document has reached the maximum size and can no longer be edited"
),
},
4401: {
title: t("Authentication failed"),
body: t("Please try logging out and back in again"),
},
4403: {
title: t("Authorization failed"),
body: t("You may have lost access to this document, try reloading"),
},
4503: {
title: t("Too many users connected to document"),
body: t("Your edits will sync once other users leave the document"),
},
};
const message = ui.multiplayerErrorCode
? codeToMessage[ui.multiplayerErrorCode]
: undefined;
return ui.multiplayerStatus === "connecting" ||
ui.multiplayerStatus === "disconnected" ? (
<Tooltip
tooltip={
<Centered>
<strong>{t("Server connection lost")}</strong>
<br />
{t("Edits you make will sync once youre online")}
</Centered>
message ? (
<Centered>
<strong>{message.title}</strong>
<br />
{message.body}
</Centered>
) : (
<Centered>
<strong>{t("Server connection lost")}</strong>
<br />
{t("Edits you make will sync once youre online")}
</Centered>
)
}
placement="bottom"
>
@@ -39,8 +72,8 @@ const Button = styled(NudeButton)`
display: none;
position: fixed;
bottom: 0;
right: 32px;
margin: 24px;
transform: translateX(-32px);
${breakpoint("tablet")`
display: block;
+117 -101
View File
@@ -1,6 +1,7 @@
import isPrintableKeyEvent from "is-printable-key-event";
import * as React from "react";
import styled from "styled-components";
import { s } from "@shared/styles";
import useOnScreen from "~/hooks/useOnScreen";
type Props = Omit<React.HTMLAttributes<HTMLSpanElement>, "ref" | "onChange"> & {
@@ -8,6 +9,7 @@ type Props = Omit<React.HTMLAttributes<HTMLSpanElement>, "ref" | "onChange"> & {
readOnly?: boolean;
onClick?: React.MouseEventHandler<HTMLDivElement>;
onChange?: (text: string) => void;
onFocus?: React.FocusEventHandler<HTMLSpanElement> | undefined;
onBlur?: React.FocusEventHandler<HTMLSpanElement> | undefined;
onInput?: React.FormEventHandler<HTMLSpanElement> | undefined;
onKeyDown?: React.KeyboardEventHandler<HTMLSpanElement> | undefined;
@@ -29,63 +31,75 @@ export type RefHandle = {
* Defines a content editable component with the same interface as a native
* HTMLInputElement (or, as close as we can get).
*/
const ContentEditable = React.forwardRef(
(
{
disabled,
onChange,
onInput,
onBlur,
onKeyDown,
value,
children,
className,
maxLength,
autoFocus,
placeholder,
readOnly,
dir,
onClick,
...rest
}: Props,
ref: React.RefObject<RefHandle>
) => {
const contentRef = React.useRef<HTMLSpanElement>(null);
const [innerValue, setInnerValue] = React.useState<string>(value);
const lastValue = React.useRef("");
const ContentEditable = React.forwardRef(function _ContentEditable(
{
disabled,
onChange,
onInput,
onFocus,
onBlur,
onKeyDown,
value,
children,
className,
maxLength,
autoFocus,
placeholder,
readOnly,
dir,
onClick,
...rest
}: Props,
ref: React.RefObject<RefHandle>
) {
const contentRef = React.useRef<HTMLSpanElement>(null);
const [innerValue, setInnerValue] = React.useState<string>(value);
const lastValue = React.useRef(value);
React.useImperativeHandle(ref, () => ({
focus: () => {
contentRef.current?.focus();
},
focusAtStart: () => {
if (contentRef.current) {
contentRef.current.focus();
React.useImperativeHandle(ref, () => ({
focus: () => {
if (contentRef.current) {
contentRef.current.focus();
// looks unnecessary but required because of https://github.com/outline/outline/issues/5198
if (!contentRef.current.innerText) {
placeCaret(contentRef.current, true);
}
},
focusAtEnd: () => {
if (contentRef.current) {
contentRef.current.focus();
placeCaret(contentRef.current, false);
}
},
getComputedDirection: () => {
if (contentRef.current) {
return window.getComputedStyle(contentRef.current).direction;
}
return "ltr";
},
}));
}
},
focusAtStart: () => {
if (contentRef.current) {
contentRef.current.focus();
placeCaret(contentRef.current, true);
}
},
focusAtEnd: () => {
if (contentRef.current) {
contentRef.current.focus();
placeCaret(contentRef.current, false);
}
},
getComputedDirection: () => {
if (contentRef.current) {
return window.getComputedStyle(contentRef.current).direction;
}
return "ltr";
},
}));
const wrappedEvent = (
const wrappedEvent =
(
callback:
| React.FocusEventHandler<HTMLSpanElement>
| React.FormEventHandler<HTMLSpanElement>
| React.KeyboardEventHandler<HTMLSpanElement>
| undefined
) => (event: any) => {
const text = contentRef.current?.innerText || "";
) =>
(event: any) => {
if (readOnly) {
return;
}
const text = event.currentTarget.textContent || "";
if (maxLength && isPrintableKeyEvent(event) && text.length >= maxLength) {
event?.preventDefault();
@@ -94,62 +108,63 @@ const ContentEditable = React.forwardRef(
if (text !== lastValue.current) {
lastValue.current = text;
onChange && onChange(text);
onChange?.(text);
}
callback?.(event);
};
// This is to account for being within a React.Suspense boundary, in this
// case the component may be rendered with display: none. React 18 may solve
// this in the future by delaying useEffect hooks:
// https://github.com/facebook/react/issues/14536#issuecomment-861980492
const isVisible = useOnScreen(contentRef);
// This is to account for being within a React.Suspense boundary, in this
// case the component may be rendered with display: none. React 18 may solve
// this in the future by delaying useEffect hooks:
// https://github.com/facebook/react/issues/14536#issuecomment-861980492
const isVisible = useOnScreen(contentRef);
React.useEffect(() => {
if (autoFocus && isVisible && !disabled && !readOnly) {
contentRef.current?.focus();
}
}, [autoFocus, disabled, isVisible, readOnly, contentRef]);
React.useEffect(() => {
if (autoFocus && isVisible && !disabled && !readOnly) {
contentRef.current?.focus();
}
}, [autoFocus, disabled, isVisible, readOnly, contentRef]);
React.useEffect(() => {
if (value !== contentRef.current?.innerText) {
setInnerValue(value);
}
}, [value, contentRef]);
React.useEffect(() => {
if (contentRef.current && value !== contentRef.current.textContent) {
setInnerValue(value);
}
}, [value, contentRef]);
// Ensure only plain text can be pasted into title when pasting from another
// rich text editor
const handlePaste = React.useCallback(
(event: React.ClipboardEvent<HTMLSpanElement>) => {
event.preventDefault();
const text = event.clipboardData.getData("text/plain");
window.document.execCommand("insertText", false, text);
},
[]
);
// Ensure only plain text can be pasted into input when pasting from another
// rich text source. Note: If `onPaste` prop is passed then it takes
// priority over this behavior.
const handlePaste = React.useCallback(
(event: React.ClipboardEvent<HTMLSpanElement>) => {
event.preventDefault();
const text = event.clipboardData.getData("text/plain");
window.document.execCommand("insertText", false, text);
},
[]
);
return (
<div className={className} dir={dir} onClick={onClick}>
<Content
ref={contentRef}
contentEditable={!disabled && !readOnly}
onInput={wrappedEvent(onInput)}
onBlur={wrappedEvent(onBlur)}
onKeyDown={wrappedEvent(onKeyDown)}
onPaste={handlePaste}
data-placeholder={placeholder}
suppressContentEditableWarning
role="textbox"
{...rest}
>
{innerValue}
</Content>
{children}
</div>
);
}
);
return (
<div className={className} dir={dir} onClick={onClick} tabIndex={-1}>
{children}
<Content
ref={contentRef}
contentEditable={!disabled && !readOnly}
onInput={wrappedEvent(onInput)}
onFocus={wrappedEvent(onFocus)}
onBlur={wrappedEvent(onBlur)}
onKeyDown={wrappedEvent(onKeyDown)}
onPaste={handlePaste}
data-placeholder={placeholder}
suppressContentEditableWarning
role="textbox"
{...rest}
>
{innerValue}
</Content>
</div>
);
});
function placeCaret(element: HTMLElement, atStart: boolean) {
if (
@@ -166,13 +181,14 @@ function placeCaret(element: HTMLElement, atStart: boolean) {
}
const Content = styled.span`
background: ${(props) => props.theme.background};
transition: ${(props) => props.theme.backgroundTransition};
color: ${(props) => props.theme.text};
-webkit-text-fill-color: ${(props) => props.theme.text};
background: ${s("background")};
transition: ${s("backgroundTransition")};
color: ${s("text")};
-webkit-text-fill-color: ${s("text")};
outline: none;
resize: none;
cursor: text;
word-break: anywhere;
&:empty {
display: inline-block;
@@ -180,8 +196,8 @@ const Content = styled.span`
&:empty::before {
display: inline-block;
color: ${(props) => props.theme.placeholder};
-webkit-text-fill-color: ${(props) => props.theme.placeholder};
color: ${s("placeholder")};
-webkit-text-fill-color: ${s("placeholder")};
content: attr(data-placeholder);
pointer-events: none;
height: 0;
+2 -1
View File
@@ -1,10 +1,11 @@
import styled from "styled-components";
import { s } from "@shared/styles";
const Header = styled.h3`
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
color: ${(props) => props.theme.sidebarText};
color: ${s("sidebarText")};
letter-spacing: 0.04em;
margin: 1em 12px 0.5em;
`;
@@ -1,11 +1,13 @@
import styled from "styled-components";
import { s } from "@shared/styles";
const MenuIconWrapper = styled.span`
width: 24px;
height: 24px;
margin-right: 6px;
margin-left: -4px;
color: ${({ theme }) => theme.textSecondary};
color: ${s("textSecondary")};
flex-shrink: 0;
`;
export default MenuIconWrapper;
+87 -60
View File
@@ -1,13 +1,16 @@
import { LocationDescriptor } from "history";
import { CheckmarkIcon } from "outline-icons";
import * as React from "react";
import { mergeRefs } from "react-merge-refs";
import { MenuItem as BaseMenuItem } from "reakit/Menu";
import styled, { css } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import MenuIconWrapper from "../MenuIconWrapper";
import MenuIconWrapper from "./MenuIconWrapper";
type Props = {
id?: string;
onClick?: (event: React.SyntheticEvent) => void | Promise<void>;
active?: boolean;
selected?: boolean;
disabled?: boolean;
dangerous?: boolean;
@@ -18,41 +21,69 @@ type Props = {
hide?: () => void;
level?: number;
icon?: React.ReactElement;
children?: React.ReactNode;
ref?: React.LegacyRef<HTMLButtonElement> | undefined;
};
const MenuItem: React.FC<Props> = ({
onClick,
children,
selected,
disabled,
as,
hide,
icon,
...rest
}) => {
const handleClick = React.useCallback(
(ev) => {
if (onClick) {
const MenuItem = (
{
onClick,
children,
active,
selected,
disabled,
as,
hide,
icon,
...rest
}: Props,
ref: React.Ref<HTMLAnchorElement>
) => {
const content = React.useCallback(
(props) => {
const handleClick = async (ev: React.MouseEvent) => {
hide?.();
if (onClick) {
ev.preventDefault();
await onClick(ev);
}
};
// Preventing default mousedown otherwise menu items do not work in Firefox,
// which triggers the hideOnClickOutside handler first via mousedown hiding
// and un-rendering the menu contents.
const handleMouseDown = (ev: React.MouseEvent) => {
ev.preventDefault();
ev.stopPropagation();
onClick(ev);
}
};
if (hide) {
hide();
}
return (
<MenuAnchor
{...props}
$active={active}
as={onClick ? "button" : as}
onClick={handleClick}
onMouseDown={handleMouseDown}
ref={mergeRefs([
ref,
props.ref as React.RefObject<HTMLAnchorElement>,
])}
>
{selected !== undefined && (
<>
{selected ? <CheckmarkIcon /> : <Spacer />}
&nbsp;
</>
)}
{icon && <MenuIconWrapper>{icon}</MenuIconWrapper>}
{children}
</MenuAnchor>
);
},
[onClick, hide]
[active, as, hide, icon, onClick, ref, children, selected]
);
// Preventing default mousedown otherwise menu items do not work in Firefox,
// which triggers the hideOnClickOutside handler first via mousedown hiding
// and un-rendering the menu contents.
const handleMouseDown = React.useCallback((ev) => {
ev.preventDefault();
ev.stopPropagation();
}, []);
return (
<BaseMenuItem
onClick={disabled ? undefined : onClick}
@@ -60,28 +91,7 @@ const MenuItem: React.FC<Props> = ({
hide={hide}
{...rest}
>
{(props) => (
<MenuAnchor
{...props}
$toggleable={selected !== undefined}
as={onClick ? "button" : as}
onClick={handleClick}
onMouseDown={handleMouseDown}
>
{selected !== undefined && (
<>
{selected ? <CheckmarkIcon color="currentColor" /> : <Spacer />}
&nbsp;
</>
)}
{icon && (
<MenuIconWrapper>
{React.cloneElement(icon, { color: "currentColor" })}
</MenuIconWrapper>
)}
{children}
</MenuAnchor>
)}
{content}
</BaseMenuItem>
);
};
@@ -97,6 +107,7 @@ type MenuAnchorProps = {
disabled?: boolean;
dangerous?: boolean;
disclosure?: boolean;
$active?: boolean;
};
export const MenuAnchorCSS = css<MenuAnchorProps>`
@@ -104,6 +115,7 @@ export const MenuAnchorCSS = css<MenuAnchorProps>`
margin: 0;
border: 0;
padding: 12px;
border-radius: 4px;
padding-left: ${(props) => 12 + (props.level || 0) * 10}px;
width: 100%;
min-height: 32px;
@@ -127,37 +139,52 @@ export const MenuAnchorCSS = css<MenuAnchorProps>`
opacity: ${(props) => (props.disabled ? ".5" : 1)};
}
${(props) =>
props.disabled
? "pointer-events: none;"
: `
${(props) => props.disabled && "pointer-events: none;"}
${(props) =>
props.$active === undefined &&
!props.disabled &&
`
@media (hover: hover) {
&:hover,
&:focus,
&.focus-visible {
color: ${props.theme.white};
background: ${props.dangerous ? props.theme.danger : props.theme.primary};
color: ${props.theme.accentText};
background: ${props.dangerous ? props.theme.danger : props.theme.accent};
box-shadow: none;
cursor: var(--pointer);
svg {
fill: ${props.theme.white};
fill: ${props.theme.accentText};
}
}
}
`};
`}
${(props) =>
props.$active &&
!props.disabled &&
`
color: ${props.theme.accentText};
background: ${props.dangerous ? props.theme.danger : props.theme.accent};
box-shadow: none;
cursor: var(--pointer);
svg {
fill: ${props.theme.accentText};
}
`}
${breakpoint("tablet")`
padding: 4px 12px;
padding-right: ${(props: MenuAnchorProps) =>
props.disclosure ? 32 : 12}px;
font-size: 14px;
`};
`}
`;
export const MenuAnchor = styled.a`
${MenuAnchorCSS}
`;
export default MenuItem;
export default React.forwardRef<HTMLAnchorElement, Props>(MenuItem);
+12 -8
View File
@@ -2,17 +2,17 @@ import * as React from "react";
import { useMousePosition } from "~/hooks/useMousePosition";
type Positions = {
/* Sub-menu x */
/** Sub-menu x */
x: number;
/* Sub-menu y */
/** Sub-menu y */
y: number;
/* Sub-menu height */
/** Sub-menu height */
h: number;
/* Sub-menu width */
/** Sub-menu width */
w: number;
/* Mouse x */
/** Mouse x */
mouseX: number;
/* Mouse y */
/** Mouse y */
mouseY: number;
};
@@ -24,8 +24,12 @@ type Positions = {
export default function MouseSafeArea(props: {
parentRef: React.RefObject<HTMLElement | null>;
}) {
const { x = 0, y = 0, height: h = 0, width: w = 0 } =
props.parentRef.current?.getBoundingClientRect() || {};
const {
x = 0,
y = 0,
height: h = 0,
width: w = 0,
} = props.parentRef.current?.getBoundingClientRect() || {};
const [mouseX, mouseY] = useMousePosition();
const positions = { x, y, h, w, mouseX, mouseY };
@@ -5,19 +5,14 @@ import NudeButton from "~/components/NudeButton";
type Props = React.ComponentProps<typeof MenuButton> & {
className?: string;
iconColor?: string;
};
export default function OverflowMenuButton({
iconColor,
className,
...rest
}: Props) {
export default function OverflowMenuButton({ className, ...rest }: Props) {
return (
<MenuButton {...rest}>
{(props) => (
<NudeButton className={className} {...props}>
<MoreIcon color={iconColor} />
<MoreIcon />
</NudeButton>
)}
</MenuButton>
+1 -1
View File
@@ -11,5 +11,5 @@ export default function Separator(rest: React.HTMLAttributes<HTMLHRElement>) {
}
const HorizontalRule = styled.hr`
margin: 0.5em 12px;
margin: 6px 0;
`;
+43 -32
View File
@@ -6,10 +6,11 @@ import {
useMenuState,
MenuButton,
MenuItem as BaseMenuItem,
MenuStateReturn,
} from "reakit/Menu";
import styled, { useTheme } from "styled-components";
import MenuIconWrapper from "~/components/ContextMenu/MenuIconWrapper";
import Flex from "~/components/Flex";
import MenuIconWrapper from "~/components/MenuIconWrapper";
import { actionToMenuItem } from "~/actions";
import useActionContext from "~/hooks/useActionContext";
import {
@@ -25,7 +26,7 @@ import MouseSafeArea from "./MouseSafeArea";
import Separator from "./Separator";
import ContextMenu from ".";
type Props = {
type Props = Omit<MenuStateReturn, "items"> & {
actions?: (Action | MenuSeparator | MenuHeading)[];
context?: Partial<ActionContext>;
items?: TMenuItem[];
@@ -37,36 +38,41 @@ const Disclosure = styled(ExpandedIcon)`
right: 8px;
`;
const Submenu = React.forwardRef(
(
{
templateItems,
title,
...rest
}: { templateItems: TMenuItem[]; title: React.ReactNode },
ref: React.LegacyRef<HTMLButtonElement>
) => {
const { t } = useTranslation();
const theme = useTheme();
const menu = useMenuState();
type SubMenuProps = MenuStateReturn & {
templateItems: TMenuItem[];
parentMenuState: Omit<MenuStateReturn, "items">;
title: React.ReactNode;
};
return (
<>
<MenuButton ref={ref} {...menu} {...rest}>
{(props) => (
<MenuAnchor disclosure {...props}>
{title} <Disclosure color={theme.textTertiary} />
</MenuAnchor>
)}
</MenuButton>
<ContextMenu {...menu} aria-label={t("Submenu")}>
<MouseSafeArea parentRef={menu.unstable_popoverRef} />
<Template {...menu} items={templateItems} />
</ContextMenu>
</>
);
}
);
const SubMenu = React.forwardRef(function _Template(
{ templateItems, title, parentMenuState, ...rest }: SubMenuProps,
ref: React.LegacyRef<HTMLButtonElement>
) {
const { t } = useTranslation();
const theme = useTheme();
const menu = useMenuState();
return (
<>
<MenuButton ref={ref} {...menu} {...rest}>
{(props) => (
<MenuAnchor disclosure {...props}>
{title} <Disclosure color={theme.textTertiary} />
</MenuAnchor>
)}
</MenuButton>
<ContextMenu
{...menu}
aria-label={t("Submenu")}
onClick={parentMenuState.hide}
parentMenuState={parentMenuState}
>
<MouseSafeArea parentRef={menu.unstable_popoverRef} />
<Template {...menu} items={templateItems} />
</ContextMenu>
</>
);
});
export function filterTemplateItems(items: TMenuItem[]): TMenuItem[] {
return items
@@ -127,6 +133,7 @@ function Template({ items, actions, context, ...menu }: Props) {
return (
<MenuItem
as={Link}
id={`${item.title}-${index}`}
to={item.to}
key={index}
disabled={item.disabled}
@@ -142,6 +149,7 @@ function Template({ items, actions, context, ...menu }: Props) {
if (item.type === "link") {
return (
<MenuItem
id={`${item.title}-${index}`}
href={item.href}
key={index}
disabled={item.disabled}
@@ -160,6 +168,7 @@ function Template({ items, actions, context, ...menu }: Props) {
return (
<MenuItem
as="button"
id={`${item.title}-${index}`}
onClick={item.onClick}
disabled={item.disabled}
selected={item.selected}
@@ -177,8 +186,10 @@ function Template({ items, actions, context, ...menu }: Props) {
return (
<BaseMenuItem
key={index}
as={Submenu}
as={SubMenu}
id={`${item.title}-${index}`}
templateItems={item.items}
parentMenuState={menu}
title={<Title title={item.title} icon={item.icon} />}
{...menu}
/>
+116 -78
View File
@@ -1,10 +1,10 @@
import { disableBodyScroll, enableBodyScroll } from "body-scroll-lock";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Menu } from "reakit/Menu";
import { Menu, MenuStateReturn } from "reakit/Menu";
import styled, { DefaultTheme } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { depths } from "@shared/styles";
import { depths, s } from "@shared/styles";
import Scrollable from "~/components/Scrollable";
import useMenuContext from "~/hooks/useMenuContext";
import useMenuHeight from "~/hooks/useMenuHeight";
@@ -36,30 +36,34 @@ export type Placement =
| "left"
| "left-start";
type Props = {
"aria-label": string;
visible?: boolean;
placement?: Placement;
animating?: boolean;
unstable_disclosureRef?: React.RefObject<HTMLElement | null>;
type Props = MenuStateReturn & {
"aria-label"?: string;
/** The parent menu state if this is a submenu. */
parentMenuState?: Omit<MenuStateReturn, "items">;
/** Called when the context menu is opened. */
onOpen?: () => void;
/** Called when the context menu is closed. */
onClose?: () => void;
hide?: () => void;
/** Called when the context menu is clicked. */
onClick?: (ev: React.MouseEvent) => void;
/** The maximum width of the context menu. */
maxWidth?: number;
children?: React.ReactNode;
};
const ContextMenu: React.FC<Props> = ({
children,
onOpen,
onClose,
parentMenuState,
...rest
}) => {
}: Props) => {
const previousVisible = usePrevious(rest.visible);
const maxHeight = useMenuHeight(rest.visible, rest.unstable_disclosureRef);
const backgroundRef = React.useRef<HTMLDivElement>(null);
const { ui } = useStores();
const { t } = useTranslation();
const { setIsMenuOpen } = useMenuContext();
const isMobile = useMobile();
const isSubMenu = !!parentMenuState;
useUnmount(() => {
setIsMenuOpen(false);
@@ -67,19 +71,17 @@ const ContextMenu: React.FC<Props> = ({
React.useEffect(() => {
if (rest.visible && !previousVisible) {
if (onOpen) {
onOpen();
}
if (rest["aria-label"] !== t("Submenu")) {
onOpen?.();
if (!isSubMenu) {
setIsMenuOpen(true);
}
}
if (!rest.visible && previousVisible) {
if (onClose) {
onClose();
}
if (rest["aria-label"] !== t("Submenu")) {
onClose?.();
if (!isSubMenu) {
setIsMenuOpen(false);
}
}
@@ -90,23 +92,10 @@ const ContextMenu: React.FC<Props> = ({
rest.visible,
ui.sidebarCollapsed,
setIsMenuOpen,
rest,
isSubMenu,
t,
]);
// We must manually manage scroll lock for iOS support so that the scrollable
// element can be passed into body-scroll-lock. See:
// https://github.com/ariakit/ariakit/issues/469
React.useEffect(() => {
const scrollElement = backgroundRef.current;
if (rest.visible && scrollElement) {
disableBodyScroll(scrollElement);
}
return () => {
scrollElement && enableBodyScroll(scrollElement);
};
}, [rest.visible]);
// Perf win don't render anything until the menu has been opened
if (!rest.visible && !previousVisible) {
return null;
@@ -117,51 +106,98 @@ const ContextMenu: React.FC<Props> = ({
return (
<>
<Menu hideOnClickOutside={!isMobile} preventBodyScroll={false} {...rest}>
{(props) => {
// kind of hacky, but this is an effective way of telling which way
// the menu will _actually_ be placed when taking into account screen
// positioning.
const topAnchor = props.style?.top === "0";
// @ts-expect-error ts-migrate(2339) FIXME: Property 'placement' does not exist on type 'Extra... Remove this comment to see the full error message
const rightAnchor = props.placement === "bottom-end";
return (
<>
{isMobile && (
<Backdrop
onClick={(ev) => {
ev.preventDefault();
ev.stopPropagation();
rest.hide?.();
}}
/>
)}
<Position {...props}>
<Background
dir="auto"
topAnchor={topAnchor}
rightAnchor={rightAnchor}
ref={backgroundRef}
hiddenScrollbars
style={
maxHeight && topAnchor
? {
maxHeight,
}
: undefined
}
>
{rest.visible || rest.animating ? children : null}
</Background>
</Position>
</>
);
}}
{(props) => (
<InnerContextMenu
// eslint-disable-next-line @typescript-eslint/no-explicit-any
menuProps={props as any}
{...rest}
isSubMenu={isSubMenu}
>
{children}
</InnerContextMenu>
)}
</Menu>
</>
);
};
type InnerContextMenuProps = MenuStateReturn & {
isSubMenu: boolean;
menuProps: { style?: React.CSSProperties; placement: string };
children: React.ReactNode;
maxWidth?: number;
};
/**
* Inner context menu allows deferring expensive window measurement hooks etc
* until the menu is actually opened.
*/
const InnerContextMenu = (props: InnerContextMenuProps) => {
const { menuProps } = props;
// kind of hacky, but this is an effective way of telling which way
// the menu will _actually_ be placed when taking into account screen
// positioning.
const topAnchor =
menuProps.style?.top === "0" || menuProps.style?.position === "fixed";
const rightAnchor = menuProps.placement === "bottom-end";
const backgroundRef = React.useRef<HTMLDivElement>(null);
const isMobile = useMobile();
const maxHeight = useMenuHeight({
visible: props.visible,
elementRef: props.unstable_disclosureRef,
});
// We must manually manage scroll lock for iOS support so that the scrollable
// element can be passed into body-scroll-lock. See:
// https://github.com/ariakit/ariakit/issues/469
React.useEffect(() => {
const scrollElement = backgroundRef.current;
if (props.visible && scrollElement && !props.isSubMenu) {
disableBodyScroll(scrollElement, {
reserveScrollBarGap: true,
});
}
return () => {
scrollElement && !props.isSubMenu && enableBodyScroll(scrollElement);
};
}, [props.isSubMenu, props.visible]);
const style =
topAnchor && !isMobile
? {
maxHeight,
}
: undefined;
return (
<>
{isMobile && (
<Backdrop
onClick={(ev) => {
ev.preventDefault();
ev.stopPropagation();
props.hide?.();
}}
/>
)}
<Position {...menuProps}>
<Background
dir="auto"
maxWidth={props.maxWidth}
topAnchor={topAnchor}
rightAnchor={rightAnchor}
ref={backgroundRef}
hiddenScrollbars
style={style}
>
{props.visible || props.animating ? props.children : null}
</Background>
</Position>
</>
);
};
export default ContextMenu;
export const Backdrop = styled.div`
@@ -171,7 +207,7 @@ export const Backdrop = styled.div`
left: 0;
right: 0;
bottom: 0;
background: ${(props) => props.theme.backdrop};
background: ${s("backdrop")};
z-index: ${depths.menu - 1};
`;
@@ -196,6 +232,7 @@ export const Position = styled.div`
type BackgroundProps = {
topAnchor?: boolean;
rightAnchor?: boolean;
maxWidth?: number;
theme: DefaultTheme;
};
@@ -203,9 +240,9 @@ export const Background = styled(Scrollable)<BackgroundProps>`
animation: ${mobileContextMenu} 200ms ease;
transform-origin: 50% 100%;
max-width: 100%;
background: ${(props) => props.theme.menuBackground};
background: ${s("menuBackground")};
border-radius: 6px;
padding: 6px 0;
padding: 6px;
min-width: 180px;
min-height: 44px;
max-height: 75vh;
@@ -221,7 +258,8 @@ export const Background = styled(Scrollable)<BackgroundProps>`
props.topAnchor ? fadeAndSlideDown : fadeAndSlideUp} 200ms ease;
transform-origin: ${(props: BackgroundProps) =>
props.rightAnchor ? "75%" : "25%"} 0;
max-width: 276px;
max-width: ${(props: BackgroundProps) => props.maxWidth ?? 276}px;
max-height: 100vh;
background: ${(props: BackgroundProps) => props.theme.menuBackground};
box-shadow: ${(props: BackgroundProps) => props.theme.menuShadow};
`};
@@ -1,13 +1,13 @@
import { HomeIcon } from "outline-icons";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { Optional } from "utility-types";
import CollectionIcon from "~/components/CollectionIcon";
import Flex from "~/components/Flex";
import CollectionIcon from "~/components/Icons/CollectionIcon";
import InputSelect from "~/components/InputSelect";
import { IconWrapper } from "~/components/Sidebar/components/SidebarLink";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
type DefaultCollectionInputSelectProps = Optional<
React.ComponentProps<typeof InputSelect>
@@ -25,10 +25,9 @@ const DefaultCollectionInputSelect = ({
const { collections } = useStores();
const [fetching, setFetching] = useState(false);
const [fetchError, setFetchError] = useState();
const { showToast } = useToasts();
React.useEffect(() => {
async function load() {
async function fetchData() {
if (!collections.isLoaded && !fetching && !fetchError) {
try {
setFetching(true);
@@ -36,11 +35,8 @@ const DefaultCollectionInputSelect = ({
limit: 100,
});
} catch (error) {
showToast(
t("Collections could not be loaded, please reload the app"),
{
type: "error",
}
toast.error(
t("Collections could not be loaded, please reload the app")
);
setFetchError(error);
} finally {
@@ -48,8 +44,8 @@ const DefaultCollectionInputSelect = ({
}
}
}
load();
}, [showToast, fetchError, t, fetching, collections]);
void fetchData();
}, [fetchError, t, fetching, collections]);
const options = React.useMemo(
() =>
@@ -73,7 +69,7 @@ const DefaultCollectionInputSelect = ({
label: (
<Flex align="center">
<IconWrapper>
<HomeIcon color="currentColor" />
<HomeIcon />
</IconWrapper>
{t("Home")}
</Flex>
+55
View File
@@ -0,0 +1,55 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { toast } from "sonner";
import KeyboardShortcuts from "~/scenes/KeyboardShortcuts";
import { useDesktopTitlebar } from "~/hooks/useDesktopTitlebar";
import useStores from "~/hooks/useStores";
import Desktop from "~/utils/Desktop";
export default function DesktopEventHandler() {
useDesktopTitlebar();
const { t } = useTranslation();
const history = useHistory();
const { dialogs } = useStores();
React.useEffect(() => {
Desktop.bridge?.redirect((path: string, replace = false) => {
if (replace) {
history.replace(path);
} else {
history.push(path);
}
});
Desktop.bridge?.updateDownloaded(() => {
toast.message("An update is ready to install.", {
duration: Infinity,
dismissible: true,
action: {
label: t("Install now"),
onClick: () => {
void Desktop.bridge?.restartAndInstall();
},
},
});
});
Desktop.bridge?.focus(() => {
window.document.body.classList.remove("backgrounded");
});
Desktop.bridge?.blur(() => {
window.document.body.classList.add("backgrounded");
});
Desktop.bridge?.openKeyboardShortcuts(() => {
dialogs.openGuide({
title: t("Keyboard shortcuts"),
content: <KeyboardShortcuts />,
});
});
}, [t, history, dialogs]);
return null;
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { observer } from "mobx-react-lite";
import { observer } from "mobx-react";
import * as React from "react";
import Guide from "~/components/Guide";
import Modal from "~/components/Modal";
+2 -1
View File
@@ -1,8 +1,9 @@
import styled from "styled-components";
import { s } from "@shared/styles";
const Divider = styled.hr`
border: 0;
border-bottom: 1px solid ${(props) => props.theme.divider};
border-bottom: 1px solid ${s("divider")};
margin: 0;
padding: 0;
`;
+45 -22
View File
@@ -3,14 +3,22 @@ import { ArchiveIcon, GoToIcon, ShapesIcon, TrashIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import type { NavigationNode } from "@shared/types";
import Document from "~/models/Document";
import Breadcrumb from "~/components/Breadcrumb";
import CollectionIcon from "~/components/CollectionIcon";
import CollectionIcon from "~/components/Icons/CollectionIcon";
import useStores from "~/hooks/useStores";
import { MenuInternalLink, NavigationNode } from "~/types";
import { collectionUrl } from "~/utils/routeHelpers";
import { MenuInternalLink } from "~/types";
import {
archivePath,
collectionPath,
settingsPath,
trashPath,
} from "~/utils/routeHelpers";
import EmojiIcon from "./Icons/EmojiIcon";
type Props = {
children?: React.ReactNode;
document: Document;
onlyText?: boolean;
};
@@ -21,27 +29,27 @@ function useCategory(document: Document): MenuInternalLink | null {
if (document.isDeleted) {
return {
type: "route",
icon: <TrashIcon color="currentColor" />,
icon: <TrashIcon />,
title: t("Trash"),
to: "/trash",
to: trashPath(),
};
}
if (document.isArchived) {
return {
type: "route",
icon: <ArchiveIcon color="currentColor" />,
icon: <ArchiveIcon />,
title: t("Archive"),
to: "/archive",
to: archivePath(),
};
}
if (document.isTemplate) {
if (document.template) {
return {
type: "route",
icon: <ShapesIcon color="currentColor" />,
icon: <ShapesIcon />,
title: t("Templates"),
to: "/templates",
to: settingsPath("templates"),
};
}
@@ -52,33 +60,36 @@ const DocumentBreadcrumb: React.FC<Props> = ({
document,
children,
onlyText,
}) => {
}: Props) => {
const { collections } = useStores();
const { t } = useTranslation();
const category = useCategory(document);
const collection = collections.get(document.collectionId);
const collection = document.collectionId
? collections.get(document.collectionId)
: undefined;
let collectionNode: MenuInternalLink;
let collectionNode: MenuInternalLink | undefined;
if (collection) {
collectionNode = {
type: "route",
title: collection.name,
icon: <CollectionIcon collection={collection} expanded />,
to: collectionUrl(collection.url),
to: collectionPath(collection.url),
};
} else {
} else if (document.collectionId && !collection) {
collectionNode = {
type: "route",
title: t("Deleted Collection"),
icon: undefined,
to: collectionUrl("deleted-collection"),
to: collectionPath("deleted-collection"),
};
}
const path = React.useMemo(
() => collection?.pathToDocument?.(document.id).slice(0, -1) || [],
[collection, document]
() => collection?.pathToDocument(document.id).slice(0, -1) || [],
// eslint-disable-next-line react-hooks/exhaustive-deps
[collection, document, document.collectionId, document.parentDocumentId]
);
const items = React.useMemo(() => {
@@ -88,12 +99,20 @@ const DocumentBreadcrumb: React.FC<Props> = ({
output.push(category);
}
output.push(collectionNode);
if (collectionNode) {
output.push(collectionNode);
}
path.forEach((node: NavigationNode) => {
output.push({
type: "route",
title: node.title,
title: node.emoji ? (
<>
<EmojiIcon emoji={node.emoji} /> {node.title}
</>
) : (
node.title
),
to: node.url,
});
});
@@ -118,7 +137,11 @@ const DocumentBreadcrumb: React.FC<Props> = ({
);
}
return <Breadcrumb items={items} children={children} highlightFirstItem />;
return (
<Breadcrumb items={items} highlightFirstItem>
{children}
</Breadcrumb>
);
};
const SmallSlash = styled(GoToIcon)`
@@ -127,7 +150,7 @@ const SmallSlash = styled(GoToIcon)`
vertical-align: middle;
flex-shrink: 0;
fill: ${(props) => props.theme.slate};
fill: ${(props) => props.theme.textTertiary};
opacity: 0.5;
`;
+29 -26
View File
@@ -7,14 +7,16 @@ import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import styled, { useTheme } from "styled-components";
import { s, ellipsis } from "@shared/styles";
import Document from "~/models/Document";
import Pin from "~/models/Pin";
import Flex from "~/components/Flex";
import NudeButton from "~/components/NudeButton";
import Time from "~/components/Time";
import useStores from "~/hooks/useStores";
import CollectionIcon from "./CollectionIcon";
import EmojiIcon from "./EmojiIcon";
import { hover } from "~/styles";
import CollectionIcon from "./Icons/CollectionIcon";
import EmojiIcon from "./Icons/EmojiIcon";
import Squircle from "./Squircle";
import Text from "./Text";
import Tooltip from "./Tooltip";
@@ -35,7 +37,9 @@ function DocumentCard(props: Props) {
const { collections } = useStores();
const theme = useTheme();
const { document, pin, canUpdatePin, isDraggable } = props;
const collection = collections.get(document.collectionId);
const collection = document.collectionId
? collections.get(document.collectionId)
: undefined;
const {
attributes,
listeners,
@@ -54,10 +58,10 @@ function DocumentCard(props: Props) {
};
const handleUnpin = React.useCallback(
(ev) => {
async (ev) => {
ev.preventDefault();
ev.stopPropagation();
pin?.delete();
await pin?.delete();
},
[pin]
);
@@ -107,11 +111,12 @@ function DocumentCard(props: Props) {
{document.emoji ? (
<Squircle color={theme.slateLight}>
<EmojiIcon emoji={document.emoji} size={26} />
<EmojiIcon emoji={document.emoji} size={24} />
</Squircle>
) : (
<Squircle color={collection?.color}>
{collection?.icon &&
collection?.icon !== "letter" &&
collection?.icon !== "collection" &&
!pin?.collectionId ? (
<CollectionIcon collection={collection} color="white" />
@@ -127,7 +132,7 @@ function DocumentCard(props: Props) {
: document.titleWithDefault}
</Heading>
<DocumentMeta size="xsmall">
<Clock color="currentColor" size={18} />
<Clock size={18} />
<Time
dateTime={document.updatedAt}
tooltipDelay={500}
@@ -142,7 +147,7 @@ function DocumentCard(props: Props) {
{!isDragging && pin && (
<Tooltip tooltip={t("Unpin")}>
<PinButton onClick={handleUnpin} aria-label={t("Unpin")}>
<CloseIcon color="currentColor" />
<CloseIcon />
</PinButton>
</Tooltip>
)}
@@ -164,9 +169,9 @@ const AnimatePresence = styled(m.div)`
`;
const Fold = styled.svg`
fill: ${(props) => props.theme.background};
stroke: ${(props) => props.theme.inputBorder};
background: ${(props) => props.theme.background};
fill: ${s("background")};
stroke: ${s("inputBorder")};
background: ${s("background")};
position: absolute;
top: -1px;
@@ -174,11 +179,11 @@ const Fold = styled.svg`
`;
const PinButton = styled(NudeButton)`
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
&:hover,
&:${hover},
&:active {
color: ${(props) => props.theme.text};
color: ${s("text")};
}
`;
@@ -188,7 +193,7 @@ const Actions = styled(Flex)`
right: ${(props) => (props.dir === "rtl" ? "auto" : "4px")};
left: ${(props) => (props.dir === "rtl" ? "4px" : "auto")};
opacity: 0;
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
// move actions above content
z-index: 2;
@@ -206,7 +211,7 @@ const Reorderable = styled.div<{ $isDragging: boolean }>`
z-index: ${(props) => (props.$isDragging ? 1 : "inherit")};
pointer-events: ${(props) => (props.$isDragging ? "none" : "inherit")};
&:hover ${Actions} {
&: ${hover} ${Actions} {
opacity: 1;
}
`;
@@ -217,14 +222,12 @@ const Content = styled(Flex)`
`;
const DocumentMeta = styled(Text)`
${ellipsis()}
display: flex;
align-items: center;
gap: 2px;
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
margin: 0 0 0 -2px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
`;
const DocumentLink = styled(Link)<{
@@ -237,9 +240,9 @@ const DocumentLink = styled(Link)<{
height: 100%;
border-radius: 8px;
cursor: var(--pointer);
background: ${(props) => props.theme.background};
background: ${s("background")};
transition: transform 50ms ease-in-out;
border: 1px solid ${(props) => props.theme.inputBorder};
border: 1px solid ${s("inputBorder")};
border-bottom-width: 2px;
border-right-width: 2px;
@@ -247,7 +250,7 @@ const DocumentLink = styled(Link)<{
opacity: 0;
}
&:hover,
&:${hover},
&:active,
&:focus,
&:focus-within {
@@ -276,9 +279,9 @@ const Heading = styled.h3`
max-height: 66px; // 3*line-height
overflow: hidden;
color: ${(props) => props.theme.text};
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
color: ${s("text")};
font-family: ${s("fontFamily")};
font-weight: 500;
`;
export default observer(DocumentCard);
+37
View File
@@ -0,0 +1,37 @@
import * as React from "react";
import { Editor } from "~/editor";
import useIdle from "~/hooks/useIdle";
export type DocumentContextValue = {
/** The current editor instance for this document. */
editor: Editor | null;
/** Set the current editor instance for this document. */
setEditor: (editor: Editor) => void;
};
const DocumentContext = React.createContext<DocumentContextValue>({
editor: null,
// eslint-disable-next-line @typescript-eslint/no-empty-function
setEditor() {},
});
export const useDocumentContext = () => React.useContext(DocumentContext);
const activityEvents = [
"click",
"mousemove",
"DOMMouseScroll",
"mousewheel",
"mousedown",
"touchstart",
"touchmove",
"focus",
];
export const useEditingFocus = () => {
const { editor } = useDocumentContext();
const isIdle = useIdle(3000, activityEvents);
return isIdle && !!editor?.view.hasFocus();
};
export default DocumentContext;
+425
View File
@@ -0,0 +1,425 @@
import FuzzySearch from "fuzzy-search";
import concat from "lodash/concat";
import difference from "lodash/difference";
import fill from "lodash/fill";
import filter from "lodash/filter";
import includes from "lodash/includes";
import map from "lodash/map";
import { observer } from "mobx-react";
import { StarredIcon, DocumentIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import AutoSizer from "react-virtualized-auto-sizer";
import { FixedSizeList as List } from "react-window";
import scrollIntoView from "smooth-scroll-into-view-if-needed";
import styled, { useTheme } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { NavigationNode } from "@shared/types";
import DocumentExplorerNode from "~/components/DocumentExplorerNode";
import DocumentExplorerSearchResult from "~/components/DocumentExplorerSearchResult";
import Flex from "~/components/Flex";
import CollectionIcon from "~/components/Icons/CollectionIcon";
import EmojiIcon from "~/components/Icons/EmojiIcon";
import { Outline } from "~/components/Input";
import InputSearch from "~/components/InputSearch";
import Text from "~/components/Text";
import useMobile from "~/hooks/useMobile";
import useStores from "~/hooks/useStores";
import { isModKey } from "~/utils/keyboard";
import { ancestors, descendants } from "~/utils/tree";
type Props = {
/** Action taken upon submission of selected item, could be publish, move etc. */
onSubmit: () => void;
/** A side-effect of item selection */
onSelect: (item: NavigationNode | null) => void;
/** Items to be shown in explorer */
items: NavigationNode[];
};
function DocumentExplorer({ onSubmit, onSelect, items }: Props) {
const isMobile = useMobile();
const { collections, documents } = useStores();
const { t } = useTranslation();
const theme = useTheme();
const [searchTerm, setSearchTerm] = React.useState<string>();
const [selectedNode, selectNode] = React.useState<NavigationNode | null>(
null
);
const [initialScrollOffset, setInitialScrollOffset] =
React.useState<number>(0);
const [activeNode, setActiveNode] = React.useState<number>(0);
const [expandedNodes, setExpandedNodes] = React.useState<string[]>([]);
const [itemRefs, setItemRefs] = React.useState<
React.RefObject<HTMLSpanElement>[]
>([]);
const inputSearchRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(
null
);
const listRef = React.useRef<List<NavigationNode[]>>(null);
const VERTICAL_PADDING = 6;
const HORIZONTAL_PADDING = 24;
const searchIndex = React.useMemo(
() =>
new FuzzySearch(items, ["title"], {
caseSensitive: false,
}),
[items]
);
React.useEffect(() => {
if (searchTerm) {
selectNode(null);
setExpandedNodes([]);
}
setActiveNode(0);
}, [searchTerm]);
React.useEffect(() => {
setItemRefs((itemRefs) =>
map(
fill(Array(items.length), 0),
(_, i) => itemRefs[i] || React.createRef()
)
);
}, [items.length]);
React.useEffect(() => {
onSelect(selectedNode);
}, [selectedNode, onSelect]);
function getNodes() {
function includeDescendants(item: NavigationNode): NavigationNode[] {
return expandedNodes.includes(item.id)
? [item, ...descendants(item, 1).flatMap(includeDescendants)]
: [item];
}
return searchTerm
? searchIndex.search(searchTerm)
: items
.filter((item) => item.type === "collection")
.flatMap(includeDescendants);
}
const nodes = getNodes();
const scrollNodeIntoView = React.useCallback(
(node: number) => {
if (itemRefs[node] && itemRefs[node].current) {
scrollIntoView(itemRefs[node].current as HTMLSpanElement, {
behavior: "auto",
block: "center",
});
}
},
[itemRefs]
);
const handleSearch = (ev: React.ChangeEvent<HTMLInputElement>) => {
setSearchTerm(ev.target.value);
};
const isExpanded = (node: number) => includes(expandedNodes, nodes[node].id);
const calculateInitialScrollOffset = (itemCount: number) => {
if (listRef.current) {
const { height, itemSize } = listRef.current.props;
const { scrollOffset } = listRef.current.state as {
scrollOffset: number;
};
const itemsHeight = itemCount * itemSize;
return itemsHeight < Number(height) ? 0 : scrollOffset;
}
return 0;
};
const collapse = (node: number) => {
const descendantIds = descendants(nodes[node]).map((des) => des.id);
setExpandedNodes(
difference(expandedNodes, [...descendantIds, nodes[node].id])
);
// remove children
const newNodes = filter(nodes, (node) => !includes(descendantIds, node.id));
const scrollOffset = calculateInitialScrollOffset(newNodes.length);
setInitialScrollOffset(scrollOffset);
};
const expand = (node: number) => {
setExpandedNodes(concat(expandedNodes, nodes[node].id));
// add children
const newNodes = nodes.slice();
newNodes.splice(node + 1, 0, ...descendants(nodes[node], 1));
const scrollOffset = calculateInitialScrollOffset(newNodes.length);
setInitialScrollOffset(scrollOffset);
};
React.useEffect(() => {
collections.orderedData
.filter(
(collection) => expandedNodes.includes(collection.id) || searchTerm
)
.forEach((collection) => {
void collection.fetchDocuments();
});
}, [collections, expandedNodes, searchTerm]);
const isSelected = (node: number) => {
if (!selectedNode) {
return false;
}
const selectedNodeId = selectedNode.id;
const nodeId = nodes[node].id;
return selectedNodeId === nodeId;
};
const hasChildren = (node: number) =>
nodes[node].children.length > 0 || nodes[node].type === "collection";
const toggleCollapse = (node: number) => {
if (!hasChildren(node)) {
return;
}
if (isExpanded(node)) {
collapse(node);
} else {
expand(node);
}
};
const toggleSelect = (node: number) => {
if (isSelected(node)) {
selectNode(null);
} else {
selectNode(nodes[node]);
}
};
const ListItem = observer(
({
index,
data,
style,
}: {
index: number;
data: NavigationNode[];
style: React.CSSProperties;
}) => {
const node = data[index];
const isCollection = node.type === "collection";
let icon, title: string, emoji: string | undefined, path;
if (isCollection) {
const col = collections.get(node.collectionId as string);
icon = col && (
<CollectionIcon collection={col} expanded={isExpanded(index)} />
);
title = node.title;
} else {
const doc = documents.get(node.id);
emoji = doc?.emoji ?? node.emoji;
title = doc?.title ?? node.title;
if (emoji) {
icon = <EmojiIcon emoji={emoji} />;
} else if (doc?.isStarred) {
icon = <StarredIcon color={theme.yellow} />;
} else {
icon = <DocumentIcon color={theme.textSecondary} />;
}
path = ancestors(node)
.map((a) => a.title)
.join(" / ");
}
return searchTerm ? (
<DocumentExplorerSearchResult
selected={isSelected(index)}
active={activeNode === index}
style={{
...style,
top: (style.top as number) + VERTICAL_PADDING,
left: (style.left as number) + HORIZONTAL_PADDING,
width: `calc(${style.width} - ${HORIZONTAL_PADDING * 2}px)`,
}}
onPointerMove={() => setActiveNode(index)}
onClick={() => toggleSelect(index)}
icon={icon}
title={title}
path={path}
/>
) : (
<DocumentExplorerNode
style={{
...style,
top: (style.top as number) + VERTICAL_PADDING,
left: (style.left as number) + HORIZONTAL_PADDING,
width: `calc(${style.width} - ${HORIZONTAL_PADDING * 2}px)`,
}}
onPointerMove={() => setActiveNode(index)}
onClick={() => toggleSelect(index)}
onDisclosureClick={(ev) => {
ev.stopPropagation();
toggleCollapse(index);
}}
selected={isSelected(index)}
active={activeNode === index}
expanded={isExpanded(index)}
icon={icon}
title={title}
depth={node.depth as number}
hasChildren={hasChildren(index)}
ref={itemRefs[index]}
/>
);
}
);
const focusSearchInput = () => {
inputSearchRef.current?.focus();
};
const next = () => Math.min(activeNode + 1, nodes.length - 1);
const prev = () => Math.max(activeNode - 1, 0);
const handleKeyDown = (ev: React.KeyboardEvent<HTMLDivElement>) => {
switch (ev.key) {
case "ArrowDown": {
ev.preventDefault();
ev.stopPropagation();
setActiveNode(next());
scrollNodeIntoView(next());
break;
}
case "ArrowUp": {
ev.preventDefault();
ev.stopPropagation();
if (activeNode === 0) {
focusSearchInput();
} else {
setActiveNode(prev());
scrollNodeIntoView(prev());
}
break;
}
case "ArrowLeft": {
if (!searchTerm && isExpanded(activeNode)) {
toggleCollapse(activeNode);
}
break;
}
case "ArrowRight": {
if (!searchTerm) {
toggleCollapse(activeNode);
// let the nodes re-render first and then scroll
setTimeout(() => scrollNodeIntoView(activeNode), 0);
}
break;
}
case "Enter": {
if (isModKey(ev)) {
onSubmit();
} else {
toggleSelect(activeNode);
}
break;
}
}
};
const innerElementType = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(function innerElementType(
{ style, ...rest }: React.HTMLAttributes<HTMLDivElement>,
ref
) {
return (
<div
ref={ref}
style={{
...style,
height: `${parseFloat(style?.height + "") + VERTICAL_PADDING * 2}px`,
}}
{...rest}
/>
);
});
return (
<Container tabIndex={-1} onKeyDown={handleKeyDown}>
<ListSearch
ref={inputSearchRef}
onChange={handleSearch}
placeholder={`${t("Search collections & documents")}`}
autoFocus
/>
<ListContainer>
{nodes.length ? (
<AutoSizer>
{({ width, height }: { width: number; height: number }) => (
<Flex role="listbox" column>
<List
ref={listRef}
key={nodes.length}
width={width}
height={height}
itemData={nodes}
itemCount={nodes.length}
itemSize={isMobile ? 48 : 32}
innerElementType={innerElementType}
initialScrollOffset={initialScrollOffset}
itemKey={(index, results) => results[index].id}
>
{ListItem}
</List>
</Flex>
)}
</AutoSizer>
) : (
<FlexContainer>
<Text type="secondary">{t("No results found")}.</Text>
</FlexContainer>
)}
</ListContainer>
</Container>
);
}
const Container = styled.div``;
const FlexContainer = styled(Flex)`
height: 100%;
align-items: center;
justify-content: center;
`;
const ListSearch = styled(InputSearch)`
${Outline} {
border-radius: 16px;
}
margin-bottom: 4px;
padding-left: 24px;
padding-right: 24px;
`;
const ListContainer = styled.div`
height: 65vh;
${breakpoint("tablet")`
height: 40vh;
`}
`;
export default observer(DocumentExplorer);
+133
View File
@@ -0,0 +1,133 @@
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { s, ellipsis } from "@shared/styles";
import Flex from "~/components/Flex";
import Disclosure from "~/components/Sidebar/components/Disclosure";
import Text from "~/components/Text";
type Props = {
selected: boolean;
active: boolean;
style: React.CSSProperties;
expanded: boolean;
icon?: React.ReactNode;
title: string;
depth: number;
hasChildren: boolean;
onDisclosureClick: (ev: React.MouseEvent) => void;
onPointerMove: (ev: React.MouseEvent) => void;
onClick: (ev: React.MouseEvent) => void;
};
function DocumentExplorerNode(
{
selected,
active,
style,
expanded,
icon,
title,
depth,
hasChildren,
onDisclosureClick,
onPointerMove,
onClick,
}: Props,
ref: React.RefObject<HTMLSpanElement>
) {
const { t } = useTranslation();
const OFFSET = 12;
const ICON_SIZE = 24;
const width = depth ? depth * ICON_SIZE + OFFSET : ICON_SIZE;
return (
<Node
ref={ref}
selected={selected}
active={active}
onClick={onClick}
style={style}
onPointerMove={onPointerMove}
role="option"
>
<Spacer width={width}>
{hasChildren && (
<StyledDisclosure
expanded={expanded}
onClick={onDisclosureClick}
tabIndex={-1}
/>
)}
</Spacer>
{icon}
<Title>{title || t("Untitled")}</Title>
</Node>
);
}
const Title = styled(Text)`
${ellipsis()}
margin: 0 4px 0 4px;
color: inherit;
`;
const StyledDisclosure = styled(Disclosure)`
position: relative;
left: auto;
margin-top: 2px;
`;
const Spacer = styled(Flex)<{ width: number }>`
flex-direction: row-reverse;
flex-shrink: 0;
width: ${(props) => props.width}px;
`;
export const Node = styled.span<{
active: boolean;
selected: boolean;
style: React.CSSProperties;
}>`
display: flex;
user-select: none;
overflow: hidden;
font-size: 16px;
width: ${(props) => props.style.width};
color: ${s("text")};
cursor: var(--pointer);
padding: 12px;
border-radius: 6px;
background: ${(props) =>
!props.selected && props.active && props.theme.listItemHoverBackground};
svg {
flex-shrink: 0;
}
&:focus {
outline: none;
}
${(props) =>
props.selected &&
`
background: ${props.theme.accent};
color: ${props.theme.white};
svg {
fill: ${props.theme.white};
}
`}
${breakpoint("tablet")`
padding: 4px;
font-size: 15px;
`}
`;
export default observer(React.forwardRef(DocumentExplorerNode));
@@ -0,0 +1,84 @@
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import scrollIntoView from "smooth-scroll-into-view-if-needed";
import styled from "styled-components";
import { ellipsis } from "@shared/styles";
import { Node as SearchResult } from "~/components/DocumentExplorerNode";
import Flex from "~/components/Flex";
import Text from "~/components/Text";
type Props = {
selected: boolean;
active: boolean;
style: React.CSSProperties;
icon?: React.ReactNode;
title: string;
path?: string;
onPointerMove: (ev: React.MouseEvent) => void;
onClick: (ev: React.MouseEvent) => void;
};
function DocumentExplorerSearchResult({
selected,
active,
style,
icon,
title,
path,
onPointerMove,
onClick,
}: Props) {
const { t } = useTranslation();
const ref = React.useCallback(
(node: HTMLSpanElement | null) => {
if (active && node) {
scrollIntoView(node, {
scrollMode: "if-needed",
behavior: "auto",
block: "nearest",
});
}
},
[active]
);
return (
<SearchResult
ref={ref}
selected={selected}
active={active}
onClick={onClick}
style={style}
onPointerMove={onPointerMove}
role="option"
>
{icon}
<Flex>
<Title>{title || t("Untitled")}</Title>
<Path $selected={selected} size="xsmall">
{path}
</Path>
</Flex>
</SearchResult>
);
}
const Title = styled(Text)`
flex-shrink: 0;
white-space: nowrap;
margin: 0 4px 0 4px;
color: inherit;
`;
const Path = styled(Text)<{ $selected: boolean }>`
${ellipsis()}
padding-top: 2px;
margin: 0 4px 0 8px;
color: ${(props) =>
props.$selected ? props.theme.white50 : props.theme.textTertiary};
`;
export default observer(DocumentExplorerSearchResult);
-158
View File
@@ -1,158 +0,0 @@
import { m } from "framer-motion";
import { observer } from "mobx-react";
import { CloseIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { useHistory, useRouteMatch } from "react-router-dom";
import styled, { useTheme } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import Event from "~/models/Event";
import Button from "~/components/Button";
import Empty from "~/components/Empty";
import Flex from "~/components/Flex";
import PaginatedEventList from "~/components/PaginatedEventList";
import Scrollable from "~/components/Scrollable";
import useKeyDown from "~/hooks/useKeyDown";
import useStores from "~/hooks/useStores";
import { documentUrl } from "~/utils/routeHelpers";
const EMPTY_ARRAY: Event[] = [];
function DocumentHistory() {
const { events, documents } = useStores();
const { t } = useTranslation();
const match = useRouteMatch<{ documentSlug: string }>();
const history = useHistory();
const theme = useTheme();
const document = documents.getByUrl(match.params.documentSlug);
const eventsInDocument = document
? events.inDocument(document.id)
: EMPTY_ARRAY;
const onCloseHistory = () => {
if (document) {
history.push(documentUrl(document));
} else {
history.goBack();
}
};
const items = React.useMemo(() => {
if (
eventsInDocument[0] &&
document &&
eventsInDocument[0].createdAt !== document.updatedAt
) {
eventsInDocument.unshift(
new Event(
{
id: "live",
name: "documents.live_editing",
documentId: document.id,
createdAt: document.updatedAt,
actor: document.updatedBy,
},
events
)
);
}
return eventsInDocument;
}, [eventsInDocument, events, document]);
useKeyDown("Escape", onCloseHistory);
return (
<Sidebar
initial={{
width: 0,
}}
animate={{
transition: {
type: "spring",
bounce: 0.2,
duration: 0.6,
},
width: theme.sidebarWidth,
}}
exit={{
width: 0,
}}
>
{document ? (
<Position column>
<Header>
<Title>{t("History")}</Title>
<Button
icon={<CloseIcon />}
onClick={onCloseHistory}
borderOnHover
neutral
/>
</Header>
<Scrollable topShadow>
<PaginatedEventList
aria-label={t("History")}
fetch={events.fetchPage}
events={items}
options={{
documentId: document.id,
}}
document={document}
empty={<EmptyHistory>{t("No history yet")}</EmptyHistory>}
/>
</Scrollable>
</Position>
) : null}
</Sidebar>
);
}
const EmptyHistory = styled(Empty)`
padding: 0 12px;
`;
const Position = styled(Flex)`
position: fixed;
top: 0;
bottom: 0;
width: ${(props) => props.theme.sidebarWidth}px;
`;
const Sidebar = styled(m.div)`
display: none;
position: relative;
flex-shrink: 0;
background: ${(props) => props.theme.background};
width: ${(props) => props.theme.sidebarWidth}px;
border-left: 1px solid ${(props) => props.theme.divider};
z-index: 1;
${breakpoint("tablet")`
display: flex;
`};
`;
const Title = styled(Flex)`
font-size: 16px;
font-weight: 600;
text-align: center;
align-items: center;
justify-content: flex-start;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
width: 0;
flex-grow: 1;
`;
const Header = styled(Flex)`
align-items: center;
position: relative;
padding: 16px 12px;
color: ${(props) => props.theme.text};
flex-shrink: 0;
`;
export default observer(DocumentHistory);
+20 -40
View File
@@ -1,14 +1,13 @@
import { observer } from "mobx-react";
import { PlusIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { CompositeStateReturn, CompositeItem } from "reakit/Composite";
import styled, { css } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { s } from "@shared/styles";
import Document from "~/models/Document";
import Badge from "~/components/Badge";
import Button from "~/components/Button";
import DocumentMeta from "~/components/DocumentMeta";
import EventBoundary from "~/components/EventBoundary";
import Flex from "~/components/Flex";
@@ -17,12 +16,11 @@ import NudeButton from "~/components/NudeButton";
import StarButton, { AnimatedStar } from "~/components/Star";
import Tooltip from "~/components/Tooltip";
import useBoolean from "~/hooks/useBoolean";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import useCurrentUser from "~/hooks/useCurrentUser";
import usePolicy from "~/hooks/usePolicy";
import DocumentMenu from "~/menus/DocumentMenu";
import { hover } from "~/styles";
import { newDocumentPath } from "~/utils/routeHelpers";
import { documentPath } from "~/utils/routeHelpers";
import EmojiIcon from "./Icons/EmojiIcon";
type Props = {
document: Document;
@@ -50,7 +48,6 @@ function DocumentListItem(
) {
const { t } = useTranslation();
const user = useCurrentUser();
const team = useCurrentTeam();
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
const {
@@ -70,8 +67,6 @@ function DocumentListItem(
!!document.title.toLowerCase().includes(highlight.toLowerCase());
const canStar =
!document.isDraft && !document.isArchived && !document.isTemplate;
const can = usePolicy(team);
const canCollection = usePolicy(document.collectionId);
return (
<CompositeItem
@@ -82,7 +77,7 @@ function DocumentListItem(
$isStarred={document.isStarred}
$menuOpen={menuOpen}
to={{
pathname: document.url,
pathname: documentPath(document),
state: {
title: document.titleWithDefault,
},
@@ -91,6 +86,12 @@ function DocumentListItem(
>
<Content>
<Heading dir={document.dir}>
{document.emoji && (
<>
<EmojiIcon emoji={document.emoji} size={24} />
&nbsp;
</>
)}
<Title
text={document.titleWithDefault}
highlight={highlight}
@@ -134,25 +135,6 @@ function DocumentListItem(
/>
</Content>
<Actions>
{document.isTemplate &&
!document.isArchived &&
!document.isDeleted &&
can.createDocument &&
canCollection.update && (
<>
<Button
as={Link}
to={newDocumentPath(document.collectionId, {
templateId: document.id,
})}
icon={<PlusIcon />}
neutral
>
{t("New doc")}
</Button>
&nbsp;
</>
)}
<DocumentMenu
document={document}
showPin={showPin}
@@ -177,11 +159,11 @@ const Actions = styled(EventBoundary)`
margin: 8px;
flex-shrink: 0;
flex-grow: 0;
color: ${s("textSecondary")};
${NudeButton} {
&:hover,
&[aria-expanded="true"] {
background: ${(props) => props.theme.sidebarControlHoverBackground};
&: ${hover}, &[aria-expanded= "true"] {
background: ${s("sidebarControlHoverBackground")};
}
}
@@ -223,7 +205,7 @@ const DocumentLink = styled(Link)<{
&:active,
&:focus,
&:focus-within {
background: ${(props) => props.theme.listItemHoverBackground};
background: ${s("listItemHoverBackground")};
${Actions} {
opacity: 1;
@@ -232,7 +214,7 @@ const DocumentLink = styled(Link)<{
${AnimatedStar} {
opacity: 0.5;
&:hover {
&:${hover} {
opacity: 1;
}
}
@@ -241,7 +223,7 @@ const DocumentLink = styled(Link)<{
${(props) =>
props.$menuOpen &&
css`
background: ${(props) => props.theme.listItemHoverBackground};
background: ${s("listItemHoverBackground")};
${Actions} {
opacity: 1;
@@ -257,14 +239,12 @@ const Heading = styled.h3<{ rtl?: boolean }>`
display: flex;
justify-content: ${(props) => (props.rtl ? "flex-end" : "flex-start")};
align-items: center;
height: 24px;
margin-top: 0;
margin-bottom: 0.25em;
overflow: hidden;
white-space: nowrap;
color: ${(props) => props.theme.text};
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
color: ${s("text")};
font-family: ${s("fontFamily")};
font-weight: 500;
`;
const StarPositioner = styled(Flex)`
@@ -280,7 +260,7 @@ const Title = styled(Highlight)`
const ResultContext = styled(Highlight)`
display: block;
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
font-size: 14px;
margin-top: -0.25em;
margin-bottom: 0.25em;
+21 -6
View File
@@ -4,7 +4,9 @@ import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import styled from "styled-components";
import { s, ellipsis } from "@shared/styles";
import Document from "~/models/Document";
import Revision from "~/models/Revision";
import DocumentBreadcrumb from "~/components/DocumentBreadcrumb";
import DocumentTasks from "~/components/DocumentTasks";
import Flex from "~/components/Flex";
@@ -13,11 +15,13 @@ import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
type Props = {
children?: React.ReactNode;
showCollection?: boolean;
showPublished?: boolean;
showLastViewed?: boolean;
showParentDocuments?: boolean;
document: Document;
revision?: Revision;
replace?: boolean;
to?: LocationDescriptor;
};
@@ -28,11 +32,12 @@ const DocumentMeta: React.FC<Props> = ({
showLastViewed,
showParentDocuments,
document,
revision,
children,
replace,
to,
...rest
}) => {
}: Props) => {
const { t } = useTranslation();
const { collections } = useStores();
const user = useCurrentUser();
@@ -56,12 +61,23 @@ const DocumentMeta: React.FC<Props> = ({
return null;
}
const collection = collections.get(document.collectionId);
const collection = document.collectionId
? collections.get(document.collectionId)
: undefined;
const lastUpdatedByCurrentUser = user.id === updatedBy.id;
const userName = updatedBy.name;
let content;
if (deletedAt) {
if (revision) {
content = (
<span>
{revision.createdBy?.id === user.id
? t("You updated")
: t("{{ userName }} updated", { userName })}{" "}
<Time dateTime={revision.createdAt} addSuffix />
</span>
);
} else if (deletedAt) {
content = (
<span>
{lastUpdatedByCurrentUser
@@ -184,7 +200,7 @@ const DocumentMeta: React.FC<Props> = ({
const Container = styled(Flex)<{ rtl?: boolean }>`
justify-content: ${(props) => (props.rtl ? "flex-end" : "flex-start")};
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
font-size: 13px;
white-space: nowrap;
overflow: hidden;
@@ -192,8 +208,7 @@ const Container = styled(Flex)<{ rtl?: boolean }>`
`;
const Viewed = styled.span`
text-overflow: ellipsis;
overflow: hidden;
${ellipsis()}
`;
const Modified = styled.span<{ highlight?: boolean }>`
-79
View File
@@ -1,79 +0,0 @@
import { LocationDescriptor } from "history";
import { observer, useObserver } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { usePopoverState, PopoverDisclosure } from "reakit/Popover";
import styled from "styled-components";
import Document from "~/models/Document";
import DocumentMeta from "~/components/DocumentMeta";
import DocumentViews from "~/components/DocumentViews";
import Popover from "~/components/Popover";
import useStores from "~/hooks/useStores";
type Props = {
document: Document;
isDraft: boolean;
to?: LocationDescriptor;
rtl?: boolean;
};
function DocumentMetaWithViews({ to, isDraft, document, ...rest }: Props) {
const { views } = useStores();
const { t } = useTranslation();
const documentViews = useObserver(() => views.inDocument(document.id));
const totalViewers = documentViews.length;
const onlyYou = totalViewers === 1 && documentViews[0].user.id;
const popover = usePopoverState({
gutter: 8,
placement: "bottom",
modal: true,
});
return (
<Meta document={document} to={to} replace {...rest}>
{totalViewers && !isDraft ? (
<PopoverDisclosure {...popover}>
{(props) => (
<>
&nbsp;&nbsp;
<a {...props}>
{t("Viewed by")}{" "}
{onlyYou
? t("only you")
: `${totalViewers} ${
totalViewers === 1 ? t("person") : t("people")
}`}
</a>
</>
)}
</PopoverDisclosure>
) : null}
<Popover {...popover} width={300} aria-label={t("Viewers")} tabIndex={0}>
<DocumentViews document={document} isOpen={popover.visible} />
</Popover>
</Meta>
);
}
const Meta = styled(DocumentMeta)<{ rtl?: boolean }>`
justify-content: ${(props) => (props.rtl ? "flex-end" : "flex-start")};
margin: -12px 0 2em 0;
font-size: 14px;
position: relative;
z-index: 1;
a {
color: inherit;
&:hover {
text-decoration: underline;
}
}
@media print {
display: none;
}
`;
export default observer(DocumentMetaWithViews);
+3 -2
View File
@@ -1,7 +1,8 @@
import { TFunction } from "i18next";
import { observer } from "mobx-react";
import { DoneIcon } from "outline-icons";
import * as React from "react";
import { useTranslation, TFunction } from "react-i18next";
import { useTranslation } from "react-i18next";
import styled, { useTheme } from "styled-components";
import Document from "~/models/Document";
import CircularProgressBar from "~/components/CircularProgressBar";
@@ -43,7 +44,7 @@ function DocumentTasks({ document }: Props) {
<>
{completed === total ? (
<Done
color={theme.primary}
color={theme.accent}
size={20}
$animated={done && previousDone === false}
/>
+5 -8
View File
@@ -3,10 +3,10 @@ import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import { useHistory } from "react-router-dom";
import { toast } from "sonner";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
import { documentUrl } from "~/utils/routeHelpers";
import { documentPath } from "~/utils/routeHelpers";
type Props = {
documentId: string;
@@ -14,7 +14,6 @@ type Props = {
function DocumentTemplatizeDialog({ documentId }: Props) {
const history = useHistory();
const { showToast } = useToasts();
const { t } = useTranslation();
const { documents } = useStores();
const document = documents.get(documentId);
@@ -23,12 +22,10 @@ function DocumentTemplatizeDialog({ documentId }: Props) {
const handleSubmit = React.useCallback(async () => {
const template = await document?.templatize();
if (template) {
history.push(documentUrl(template));
showToast(t("Template created, go ahead and customize it"), {
type: "info",
});
history.push(documentPath(template));
toast.success(t("Template created, go ahead and customize it"));
}
}, [document, showToast, history, t]);
}, [document, history, t]);
return (
<ConfirmationDialog
+26 -16
View File
@@ -1,13 +1,15 @@
import { formatDistanceToNow } from "date-fns";
import { sortBy } from "lodash";
import compact from "lodash/compact";
import sortBy from "lodash/sortBy";
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { dateLocale, dateToRelative } from "@shared/utils/date";
import Document from "~/models/Document";
import User from "~/models/User";
import Avatar from "~/components/Avatar";
import ListItem from "~/components/List/Item";
import PaginatedList from "~/components/PaginatedList";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
type Props = {
@@ -18,6 +20,9 @@ type Props = {
function DocumentViews({ document, isOpen }: Props) {
const { t } = useTranslation();
const { views, presence } = useStores();
const user = useCurrentUser();
const locale = dateLocale(user.language);
const documentPresence = presence.get(document.id);
const documentPresenceArray = documentPresence
? Array.from(documentPresence.values())
@@ -31,11 +36,12 @@ function DocumentViews({ document, isOpen }: Props) {
const documentViews = views.inDocument(document.id);
const sortedViews = sortBy(
documentViews,
(view) => !presentIds.includes(view.user.id)
(view) => !presentIds.includes(view.userId)
);
const users = React.useMemo(
() => compact(sortedViews.map((v) => v.user)),
[sortedViews]
);
const users = React.useMemo(() => sortedViews.map((v) => v.user), [
sortedViews,
]);
return (
<>
@@ -43,25 +49,29 @@ function DocumentViews({ document, isOpen }: Props) {
<PaginatedList
aria-label={t("Viewers")}
items={users}
renderItem={(item: User) => {
const view = documentViews.find((v) => v.user.id === item.id);
const isPresent = presentIds.includes(item.id);
const isEditing = editingIds.includes(item.id);
renderItem={(model: User) => {
const view = documentViews.find((v) => v.userId === model.id);
const isPresent = presentIds.includes(model.id);
const isEditing = editingIds.includes(model.id);
const subtitle = isPresent
? isEditing
? t("Currently editing")
: t("Currently viewing")
: t("Viewed {{ timeAgo }} ago", {
timeAgo: formatDistanceToNow(
view ? Date.parse(view.lastViewedAt) : new Date()
: t("Viewed {{ timeAgo }}", {
timeAgo: dateToRelative(
view ? Date.parse(view.lastViewedAt) : new Date(),
{
addSuffix: true,
locale,
}
),
});
return (
<ListItem
key={item.id}
title={item.name}
key={model.id}
title={model.name}
subtitle={subtitle}
image={<Avatar key={item.id} src={item.avatarUrl} size={32} />}
image={<Avatar key={model.id} model={model} size={32} />}
border={false}
small
/>
+21
View File
@@ -0,0 +1,21 @@
import { observer } from "mobx-react";
import * as React from "react";
import Collection from "~/models/Collection";
type Props = {
enabled: boolean;
collection: Collection;
children: React.ReactNode;
};
function DocumentsLoader({ collection, enabled, children }: Props) {
React.useEffect(() => {
if (enabled) {
void collection.fetchDocuments();
}
}, [collection, enabled]);
return <>{children}</>;
}
export default observer(DocumentsLoader);
+74
View File
@@ -0,0 +1,74 @@
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { DocumentValidation } from "@shared/validations";
import Document from "~/models/Document";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import Input from "./Input";
import Text from "./Text";
type Props = {
/** The original document to duplicate */
document: Document;
onSubmit: (documents: Document[]) => void;
};
function DuplicateDialog({ document, onSubmit }: Props) {
const { t } = useTranslation();
const defaultTitle = t(`Copy of {{ documentName }}`, {
documentName: document.title,
});
const [recursive, setRecursive] = React.useState<boolean>(true);
const [title, setTitle] = React.useState<string>(defaultTitle);
const handleRecursiveChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setRecursive(ev.target.checked);
},
[]
);
const handleTitleChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setTitle(ev.target.value);
},
[]
);
const handleSubmit = async () => {
const result = await document.duplicate({
recursive,
title,
});
onSubmit(result);
};
return (
<ConfirmationDialog onSubmit={handleSubmit} submitText={t("Duplicate")}>
<Input
autoFocus
autoSelect
name="title"
label={t("Title")}
onChange={handleTitleChange}
maxLength={DocumentValidation.maxTitleLength}
defaultValue={defaultTitle}
/>
{document.publishedAt && !document.isTemplate && (
<label>
<Text size="small">
<input
type="checkbox"
name="recursive"
checked={recursive}
onChange={handleRecursiveChange}
/>{" "}
{t("Include nested documents")}
</Text>
</label>
)}
</ConfirmationDialog>
);
}
export default observer(DuplicateDialog);
+98 -72
View File
@@ -1,13 +1,17 @@
import { formatDistanceToNow } from "date-fns";
import { deburr, sortBy } from "lodash";
import deburr from "lodash/deburr";
import difference from "lodash/difference";
import sortBy from "lodash/sortBy";
import { observer } from "mobx-react";
import { DOMParser as ProsemirrorDOMParser } from "prosemirror-model";
import { TextSelection } from "prosemirror-state";
import * as React from "react";
import { mergeRefs } from "react-merge-refs";
import { useHistory } from "react-router-dom";
import { Optional } from "utility-types";
import insertFiles from "@shared/editor/commands/insertFiles";
import { Heading } from "@shared/editor/lib/getHeadings";
import { AttachmentPreset } from "@shared/types";
import { Heading } from "@shared/utils/ProsemirrorHelper";
import { dateLocale, dateToRelative } from "@shared/utils/date";
import { getDataTransferFiles } from "@shared/utils/files";
import parseDocumentSlug from "@shared/utils/parseDocumentSlug";
import { isInternalUrl } from "@shared/utils/urls";
@@ -15,27 +19,21 @@ import { AttachmentValidation } from "@shared/validations";
import Document from "~/models/Document";
import ClickablePadding from "~/components/ClickablePadding";
import ErrorBoundary from "~/components/ErrorBoundary";
import HoverPreview from "~/components/HoverPreview";
import type { Props as EditorProps, Editor as SharedEditor } from "~/editor";
import useCurrentUser from "~/hooks/useCurrentUser";
import useDictionary from "~/hooks/useDictionary";
import useEmbeds from "~/hooks/useEmbeds";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
import useUserLocale from "~/hooks/useUserLocale";
import { NotFoundError } from "~/utils/errors";
import { uploadFile } from "~/utils/files";
import history from "~/utils/history";
import { isModKey } from "~/utils/keyboard";
import lazyWithRetry from "~/utils/lazyWithRetry";
import { sharedDocumentPath } from "~/utils/routeHelpers";
import { isHash } from "~/utils/urls";
import DocumentBreadcrumb from "./DocumentBreadcrumb";
const LazyLoadedEditor = React.lazy(
() =>
import(
/* webpackChunkName: "preload-shared-editor" */
"~/editor"
)
);
const LazyLoadedEditor = lazyWithRetry(() => import("~/editor"));
export type Props = Optional<
EditorProps,
@@ -44,37 +42,35 @@ export type Props = Optional<
| "onClickLink"
| "embeds"
| "dictionary"
| "onShowToast"
| "extensions"
> & {
shareId?: string | undefined;
embedsDisabled?: boolean;
grow?: boolean;
onHeadingsChange?: (headings: Heading[]) => void;
onSynced?: () => Promise<void>;
onPublish?: (event: React.MouseEvent) => any;
onPublish?: (event: React.MouseEvent) => void;
editorStyle?: React.CSSProperties;
};
function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
const { id, shareId, onChange, onHeadingsChange } = props;
const { documents } = useStores();
const { showToast } = useToasts();
const {
id,
shareId,
onChange,
onHeadingsChange,
onCreateCommentMark,
onDeleteCommentMark,
} = props;
const userLocale = useUserLocale();
const locale = dateLocale(userLocale);
const { comments, documents } = useStores();
const dictionary = useDictionary();
const embeds = useEmbeds(!shareId);
const [
activeLinkEvent,
setActiveLinkEvent,
] = React.useState<MouseEvent | null>(null);
const history = useHistory();
const localRef = React.useRef<SharedEditor>();
const preferences = useCurrentUser({ rejectOnEmpty: false })?.preferences;
const previousHeadings = React.useRef<Heading[] | null>(null);
const handleLinkActive = React.useCallback((event: MouseEvent) => {
setActiveLinkEvent(event);
return false;
}, []);
const handleLinkInactive = React.useCallback(() => {
setActiveLinkEvent(null);
}, []);
const previousCommentIds = React.useRef<string[]>();
const handleSearchLink = React.useCallback(
async (term: string) => {
@@ -87,8 +83,10 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
try {
const document = await documents.fetch(slug);
const time = formatDistanceToNow(Date.parse(document.updatedAt), {
const time = dateToRelative(Date.parse(document.updatedAt), {
addSuffix: true,
shorten: true,
locale,
});
return [
@@ -110,13 +108,11 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
const results = await documents.searchTitles(term);
return sortBy(
results.map((document: Document) => {
return {
title: document.title,
subtitle: <DocumentBreadcrumb document={document} onlyText />,
url: document.url,
};
}),
results.map((document: Document) => ({
title: document.title,
subtitle: <DocumentBreadcrumb document={document} onlyText />,
url: document.url,
})),
(document) =>
deburr(document.title)
.toLowerCase()
@@ -125,20 +121,21 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
: 1
);
},
[documents]
[locale, documents]
);
const onUploadFile = React.useCallback(
const handleUploadFile = React.useCallback(
async (file: File) => {
const result = await uploadFile(file, {
documentId: id,
preset: AttachmentPreset.DocumentAttachment,
});
return result.url;
},
[id]
);
const onClickLink = React.useCallback(
const handleClickLink = React.useCallback(
(href: string, event: MouseEvent) => {
// on page hash
if (isHash(href)) {
@@ -160,6 +157,12 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
}
}
// Link to our own API should be opened in a new tab, not in the app
if (navigateTo.startsWith("/api/")) {
window.open(href, "_blank");
return;
}
// If we're navigating to an internal document link then prepend the
// share route to the URL so that the document is loaded in context
if (shareId && navigateTo.includes("/doc/")) {
@@ -171,12 +174,12 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
window.open(href, "_blank");
}
},
[shareId]
[history, shareId]
);
const focusAtEnd = React.useCallback(() => {
ref?.current?.focusAtEnd();
}, [ref]);
localRef?.current?.focusAtEnd();
}, [localRef]);
const handleDrop = React.useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
@@ -184,7 +187,7 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
event.stopPropagation();
const files = getDataTransferFiles(event);
const view = ref?.current?.view;
const view = localRef?.current?.view;
if (!view) {
return;
}
@@ -219,21 +222,19 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
);
insertFiles(view, event, pos, files, {
uploadFile: onUploadFile,
uploadFile: handleUploadFile,
onFileUploadStart: props.onFileUploadStart,
onFileUploadStop: props.onFileUploadStop,
onShowToast: showToast,
dictionary,
isAttachment,
});
},
[
ref,
localRef,
props.onFileUploadStart,
props.onFileUploadStop,
dictionary,
onUploadFile,
showToast,
handleUploadFile,
]
);
@@ -249,7 +250,7 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
// Calculate if headings have changed and trigger callback if so
const updateHeadings = React.useCallback(() => {
if (onHeadingsChange) {
const headings = ref?.current?.getHeadings();
const headings = localRef?.current?.getHeadings();
if (
headings &&
headings.map((h) => h.level + h.title).join("") !==
@@ -259,55 +260,80 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
onHeadingsChange(headings);
}
}
}, [ref, onHeadingsChange]);
}, [localRef, onHeadingsChange]);
const updateComments = React.useCallback(() => {
if (onCreateCommentMark && onDeleteCommentMark) {
const commentMarks = localRef.current?.getComments();
const commentIds = comments.orderedData.map((c) => c.id);
const commentMarkIds = commentMarks?.map((c) => c.id);
const newCommentIds = difference(
commentMarkIds,
previousCommentIds.current ?? [],
commentIds
);
newCommentIds.forEach((commentId) => {
const mark = commentMarks?.find((c) => c.id === commentId);
if (mark) {
onCreateCommentMark(mark.id, mark.userId);
}
});
const removedCommentIds = difference(
previousCommentIds.current ?? [],
commentMarkIds ?? []
);
removedCommentIds.forEach((commentId) => {
onDeleteCommentMark(commentId);
});
previousCommentIds.current = commentMarkIds;
}
}, [onCreateCommentMark, onDeleteCommentMark, comments.orderedData]);
const handleChange = React.useCallback(
(event) => {
onChange?.(event);
updateHeadings();
updateComments();
},
[onChange, updateHeadings]
[onChange, updateComments, updateHeadings]
);
const handleRefChanged = React.useCallback(
(node: SharedEditor | null) => {
if (node && !previousHeadings.current) {
if (node) {
updateHeadings();
updateComments();
}
},
[updateHeadings]
[updateComments, updateHeadings]
);
return (
<ErrorBoundary reloadOnChunkMissing>
<ErrorBoundary component="div" reloadOnChunkMissing>
<>
<LazyLoadedEditor
ref={mergeRefs([ref, handleRefChanged])}
uploadFile={onUploadFile}
onShowToast={showToast}
ref={mergeRefs([ref, localRef, handleRefChanged])}
uploadFile={handleUploadFile}
embeds={embeds}
userPreferences={preferences}
dictionary={dictionary}
{...props}
onHoverLink={handleLinkActive}
onClickLink={onClickLink}
onClickLink={handleClickLink}
onSearchLink={handleSearchLink}
onChange={handleChange}
placeholder={props.placeholder || ""}
defaultValue={props.defaultValue || ""}
/>
{props.grow && !props.readOnly && (
{props.editorStyle?.paddingBottom && !props.readOnly && (
<ClickablePadding
onClick={focusAtEnd}
onDrop={handleDrop}
onDragOver={handleDragOver}
grow
/>
)}
{activeLinkEvent && !shareId && (
<HoverPreview
node={activeLinkEvent.target as HTMLAnchorElement}
event={activeLinkEvent}
onClose={handleLinkInactive}
minHeight={props.editorStyle.paddingBottom}
/>
)}
</>
+23
View File
@@ -0,0 +1,23 @@
import styled from "styled-components";
import Button from "~/components/Button";
import { hover } from "~/styles";
import Flex from "../Flex";
export const EmojiButton = styled(Button)`
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
&: ${hover},
&:active,
&[aria-expanded= "true"] {
opacity: 1 !important;
}
`;
export const Emoji = styled(Flex)<{ size?: number }>`
line-height: 1.6;
${(props) => (props.size ? `font-size: ${props.size}px` : "")}
`;
+269
View File
@@ -0,0 +1,269 @@
import data from "@emoji-mart/data";
import Picker from "@emoji-mart/react";
import { SmileyIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { usePopoverState, PopoverDisclosure } from "reakit/Popover";
import styled, { useTheme } from "styled-components";
import { depths, s } from "@shared/styles";
import { toRGB } from "@shared/utils/color";
import Button from "~/components/Button";
import Popover from "~/components/Popover";
import useStores from "~/hooks/useStores";
import useUserLocale from "~/hooks/useUserLocale";
import { Emoji, EmojiButton } from "./components";
/* Locales supported by emoji-mart */
const supportedLocales = [
"en",
"ar",
"be",
"cs",
"de",
"es",
"fa",
"fi",
"fr",
"hi",
"it",
"ja",
"kr",
"nl",
"pl",
"pt",
"ru",
"sa",
"tr",
"uk",
"vi",
"zh",
];
/**
* React hook to derive emoji picker's theme from UI theme
*
* @returns {string} Theme to use for emoji picker
*/
function usePickerTheme(): string {
const { ui } = useStores();
const { theme } = ui;
if (theme === "system") {
return "auto";
}
return theme;
}
type Props = {
/** The selected emoji, if any */
value?: string | null;
/** Callback when an emoji is selected */
onChange: (emoji: string | null) => void | Promise<void>;
/** Callback when the picker is opened */
onOpen?: () => void;
/** Callback when the picker is closed */
onClose?: () => void;
/** Callback when the picker is clicked outside of */
onClickOutside: () => void;
/** Whether to auto focus the search input on open */
autoFocus?: boolean;
/** Class name to apply to the trigger button */
className?: string;
};
function EmojiPicker({
value,
onOpen,
onClose,
onChange,
onClickOutside,
autoFocus,
className,
}: Props) {
const { t } = useTranslation();
const pickerTheme = usePickerTheme();
const theme = useTheme();
const locale = useUserLocale(true) ?? "en";
const popover = usePopoverState({
placement: "bottom-start",
modal: true,
unstable_offset: [0, 0],
});
const [emojisPerLine, setEmojisPerLine] = React.useState(9);
const pickerRef = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (popover.visible) {
onOpen?.();
} else {
onClose?.();
}
}, [popover.visible, onOpen, onClose]);
React.useEffect(() => {
if (popover.visible && pickerRef.current) {
// 28 is picker's observed width when perLine is set to 0
// and 36 is the default emojiButtonSize
// Ref: https://github.com/missive/emoji-mart#options--props
setEmojisPerLine(Math.floor((pickerRef.current.clientWidth - 28) / 36));
}
}, [popover.visible]);
const handleEmojiChange = React.useCallback(
async (emoji) => {
popover.hide();
await onChange(emoji ? emoji.native : null);
},
[popover, onChange]
);
const handleClick = React.useCallback(
(ev: React.MouseEvent) => {
ev.stopPropagation();
if (popover.visible) {
popover.hide();
} else {
popover.show();
}
},
[popover]
);
const handleClickOutside = React.useCallback(() => {
// It was observed that onClickOutside got triggered
// even when the picker wasn't open or opened at all.
// Hence, this guard here...
if (popover.visible) {
onClickOutside();
}
}, [popover.visible, onClickOutside]);
// Auto focus search input when picker is opened
React.useLayoutEffect(() => {
if (autoFocus && popover.visible) {
requestAnimationFrame(() => {
const searchInput = pickerRef.current
?.querySelector("em-emoji-picker")
?.shadowRoot?.querySelector(
"input[type=search]"
) as HTMLInputElement | null;
searchInput?.focus();
});
}
}, [autoFocus, popover.visible]);
return (
<>
<PopoverDisclosure {...popover}>
{(props) => (
<EmojiButton
{...props}
className={className}
onClick={handleClick}
icon={
value ? (
<Emoji size={32} align="center" justify="center">
{value}
</Emoji>
) : (
<StyledSmileyIcon size={32} color={theme.textTertiary} />
)
}
neutral
borderOnHover
/>
)}
</PopoverDisclosure>
<PickerPopover
{...popover}
tabIndex={0}
// This prevents picker from closing when any of its
// children are focused, e.g, clicking on search bar or
// a click on skin tone button
onClick={(e) => e.stopPropagation()}
width={352}
aria-label={t("Emoji Picker")}
>
{popover.visible && (
<>
{value && (
<RemoveButton neutral onClick={() => handleEmojiChange(null)}>
{t("Remove")}
</RemoveButton>
)}
<PickerStyles ref={pickerRef}>
<Picker
// https://github.com/missive/emoji-mart/issues/800
locale={
locale === "ko"
? "kr"
: supportedLocales.includes(locale)
? locale
: "en"
}
data={data}
onEmojiSelect={handleEmojiChange}
theme={pickerTheme}
previewPosition="none"
perLine={emojisPerLine}
onClickOutside={handleClickOutside}
/>
</PickerStyles>
</>
)}
</PickerPopover>
</>
);
}
const StyledSmileyIcon = styled(SmileyIcon)`
flex-shrink: 0;
@media print {
display: none;
}
`;
const RemoveButton = styled(Button)`
margin-left: -12px;
margin-bottom: 8px;
border-radius: 6px;
height: 24px;
font-size: 13px;
> :first-child {
min-height: unset;
line-height: unset;
}
`;
const PickerPopover = styled(Popover)`
z-index: ${depths.popover};
> :first-child {
padding-top: 8px;
padding-bottom: 0;
max-height: 488px;
overflow: unset;
}
`;
const PickerStyles = styled.div`
margin-left: -24px;
margin-right: -24px;
em-emoji-picker {
--shadow: none;
--font-family: ${s("fontFamily")};
--rgb-background: ${(props) => toRGB(props.theme.menuBackground)};
--rgb-accent: ${(props) => toRGB(props.theme.accent)};
--border-radius: 6px;
margin-left: auto;
margin-right: auto;
min-height: 443px;
}
`;
export default EmojiPicker;
+2 -1
View File
@@ -1,7 +1,8 @@
import styled from "styled-components";
import { s } from "@shared/styles";
const Empty = styled.p`
color: ${(props) => props.theme.textTertiary};
color: ${s("textTertiary")};
user-select: none;
`;
+37 -20
View File
@@ -3,7 +3,8 @@ import { observer } from "mobx-react";
import * as React from "react";
import { withTranslation, Trans, WithTranslation } from "react-i18next";
import styled from "styled-components";
import { githubIssuesUrl } from "@shared/utils/urlHelpers";
import { s } from "@shared/styles";
import { githubIssuesUrl, feedbackUrl } from "@shared/utils/urlHelpers";
import Button from "~/components/Button";
import CenteredContent from "~/components/CenteredContent";
import PageTitle from "~/components/PageTitle";
@@ -13,7 +14,12 @@ import Logger from "~/utils/Logger";
import isCloudHosted from "~/utils/isCloudHosted";
type Props = WithTranslation & {
/** Whether to reload the page if a chunk fails to load. */
reloadOnChunkMissing?: boolean;
/** Whether to show a title heading. */
showTitle?: boolean;
/** The wrapping component to use. */
component?: React.ComponentType | string;
};
@observer
@@ -30,7 +36,7 @@ class ErrorBoundary extends React.Component<Props> {
if (
this.props.reloadOnChunkMissing &&
error.message &&
error.message.match(/chunk/)
error.message.match(/dynamically imported module/)
) {
// If the editor bundle fails to load then reload the entire window. This
// can happen if a deploy happens between the user loading the initial JS
@@ -51,24 +57,31 @@ class ErrorBoundary extends React.Component<Props> {
};
handleReportBug = () => {
window.open(githubIssuesUrl());
window.open(isCloudHosted ? feedbackUrl() : githubIssuesUrl());
};
render() {
const { t } = this.props;
const { t, component: Component = CenteredContent, showTitle } = this.props;
if (this.error) {
const error = this.error;
const isReported = !!env.SENTRY_DSN && isCloudHosted;
const isChunkError = this.error.message.match(/chunk/);
const isChunkError = [
"module script failed",
"dynamically imported module",
].some((msg) => this.error?.message?.includes(msg));
if (isChunkError) {
return (
<CenteredContent>
<PageTitle title={t("Module failed to load")} />
<h1>
<Trans>Loading Failed</Trans>
</h1>
<Component>
{showTitle && (
<>
<PageTitle title={t("Module failed to load")} />
<h1>
<Trans>Loading Failed</Trans>
</h1>
</>
)}
<Text type="secondary">
<Trans>
Sorry, part of the application failed to load. This may be
@@ -79,16 +92,20 @@ class ErrorBoundary extends React.Component<Props> {
<p>
<Button onClick={this.handleReload}>{t("Reload")}</Button>
</p>
</CenteredContent>
</Component>
);
}
return (
<CenteredContent>
<PageTitle title={t("Something Unexpected Happened")} />
<h1>
<Trans>Something Unexpected Happened</Trans>
</h1>
<Component>
{showTitle && (
<>
<PageTitle title={t("Something Unexpected Happened")} />
<h1>
<Trans>Something Unexpected Happened</Trans>
</h1>
</>
)}
<Text type="secondary">
<Trans
defaults="Sorry, an unrecoverable error occurred{{notified}}. Please try reloading the page, it may have been a temporary glitch."
@@ -104,15 +121,15 @@ class ErrorBoundary extends React.Component<Props> {
<Button onClick={this.handleReload}>{t("Reload")}</Button>{" "}
{this.showDetails ? (
<Button onClick={this.handleReportBug} neutral>
<Trans>Report a Bug</Trans>
<Trans>Report a bug</Trans>
</Button>
) : (
<Button onClick={this.handleShowDetails} neutral>
<Trans>Show Detail</Trans>
<Trans>Show detail</Trans>
</Button>
)}
</p>
</CenteredContent>
</Component>
);
}
@@ -121,7 +138,7 @@ class ErrorBoundary extends React.Component<Props> {
}
const Pre = styled.pre`
background: ${(props) => props.theme.secondaryBackground};
background: ${s("secondaryBackground")};
padding: 16px;
border-radius: 4px;
font-size: 12px;
+2 -1
View File
@@ -1,10 +1,11 @@
import * as React from "react";
type Props = {
children?: React.ReactNode;
className?: string;
};
const EventBoundary: React.FC<Props> = ({ children, className }) => {
const EventBoundary: React.FC<Props> = ({ children, className }: Props) => {
const handleClick = React.useCallback((event: React.SyntheticEvent) => {
event.preventDefault();
event.stopPropagation();
+34 -34
View File
@@ -7,13 +7,13 @@ import {
PublishIcon,
MoveIcon,
UnpublishIcon,
LightningIcon,
} from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { useLocation } from "react-router-dom";
import { CompositeStateReturn } from "reakit/Composite";
import styled, { css } from "styled-components";
import { s } from "@shared/styles";
import Document from "~/models/Document";
import Event from "~/models/Event";
import Avatar from "~/components/Avatar";
@@ -24,7 +24,9 @@ import Item, { Actions } from "~/components/List/Item";
import Time from "~/components/Time";
import useStores from "~/hooks/useStores";
import RevisionMenu from "~/menus/RevisionMenu";
import { documentHistoryUrl } from "~/utils/routeHelpers";
import { hover } from "~/styles";
import Logger from "~/utils/Logger";
import { documentHistoryPath } from "~/utils/routeHelpers";
type Props = {
document: Document;
@@ -49,33 +51,30 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
ref.current?.focus();
};
const prefetchRevision = () => {
const prefetchRevision = async () => {
if (event.name === "revisions.create" && event.modelId) {
revisions.fetch(event.modelId);
await revisions.fetch(event.modelId);
}
};
switch (event.name) {
case "revisions.create":
icon = <EditIcon color="currentColor" size={16} />;
meta = t("{{userName}} edited", opts);
icon = <EditIcon size={16} />;
meta = latest ? (
<>
{t("Current version")} &middot; {event.actor.name}
</>
) : (
t("{{userName}} edited", opts)
);
to = {
pathname: documentHistoryUrl(document, event.modelId || ""),
state: { retainScrollPosition: true },
};
break;
case "documents.live_editing":
icon = <LightningIcon color="currentColor" size={16} />;
meta = t("Latest");
to = {
pathname: documentHistoryUrl(document),
pathname: documentHistoryPath(document, event.modelId || "latest"),
state: { retainScrollPosition: true },
};
break;
case "documents.archive":
icon = <ArchiveIcon color="currentColor" size={16} />;
icon = <ArchiveIcon size={16} />;
meta = t("{{userName}} archived", opts);
break;
@@ -84,7 +83,7 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
break;
case "documents.delete":
icon = <TrashIcon color="currentColor" size={16} />;
icon = <TrashIcon size={16} />;
meta = t("{{userName}} deleted", opts);
break;
@@ -93,22 +92,22 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
break;
case "documents.publish":
icon = <PublishIcon color="currentColor" size={16} />;
icon = <PublishIcon size={16} />;
meta = t("{{userName}} published", opts);
break;
case "documents.unpublish":
icon = <UnpublishIcon color="currentColor" size={16} />;
icon = <UnpublishIcon size={16} />;
meta = t("{{userName}} unpublished", opts);
break;
case "documents.move":
icon = <MoveIcon color="currentColor" size={16} />;
icon = <MoveIcon size={16} />;
meta = t("{{userName}} moved", opts);
break;
default:
console.warn("Unhandled event: ", event.name);
Logger.warn("Unhandled event", { event });
}
if (!meta) {
@@ -142,7 +141,7 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
onClick={handleTimeClick}
/>
}
image={<Avatar src={event.actor?.avatarUrl} size={32} />}
image={<Avatar model={event.actor} size={32} />}
subtitle={
<Subtitle>
{icon}
@@ -150,7 +149,7 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
</Subtitle>
}
actions={
isRevision && isActive && event.modelId ? (
isRevision && isActive && event.modelId && !latest ? (
<RevisionMenu document={document} revisionId={event.modelId} />
) : undefined
}
@@ -161,15 +160,16 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
);
};
const BaseItem = React.forwardRef(
({ to, ...rest }: ItemProps, ref?: React.Ref<HTMLAnchorElement>) => {
if (to) {
return <CompositeListItem to={to} ref={ref} {...rest} />;
}
return <ListItem ref={ref} {...rest} />;
const BaseItem = React.forwardRef(function _BaseItem(
{ to, ...rest }: ItemProps,
ref?: React.Ref<HTMLAnchorElement>
) {
if (to) {
return <CompositeListItem to={to} ref={ref} {...rest} />;
}
);
return <ListItem ref={ref} {...rest} />;
});
const Subtitle = styled.span`
svg {
@@ -197,7 +197,7 @@ const ItemStyle = css`
left: 23px;
width: 2px;
height: calc(100% + 8px);
background: ${(props) => props.theme.textSecondary};
background: ${s("textSecondary")};
opacity: 0.25;
}
@@ -218,7 +218,7 @@ const ItemStyle = css`
${Actions} {
opacity: 0.5;
&:hover {
&: ${hover} {
opacity: 1;
}
}
+162
View File
@@ -0,0 +1,162 @@
import { observer } from "mobx-react";
import * as React from "react";
import { Trans, useTranslation } from "react-i18next";
import { toast } from "sonner";
import styled from "styled-components";
import { FileOperationFormat, NotificationEventType } from "@shared/types";
import Collection from "~/models/Collection";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import Flex from "~/components/Flex";
import Text from "~/components/Text";
import env from "~/env";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
import history from "~/utils/history";
import { settingsPath } from "~/utils/routeHelpers";
type Props = {
collection?: Collection;
onSubmit: () => void;
};
function ExportDialog({ collection, onSubmit }: Props) {
const [format, setFormat] = React.useState<FileOperationFormat>(
FileOperationFormat.MarkdownZip
);
const [includeAttachments, setIncludeAttachments] =
React.useState<boolean>(true);
const user = useCurrentUser();
const { collections } = useStores();
const { t } = useTranslation();
const appName = env.APP_NAME;
const handleFormatChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setFormat(ev.target.value as FileOperationFormat);
},
[]
);
const handleIncludeAttachmentsChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setIncludeAttachments(ev.target.checked);
},
[]
);
const handleSubmit = async () => {
if (collection) {
await collection.export(format, includeAttachments);
toast.success(t("Export started"), {
description: t(`Your file will be available in {{ location }} soon`, {
location: `"${t("Settings")} > ${t("Export")}"`,
}),
action: {
label: t("View"),
onClick: () => {
history.push(settingsPath("export"));
},
},
});
} else {
await collections.export(format, includeAttachments);
toast.success(t("Export started"));
}
onSubmit();
};
const items = [
{
title: "Markdown",
description: t(
"A ZIP file containing the images, and documents in the Markdown format."
),
value: FileOperationFormat.MarkdownZip,
},
{
title: "HTML",
description: t(
"A ZIP file containing the images, and documents as HTML files."
),
value: FileOperationFormat.HTMLZip,
},
{
title: "JSON",
description: t(
"Structured data that can be used to transfer data to another compatible {{ appName }} instance.",
{
appName,
}
),
value: FileOperationFormat.JSON,
},
];
return (
<ConfirmationDialog onSubmit={handleSubmit} submitText={t("Export")}>
{collection && (
<Text>
<Trans
defaults="Exporting the collection <em>{{collectionName}}</em> may take some time."
values={{
collectionName: collection.name,
}}
components={{
em: <strong />,
}}
/>{" "}
{user.subscribedToEventType(NotificationEventType.ExportCompleted) &&
t("You will receive an email when it's complete.")}
</Text>
)}
<Flex gap={12} column>
{items.map((item) => (
<Option key={item.value}>
<input
type="radio"
name="format"
value={item.value}
checked={format === item.value}
onChange={handleFormatChange}
/>
<div>
<Text size="small" weight="bold">
{item.title}
</Text>
<Text size="small">{item.description}</Text>
</div>
</Option>
))}
</Flex>
<hr />
<Option>
<input
type="checkbox"
name="includeAttachments"
checked={includeAttachments}
onChange={handleIncludeAttachmentsChange}
/>
<div>
<Text size="small" weight="bold">
{t("Include attachments")}
</Text>
<Text size="small">
{t("Including uploaded images and files in the exported data")}.
</Text>{" "}
</div>
</Option>
</ConfirmationDialog>
);
}
const Option = styled.label`
display: flex;
align-items: center;
gap: 16px;
p {
margin: 0;
}
`;
export default observer(ExportDialog);
+10 -6
View File
@@ -1,6 +1,7 @@
import { observer } from "mobx-react";
import * as React from "react";
import styled from "styled-components";
import { s } from "@shared/styles";
import User from "~/models/User";
import Avatar from "~/components/Avatar";
import Flex from "~/components/Flex";
@@ -31,15 +32,18 @@ function Facepile({
</span>
</More>
)}
{users.slice(0, limit).map((user) => (
<AvatarWrapper key={user.id}>{renderAvatar(user)}</AvatarWrapper>
))}
{users
.filter(Boolean)
.slice(0, limit)
.map((user) => (
<AvatarWrapper key={user.id}>{renderAvatar(user)}</AvatarWrapper>
))}
</Avatars>
);
}
function DefaultAvatar(user: User) {
return <Avatar user={user} src={user.avatarUrl} size={32} />;
return <Avatar model={user} size={32} />;
}
const AvatarWrapper = styled.div`
@@ -59,8 +63,8 @@ const More = styled.div<{ size: number }>`
height: ${(props) => props.size}px;
border-radius: 100%;
background: ${(props) => props.theme.slate};
color: ${(props) => props.theme.text};
border: 2px solid ${(props) => props.theme.background};
color: ${s("text")};
border: 2px solid ${s("background")};
text-align: center;
font-size: 11px;
font-weight: 600;
+11 -2
View File
@@ -1,6 +1,7 @@
import * as React from "react";
import { useMenuState, MenuButton } from "reakit/Menu";
import styled from "styled-components";
import { s } from "@shared/styles";
import Button, { Inner } from "~/components/Button";
import ContextMenu from "~/components/ContextMenu";
import MenuItem from "~/components/ContextMenu/MenuItem";
@@ -10,6 +11,7 @@ type TFilterOption = {
key: string;
label: string;
note?: string;
icon?: React.ReactNode;
};
type Props = {
@@ -57,6 +59,7 @@ const FilterOptions = ({
selected={option.key === activeKey}
{...menu}
>
{option.icon && <Icon>{option.icon}</Icon>}
{option.note ? (
<LabelWithNote>
{option.label}
@@ -77,8 +80,8 @@ const Note = styled(Text)`
margin-bottom: 0;
line-height: 1.2em;
font-size: 14px;
font-weight: 400;
color: ${(props) => props.theme.textTertiary};
font-weight: 500;
color: ${s("textTertiary")};
`;
const LabelWithNote = styled.div`
@@ -106,6 +109,12 @@ const StyledButton = styled(Button)`
}
`;
const Icon = styled.div`
margin-right: 8px;
width: 18px;
height: 18px;
`;
const Wrapper = styled.div`
margin-right: 8px;
`;

Some files were not shown because too many files have changed in this diff Show More