Compare commits

...

1869 Commits

Author SHA1 Message Date
Tom Moor bfaed5d9cb test 2022-09-05 15:38:00 +02:00
Tom Moor 5923281edb Allow arbitrary revisions to be compared 2022-09-05 13:55:07 +02:00
Tom Moor 01bfe2bde7 Add revisions.diff endpoint, first version 2022-09-05 13:35:27 +02:00
Tom Moor 9c6780adab Allow DocumentHelper to be used with Revisions 2022-09-05 12:58:40 +02:00
Tom Moor 93f1d4cfc7 div>article for easier programatic content extraction 2022-09-05 11:52:12 +02:00
Tom Moor 21a43dfc5e Refactor to allow for styling of HTML export 2022-09-04 22:57:54 +02:00
Tom Moor 47fafb5d69 fix nodes that required document to render 2022-09-04 17:29:02 +02:00
Tom Moor 32d76eeb9e docs 2022-09-04 17:07:26 +02:00
Tom Moor 99bef2c02b Add HTML download option to UI 2022-09-04 16:30:35 +02:00
Tom Moor 1125412972 fix: Add compatability for documents without collab state 2022-09-04 16:10:03 +02:00
Tom Moor 2e0d160fcc Add title to HTML export 2022-09-04 15:58:59 +02:00
Tom Moor 21e31be517 tidy 2022-09-04 15:31:42 +02:00
Translate-O-Tron 18821fdee2 New Crowdin updates (#4004) 2022-09-04 03:56:48 -07:00
Tom Moor c8b12a59e2 fix: Post-signin redirect path is no longer saved (#4054)
closes #4045
2022-09-04 03:56:12 -07:00
Tom Moor c964163cc5 fix: Handle GitLab can be configured for tokens to not expire. (#4051)
closes #4040
2022-09-04 03:56:00 -07:00
Tom Moor c9156ae399 fix: Login screen not vertically centered on mobile (#4052) 2022-09-04 00:14:32 -07:00
Tom Moor e0e87ea6a2 fix: Allow backlinks to work with fully qualified urls and anchors (#4050)
closes #4048
2022-09-04 00:14:21 -07:00
Tom Moor e1b0e94fd5 Wrap code blocks when printing, closes #4001 2022-09-03 23:39:22 +02:00
Tom Moor 2fa5e5c796 fix: Incorrect validation 2022-09-02 20:56:13 +02:00
Tom Moor 0882a50cfd fix: Requests using GET that should be POST, related #4042 2022-09-02 10:45:20 +02:00
Tom Moor c85f3bd7b4 fix: Remove ability to use GET for RPC API requests by default (#4042)
* fix: Remove ability to use GET for RPC API requests by default

* tsc
2022-09-02 01:05:40 -07:00
Nicolas Caluori 2d29f0f042 Content is displayed wrongly when printing / Save as PDF (#4043) 2022-09-02 01:05:09 -07:00
dependabot[bot] 67d119f932 chore(deps): bump moment-timezone from 0.5.34 to 0.5.37 (#4037)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-31 11:48:30 +05:30
Tom Moor 32b76303e5 Add simple count of views to share links (#4036)
* Add simple count of views to share links

* Remove no longer applicable tests

* Avoid incrementing view count for known bots
2022-08-30 23:16:40 -07:00
Tom Moor 212985e18f feat: Allow viewers to be upgraded to editors on individual collections (#4023)
* Improve types

* More types, fix default permission for viewers added to collection

* fix change of default role for CollectionGroup

* Restore policy

* test

* tests
2022-08-30 23:12:27 -07:00
Tom Moor b8115ae3ce fix: Add url validation to team and user avatar fields 2022-08-30 23:05:57 +02:00
Tom Moor 264f19d255 fix: Suppress TooManyRequestsError to error tracker 2022-08-28 21:17:51 +02:00
Tom Moor 6fc1cbc0ce fix: Unneccessary requests made on share links 2022-08-27 20:45:07 +02:00
Tom Moor 3cc3cd8cf8 fix: Do not replace SSR title with 'Untitled', closes #3985 2022-08-27 20:20:59 +02:00
Tom Moor b9f1fde2e3 test 2022-08-27 13:39:11 +02:00
Tom Moor a1d4cca9d9 Add support for document subscriptions to websockets 2022-08-27 12:53:40 +02:00
Tom Moor 922bf53753 fix: Document subscriptions backfill not recursive 2022-08-27 11:58:21 +02:00
Tom Moor 1c8fadbe02 Merge branch 'tom/socket-refactor' 2022-08-27 11:51:38 +02:00
Apoorv Mishra 4dbad4e46c feat: Support embed configuration (#3980)
* wip

* stash

* fix: make authenticationId nullable fk

* fix: apply generics to resolve compile time type errors

* fix: loosen integration settings

* chore: refactor into functional component

* feat: pass integrations all the way to embeds

* perf: avoid re-fetching integrations

* fix: change attr name to avoid type overlap

* feat: use hostname from embed settings in matcher

* Revert "feat: use hostname from embed settings in matcher"

This reverts commit e7485d9cda.

* feat: refactor  into a class

* chore: refactor url regex formation as a util

* fix: escape regex special chars

* fix: remove in-house escapeRegExp in favor of lodash's

* fix: sanitize url

* perf: memoize embeds

* fix: rename hostname to url and allow spreading entire settings instead of just url

* fix: replace diagrams with drawio

* fix: rename

* fix: support self-hosted and saas both

* fix: assert on settings url

* fix: move embed integrations loading to hook

* fix: address review comments

* fix: use observer in favor of explicit state setters

* fix: refactor useEmbedIntegrations into useEmbeds

* fix: use translations for toasts

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-08-26 12:21:46 +05:30
CuriousCorrelation 24c71c38a5 feat: Document subscriptions (#3834)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-08-25 23:47:13 -07:00
Tom Moor 354a68a8b7 Remove long-deprecated documents.star/documents.unstar 2022-08-25 21:51:34 +02:00
Tom Moor bb12f1fabb SocketProvider -> WebsocketProvider 2022-08-25 21:34:54 +02:00
Tom Moor debadcb711 fix: Wrap websocket handlers in action
Separate documents.archive
2022-08-25 21:34:54 +02:00
Tom Moor d2aea687f3 Remove collection fetch on document delete 2022-08-25 21:34:54 +02:00
Tom Moor 60309975e0 Allow usePolicy to fetch missing policies 2022-08-25 21:34:54 +02:00
Tom Moor 983010b5d8 fix: collections.create event not propagated when initialized with private permissions 2022-08-25 21:34:54 +02:00
Tom Moor de5524d366 Add tracing around websocket processor 2022-08-25 21:34:54 +02:00
Tom Moor c62bfc4a60 Separate documents.update event 2022-08-25 21:34:54 +02:00
Tom Moor 7804f33e0d Separate teams.update event 2022-08-25 21:34:54 +02:00
Tom Moor d17e6f3432 Separate documents.delete event 2022-08-25 21:34:54 +02:00
Tom Moor 4f1277f912 Separate groups.delete event 2022-08-25 21:34:54 +02:00
Tom Moor b172da6fdf Separate collections.delete event 2022-08-25 21:34:54 +02:00
Tom Moor 138bc367dd types 2022-08-25 21:34:54 +02:00
Tom Moor c657134b46 types 2022-08-25 21:34:54 +02:00
Tom Moor 864f585e5b chore: Remove long deprecated database columns (#3821)
* chore: Remove long deprecated database columns

* test

* Update 20220720221531-remove-deprecated-columns.js

* fix rollback

* Add guard for upgrading past v0.54.0
2022-08-25 11:52:01 -07:00
Tom Moor a869ab7609 fix: Improve error messaging when file cannot be fetched for import
related #4006
2022-08-24 21:25:19 +02:00
Tom Moor a3d8e6c8fc chore: Add db:create command 2022-08-24 00:04:37 -07:00
Tom Moor 68f24fce21 fix: Add support for new clickup sharing links 2022-08-23 23:04:21 +02:00
Tom Moor f0cbbee4b8 Merge branch 'main' of github.com:outline/outline 2022-08-23 22:58:45 +02:00
Tom Moor 7345d0c256 Remove links to valid files 2022-08-23 10:21:35 -07:00
Tom Moor ee05a8a0ca Merge branch 'main' of github.com:outline/outline 2022-08-23 09:58:03 +02:00
Translate-O-Tron fd7e0ef41f New Crowdin updates (#3958) 2022-08-22 11:41:16 -07:00
Tom Moor 1e5cf2d960 chore: Update dd-trace 2022-08-22 14:47:19 +02:00
Tom Moor 421312b845 Possible fix for #3986 2022-08-22 09:47:47 +02:00
Tom Moor f1bd4a5b31 Merge branch '3991-add-explicit-timeouts-to-requests' 2022-08-22 09:21:22 +02:00
Tom Moor 72b0e78788 fix: Validate uuid on attachments.create endpoint 2022-08-20 23:46:01 +02:00
Tom Moor 8302840ab5 feat: Add timeout to incoming requests 2022-08-19 08:14:11 +02:00
Tom Moor f32f07cdcc chore: Refactor user activation to command 2022-08-18 11:24:27 +02:00
Tom Moor f620a9d34c fix: Cannot start without --services argument, regressed in 41d7cc26b5
closes #3984
2022-08-18 09:48:28 +02:00
Tom Moor 7113b5f604 fix: Restore user deletion through API, increase rate limit 2022-08-17 22:40:00 +02:00
Tom Moor 41d7cc26b5 chore: Adds name to Redis connections for debugging (#3982)
* chore: Adds name to Redis connections for debugging, minor associated refactoring

* Upgrade bull, ioredis

* Add pid to redis connection name in development
2022-08-17 12:55:57 -07:00
Tom Moor e57941732a fix: emoji column no longer filled in db, simplified state length validation 2022-08-16 22:05:10 +02:00
Tom Moor a738b51d87 chore: Add additional logging for unknown request errors 2022-08-16 19:49:15 +02:00
Tom Moor 85dab03820 docs 2022-08-16 19:43:50 +02:00
Tom Moor ed8176ca7d fix: Limit ws payload size 2022-08-16 10:27:55 +02:00
Tom Moor cfa7ecd7f8 fix: Add missing validation to document state 2022-08-16 09:35:31 +02:00
github-actions[bot] 44a4aee5cf chore: Auto Compress Images (#3977)
Co-authored-by: apoorv-mishra <apoorv-mishra@users.noreply.github.com>
2022-08-16 00:10:52 -07:00
Jonathan Harrrington 7ead17a8e0 Add support for Grist embeds. (#3914)
* Add support for Grist embeds.

* Change Grist integration to only support SaaS

* Update Regex

* Update shared/editor/embeds/index.tsx

Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>

* Change Grist embed to use function based API

* Convert standard URL into embed url

* Update shared/editor/embeds/Grist.tsx

Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>

* Update shared/editor/embeds/Grist.tsx

Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>

* Update shared/editor/embeds/Grist.tsx

Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>

* Lint and test updates

Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-08-16 09:17:20 +05:30
Apoorv Mishra 7a758f84a0 chore: refactor server test setup (#3976)
* chore: refactor server test setup

* Close dangling redis connections instead of mocking rate limiter
  specific modules
* Segregate pre and post env test setup

* fix: remove mock file
2022-08-16 09:16:57 +05:30
Tom Moor 93bb9d067d fix: H1 and title should be different sizes, closes #3975 2022-08-15 23:02:35 +02:00
Tom Moor 9f3266abaf Remove headings 4 and below from TOC, see:
https://github.com/outline/outline/discussions/3973
2022-08-15 22:46:49 +02:00
Tom Moor 4d0473c22c Reference email image by cid for self hosted instances (#3957) 2022-08-14 08:50:49 -07:00
Tom Moor d8b4814aa9 perf: Suppress Mermaid diagram rendering when hidden (#3963) 2022-08-14 08:50:37 -07:00
Tom Moor a326e0ee88 chore: Rate limiter audit (#3965)
* chore: Rate limiter audit api/users

* Make requests required

* api/collections

* Remove checkRateLimit on FileOperation (now done at route level through rate limiter)

* auth rate limit

* Add metric logging when rate limit exceeded

* Refactor to shared configs

* test
2022-08-14 08:04:04 -07:00
Tom Moor 9338328a82 fix: Add expiry to socket<->user mapping in Redis 2022-08-13 22:26:13 +02:00
Tom Moor 31931fc80c test: Remove --detectLeaks as this expiremental flag is good – but flakey, tests fail in CI that do not locally 2022-08-12 15:37:08 +02:00
Tom Moor 7deda03000 test: Fix test memory leakage by mocking RateLimiter 2022-08-12 15:14:58 +02:00
Nan Yu 990de127e3 feat: add session switching to the root action menu (#3925)
* feat: add session switching to the root action menu

* minor fixes

* stylistic consistency

* capitalize account section

* minor fix
2022-08-12 05:11:22 -07:00
Apoorv Mishra 0c51bfb899 perf: reduce memory usage upon running server tests (#3949)
* perf: reduce memory usage upon running server tests

* perf: plug leaks in server/routes

* perf: plug leaks in server/scripts

* perf: plug leaks in server/policies

* perf: plug leaks in server/models

* perf: plug leaks in server/middlewares

* perf: plug leaks in server/commands

* fix: missing await on db.flush

* perf: plug leaks in server/queues

* chore: remove unused legacy funcs

* fix: await on db.flush

* perf: await on GC to run in between tests

* fix: remove db refs

* fix: revert embeds

* perf: plug leaks in shared/i18n
2022-08-11 21:39:17 +05:30
akp 8e1f42a9cb Add optional export notifications (#3935)
* Add `emails.export_completed` notification to settings menu

Signed-off-by: AKP <tom@tdpain.net>

* Don't send email when export_completed notifications are disabled

Signed-off-by: AKP <tom@tdpain.net>

* Automatically subscribe new users to `export_completed` notifications

Signed-off-by: AKP <tom@tdpain.net>

* Alter secondary text on export page to mention optional notifications

Signed-off-by: AKP <tom@tdpain.net>

* Alter toast text on collection export for optional notifications

Signed-off-by: AKP <tom@tdpain.net>

* Only subscribe new admins to export notifs

Signed-off-by: AKP <tom@tdpain.net>

* Move `export_completed` notification decision into `beforeSend`

Signed-off-by: AKP <tom@tdpain.net>

* Update server/emails/templates/ExportFailureEmail.tsx

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update server/emails/templates/ExportSuccessEmail.tsx

Co-authored-by: Tom Moor <tom.moor@gmail.com>

Signed-off-by: AKP <tom@tdpain.net>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-08-11 07:31:35 -07:00
Tom Moor 1adcce6b5d fix: Upgrade markdown-it to fix text collapse bug (#3953)
* fix: Upgrade markdown-it to fix text collapse bug

* tsc. Need to overwrite the types for now until all Prosemirror modules are updated, they have recently been converted to Typescript and the types conflict
2022-08-11 06:31:52 -07:00
Translate-O-Tron a5d611d544 New Crowdin updates (#3795) 2022-08-11 05:46:21 -07:00
Tom Moor 1d242d44b1 chore: Add eslint rule for object shorthand (#3955) 2022-08-11 05:18:14 -07:00
Apoorv Mishra 7eaa8eb961 feat: Put request rate limit at application server (#3857)
* feat: Put request rate limit at application server

This PR contains implementation for a blanket rate limiter at
application server level. Currently the allowed throughput is set high
only to be changed later as per the actual data gathered.

* Simplify implementation

1. Remove shutdown handler to purge rate limiter keys
2. Have separate keys for default and custom(route-based) rate limiters
3. Do not kill default rate limiter because it is not needed anymore due
   to (2) above

* Set 60s as default for rate limiting window

* Fix env types
2022-08-11 15:40:30 +05:30
Tom Moor 593cf73118 test: Update jest configuration (#3951)
* Split shared tests

* Centralize and parallelize jest config

* ci
2022-08-10 13:26:36 -07:00
Tom Moor e5c5e8907a fix: Disallow data: URI's for images 2022-08-09 16:31:09 +02:00
dependabot[bot] 5640ec30cc chore(deps): bump compressorjs from 1.0.7 to 1.1.1 (#3943)
Bumps [compressorjs](https://github.com/fengyuanchen/compressorjs) from 1.0.7 to 1.1.1.
- [Release notes](https://github.com/fengyuanchen/compressorjs/releases)
- [Changelog](https://github.com/fengyuanchen/compressorjs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fengyuanchen/compressorjs/compare/v1.0.7...v1.1.1)

---
updated-dependencies:
- dependency-name: compressorjs
  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>
2022-08-08 09:13:03 -07:00
dependabot[bot] da67486f2f chore(deps): bump aws-sdk from 2.1044.0 to 2.1189.0 (#3942)
Bumps [aws-sdk](https://github.com/aws/aws-sdk-js) from 2.1044.0 to 2.1189.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.1044.0...v2.1189.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>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-08 09:11:55 -07:00
Tom Moor 8c39487c80 Move various document menu actions to action definitions 2022-08-08 17:31:53 +02:00
dependabot[bot] 3ab9d7492e chore(deps): bump react-merge-refs from 1.1.0 to 2.0.1 (#3903)
* chore(deps): bump react-merge-refs from 1.1.0 to 2.0.1

Bumps [react-merge-refs](https://github.com/gregberge/react-merge-refs) from 1.1.0 to 2.0.1.
- [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/v1.1.0...v2.0.1)

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

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

* tsc

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-08-08 15:04:18 +01:00
dependabot[bot] 6a5d6ee3db chore(deps): bump oy-vey from 0.10.0 to 0.11.2 (#3902)
* chore(deps): bump oy-vey from 0.10.0 to 0.11.2

Bumps [oy-vey](https://github.com/oysterbooks/oy) from 0.10.0 to 0.11.2.
- [Release notes](https://github.com/oysterbooks/oy/releases)
- [Changelog](https://github.com/revivek/oy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/oysterbooks/oy/compare/0.10.0...0.11.2)

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

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

* tsc

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-08-08 07:02:41 -07:00
Tom Moor 57f9871c22 Add NODE_ENV=production to env sample 2022-08-08 05:52:03 -07:00
Tom Moor dca491fc28 test: Fix frontend test failures from upgrading Jest to v28 2022-08-08 13:31:34 +02:00
Tom Moor e97cc61e2f test: Mock bull, fix setInterval capturing memory in tests
Towards #3939
2022-08-08 13:15:06 +02:00
Tom Moor ba385e1507 chore: Bump jest 2022-08-08 12:40:17 +02:00
Tom Moor 71c9fcf59b test: Avoid creation of new server/app instance for each route test 2022-08-08 12:06:54 +02:00
Tom Moor b45e6c504f fix: Prevent webhook delivery for deleted teams 2022-08-08 11:15:04 +02:00
Tom Moor 1b00d51c74 fix: Check WebhookSubscription is not disabled before delivery attempt 2022-08-08 11:10:10 +02:00
Tom Moor 7923a7e071 Enforce user invites/request on server 2022-08-08 11:02:37 +02:00
Tom Moor b37a848914 Add limit of 10 webhooks/team 2022-08-08 10:58:47 +02:00
github-actions[bot] dca9bc1598 chore: Compressed inefficient images automatically (#3933)
Co-authored-by: apoorv-mishra <apoorv-mishra@users.noreply.github.com>
2022-08-07 13:10:08 -07:00
Apoorv Mishra 982ab2b48e feat(editor): support google form embeds (#3930)
Fixes #3129 and #3923
2022-08-07 12:41:30 +05:30
Nan Yu 74d9409cc3 fix: refactor auth flow to explicitly pass in a host (#3909)
* fix: refactor auth flow to explicitly pass in a host

* add new error handler to all SSO providers

* refactor passport error into middleware
2022-08-04 02:00:52 -07:00
Apoorv Mishra 0a6cfe5a6a feat: Choose random color on collection creation (#3912)
Choose a random color from a shared color palette between backend
and frontend during collection creation.
2022-08-04 01:48:19 -07:00
Apoorv Mishra 4a16124a94 fix: Remove templatize action for trashed document (#3922) 2022-08-04 01:44:15 -07:00
Apoorv Mishra 294521f162 fix: Escape regex for embeds (#3907)
Fixes #3899
2022-08-02 01:40:11 -07:00
Apoorv Mishra 00481d2bfc fix: Improve document delete confirmation message (#3876)
Modify document delete confirmation message to warn
about the number of expected nested documents to be deleted.
2022-08-01 15:51:30 -07:00
Tom Moor eace258a86 Revert "chore(deps-dev): bump react-refresh from 0.9.0 to 0.14.0 (#3901)" (#3908)
This reverts commit de4b515e64.
2022-08-01 15:43:47 -07:00
dependabot[bot] de4b515e64 chore(deps-dev): bump react-refresh from 0.9.0 to 0.14.0 (#3901)
Bumps [react-refresh](https://github.com/facebook/react/tree/HEAD/packages/react) from 0.9.0 to 0.14.0.
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v0.14.0/packages/react)

---
updated-dependencies:
- dependency-name: react-refresh
  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>
2022-08-01 13:57:32 -07:00
dependabot[bot] c35c566fef chore(deps-dev): bump concurrently from 6.2.1 to 7.3.0 (#3905)
Bumps [concurrently](https://github.com/open-cli-tools/concurrently) from 6.2.1 to 7.3.0.
- [Release notes](https://github.com/open-cli-tools/concurrently/releases)
- [Commits](https://github.com/open-cli-tools/concurrently/compare/v6.2.1...v7.3.0)

---
updated-dependencies:
- dependency-name: concurrently
  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>
2022-08-01 11:56:14 -07:00
Pavlos d9dc6aa2d7 Fix URL in huntr page link (#3906) 2022-08-01 18:51:38 +01:00
Spotlight 192802d360 feat: Expand highlighted languages (#3891)
Adds Elixir, Kotlin, and Swift to the list of available languages to be highlighted.
2022-07-31 11:23:59 -07:00
Tom Moor cb9773ad85 chore: Add emailed confirmation code to account deletion (#3873)
* wip

* tests
2022-07-31 10:59:40 -07:00
Tom Moor f9d9a82e47 fix: Cannot hit enter after sentance starting with forward slash
closes #3879
2022-07-29 09:15:48 +01:00
Tom Moor 383bac241e fix: Suppress ForbiddenError in error tracker 2022-07-26 23:18:26 +01:00
Tom Moor ea28dc46eb fix: Error in WebhookProcessor when team is permanatly destroyed 2022-07-26 22:33:48 +01:00
Tom Moor 2794057738 fix: Sequelize rejectOnEmpty should result in 404 status 2022-07-26 22:06:47 +01:00
Tom Moor b7b1f5e1fd fix: Cleanup attachments uploaded to S3 when import fails (#3868) 2022-07-26 12:10:13 -07:00
Tom Moor 8fdd5bf734 fix: substitution of content when sending an image to a profile (#3869)
* fix: Limit public uploads to basic image types

* test
2022-07-26 12:10:00 -07:00
Tom Moor 086c3ec2d8 fix: Allow more flexible SMTP connection when SSL is not required. Do not fail on self-signed certs 2022-07-25 23:44:20 +01:00
Tom Moor f370b0296b fix: File operation cleanup task should also remove import data 2022-07-25 21:10:37 +01:00
Tom Moor 9b837763e6 0.65.2 2022-07-25 19:25:23 +01:00
dependabot[bot] 3d9a8be867 chore(deps-dev): bump typescript from 4.4.4 to 4.7.4 (#3866)
* chore(deps-dev): bump typescript from 4.4.4 to 4.7.4

Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.4.4 to 4.7.4.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.4.4...v4.7.4)

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

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

* tsc

* tsc

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-07-25 11:21:04 -07:00
dependabot[bot] c8caeebdba chore(deps): bump react-window from 1.8.6 to 1.8.7 (#3865)
Bumps [react-window](https://github.com/bvaughn/react-window) from 1.8.6 to 1.8.7.
- [Release notes](https://github.com/bvaughn/react-window/releases)
- [Changelog](https://github.com/bvaughn/react-window/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bvaughn/react-window/commits)

---
updated-dependencies:
- dependency-name: react-window
  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>
2022-07-25 11:09:47 -07:00
dependabot[bot] 2c7d5ac3d8 chore(deps-dev): bump @types/jsonwebtoken from 8.5.5 to 8.5.8 (#3864)
Bumps [@types/jsonwebtoken](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsonwebtoken) from 8.5.5 to 8.5.8.
- [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>
2022-07-25 11:09:32 -07:00
Tom Moor 30190866f8 test: Flakey test 2022-07-25 08:59:30 +01:00
Tom Moor 53a08cf307 chore: Basic protection against zip bombs 2022-07-24 23:51:04 +01:00
dependabot[bot] 1c5864deee chore(deps-dev): bump eslint-config-prettier from 8.3.0 to 8.5.0 (#3807)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.3.0 to 8.5.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.3.0...v8.5.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>
2022-07-24 13:11:11 -07:00
Tom Moor 865e6d048e fix: 'Export' option missing in collection menu for admins 2022-07-24 20:29:59 +01:00
Tom Moor 5e852170f9 perf: Read attachment buffers only when neccessary, closes #3849 2022-07-24 19:15:34 +01:00
Tom Moor 71da57773e docs 2022-07-24 14:09:43 +01:00
Tom Moor ec35af4bc5 Refactor validations 2022-07-24 13:40:04 +01:00
Nan Yu 870d9ed41e feat: allow external SSO methods to log into teams as long as emails match (#3813)
* wip

* wip

* fix comments

* better separation of conerns

* fix up tests

* fix semantics

* fixup tsc

* fix some tests

* the old semantics were easier to use

* add db:reset to scripts

* explicitly throw for unauthorized external authorization

* fix minor bug

* add additional tests for user creator and team creator

* yank the email matching logic out of teamcreator

* renaming

* fix type and test errors

* adds test to ensure that accountProvisioner works with email matching

* remove only

* fix comments

* recreate changes to allow self hosted to make teams
2022-07-24 04:55:30 -07:00
Apoorv Mishra 24170e8684 chore: Remove updatedAt column from events table (#3841) 2022-07-24 01:57:21 -07:00
Tom Moor 7ae892fe06 fix: Long collection description prevents import (#3847)
* fix: Long collection description prevents import
fix: Parallelize attachment upload during import

* fix: Improve Notion image import matching

* chore: Bump JSZIP (perf)

* fix: Allow redirect from /doc/<id> to canonical url

* fix: Importing document with only title duplicates title in body
2022-07-24 01:37:20 -07:00
Tom Moor 4f537c7578 Remove retry on export task 2022-07-23 17:00:32 +01:00
Tom Moor 4bca081faa chore: Add rolling window limits to import and export operations 2022-07-23 16:29:28 +01:00
Tom Moor 87b4c9fdba fix: Cannot create collection if all existing collections are deleted (#3836) 2022-07-22 10:44:11 -07:00
Tom Moor 6fe4b1cba1 fix: Code block previous language memory (#3830) 2022-07-22 01:59:48 -07:00
Tom Moor ef2abf824e fix: Correctly sanitize href in link editor 'open url' flow 2022-07-22 00:23:53 +01:00
Tom Moor 4b4b0f7037 Revert "feat: Port scenes/Search to functional component style (#3800)" (#3827)
This reverts commit 5758ff3459.
2022-07-21 03:37:27 -07:00
Tom Moor 80d50e3d88 fix: Diagrams.net proxy path considered as embeddable 2022-07-21 10:51:34 +01:00
Tom Moor ba264974cf fix: Improvement to accuracy of collaboration server metrics 2022-07-21 09:44:13 +01:00
CuriousCorrelation 71dd4f267b feat: Port UserListItem to functional style (#3802)
* feat: Port `UserListItem` to functional style

* Add translation for pending invite

* Add missing translations

* Update `translations.json`

* Revert "Update `translations.json`"

This reverts commit d8000a7510.

* fix: Incorrect translation strings

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-07-20 15:07:01 -07:00
CuriousCorrelation 5758ff3459 feat: Port scenes/Search to functional component style (#3800)
* feat: Refactor Search scene to functional style

* fix: Clicking on recent not updating search input

* Replace translations and root objs with stores

* Replace `props.location` with `useLocation`

* deconstruct `useLocation` for readability

* Replace match prop term with `useParams`

* [WIP] Replace props history with `useHistory`

* Replace `ReactComponentProps` with state style

* Remove `lastParam` check, use dependency array instead

* Add explict match on param change

This reverts commit bfcc4038ff.
2022-07-20 15:06:49 -07:00
dependabot[bot] 6568b16ef9 chore(deps): bump terser from 4.8.0 to 4.8.1 (#3817)
Bumps [terser](https://github.com/terser/terser) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-20 15:05:19 -07:00
Tom Moor ef0412c449 fix: Cannot create new team on self-hosted (#3819) 2022-07-20 13:18:21 -07:00
Tom Moor 031a7d396f Add message to login screen for shared links 2022-07-19 17:57:13 +01:00
Nan Yu c3f5563e7f feat: scope login attempts to specific subdomains if available - do not switch subdomains (#3741)
* make the user lookup in user creator sensitive to team
* add team specific logic to oidc strat
* factor out slugifyDomain
* change type of req during auth to Koa.Context
2022-07-19 06:50:55 -07:00
Tom Moor 4ee3929e9d 0.65.1 2022-07-19 09:59:02 +01:00
Tom Moor 9ab409a640 fix: Account for non-SSL database connection in pending migrations check (#3811)
* fix: Account for non-SSL database connection in pending migrations check

* Double exit
2022-07-19 01:58:48 -07:00
Tom Moor 9cafe75bf2 0.65.0 2022-07-18 23:30:51 +01:00
Tom Moor 630b4eff8a chore: Bump passport 2022-07-18 22:51:11 +01:00
Tom Moor bf8ca59442 chore: Bump moment 2022-07-18 22:40:34 +01:00
Tom Moor 9dd28def67 fix: Force download of public attachments 2022-07-18 21:49:48 +01:00
dependabot[bot] d785389fde chore(deps): bump prosemirror-gapcursor from 1.2.1 to 1.3.1 (#3808)
Bumps [prosemirror-gapcursor](https://github.com/prosemirror/prosemirror-gapcursor) from 1.2.1 to 1.3.1.
- [Release notes](https://github.com/prosemirror/prosemirror-gapcursor/releases)
- [Changelog](https://github.com/ProseMirror/prosemirror-gapcursor/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prosemirror/prosemirror-gapcursor/compare/1.2.1...1.3.1)

---
updated-dependencies:
- dependency-name: prosemirror-gapcursor
  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>
2022-07-18 13:01:26 -07:00
Tom Moor 1ccd770bce Merge branch 'main' of github.com:outline/outline 2022-07-18 19:25:50 +01:00
dependabot[bot] 7719d378b0 chore(deps): bump semver and @types/semver (#3805)
Bumps [semver](https://github.com/npm/node-semver) and [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver). These dependencies needed to be updated together.

Updates `semver` from 7.3.5 to 7.3.7
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.3.5...v7.3.7)

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

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: "@types/semver"
  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>
2022-07-18 11:25:09 -07:00
dependabot[bot] f26f8d4bb9 chore(deps-dev): bump @types/node from 15.12.2 to 18.0.6 (#3806)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 15.12.2 to 18.0.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  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>
2022-07-18 11:24:43 -07:00
dependabot[bot] 89d4aeac67 chore(deps): bump slug and @types/slug (#3804)
Bumps [slug](https://github.com/Trott/slug) and [@types/slug](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/slug). These dependencies needed to be updated together.

Updates `slug` from 4.0.4 to 5.3.0
- [Release notes](https://github.com/Trott/slug/releases)
- [Changelog](https://github.com/Trott/slug/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Trott/slug/compare/v4.0.4...v5.3.0)

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

---
updated-dependencies:
- dependency-name: slug
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: "@types/slug"
  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>
2022-07-18 11:24:29 -07:00
Tom Moor dc94a683e7 chore: Reduce timeout on webhook deliveries 2022-07-17 18:48:45 +01:00
Jamie Slome 04f5b08ba1 Update SECURITY.md (#3711)
* Update SECURITY.md

* Update SECURITY.md

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-07-17 07:29:10 -07:00
CuriousCorrelation 5924f4909f fix: Cursor disappearing behind emoji (#3786)
* fix: Cursor disappearing behind emoji

* Move emoji node styles to `Styles.ts`

* fix: grammar

* fix: Pasting emoji adds a new line

* fix: DOM element type
2022-07-17 06:49:39 -07:00
CuriousCorrelation c00bad38e2 feat(editor): Ability to select line in codeblocks (#3798)
* feat(editor): Ability to select line in codeblocks

* fix: Check to make sure sel is indeed in codeblock
2022-07-17 06:49:30 -07:00
Tom Moor 11e1ef455f chore: Improve UUID vaildation – prevent nonsense reaching db queries 2022-07-17 14:49:04 +01:00
Tom Moor 4af69b2758 fix: Moving an image to empty space results in endless upload (#3799)
* fix: Error dragging images below doc, types

* fix: Handle html/text content dropped into padding

* refactor, docs
2022-07-17 03:31:55 -07:00
Tom Moor dee87f15af fix: Members table does not correctly reset from filters 2022-07-16 18:47:36 +01:00
dependabot[bot] 67885e7339 chore(deps): bump react-dnd-html5-backend from 14.0.0 to 16.0.1 (#3769)
Bumps [react-dnd-html5-backend](https://github.com/react-dnd/react-dnd) from 14.0.0 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-html5-backend
  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>
2022-07-16 10:15:11 -07:00
Tom Moor 0b0a1b0169 fix: Heading action depth conflict, closes #3558 2022-07-16 17:58:02 +01:00
Tom Moor de18196fd8 chore: Upgrade socket.io (#3697)
* Upgrade wip

* tsc

* tsc

* fix: Missing authenticated message
2022-07-16 06:02:03 -07:00
dependabot[bot] 96d1c4997b chore(deps): bump yjs from 13.5.34 to 13.5.39 (#3770)
Bumps [yjs](https://github.com/yjs/yjs) from 13.5.34 to 13.5.39.
- [Release notes](https://github.com/yjs/yjs/releases)
- [Commits](https://github.com/yjs/yjs/compare/v13.5.34...v13.5.39)

---
updated-dependencies:
- dependency-name: yjs
  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>
2022-07-16 02:40:34 -07:00
Tom Moor 95f4fb2424 chore: Remove deprecated socket.io-auth (#3780) 2022-07-16 02:27:09 -07:00
Tom Moor 1247bb411e Merge branch 'paullessing-issue-3655-allowed-domains-save-no-change' 2022-07-16 00:38:28 +01:00
Tom Moor 7ffb182034 Merge branch 'issue-3655-allowed-domains-save-no-change' of github.com:paullessing/outline into paullessing-issue-3655-allowed-domains-save-no-change 2022-07-16 00:37:49 +01:00
Translate-O-Tron fc414e2dd4 New Crowdin updates (#3723) 2022-07-15 16:19:13 -07:00
Nan Yu c3ec7b0877 Feat: clarify security language and hide default settings when invites are required (#3751)
* clarify default role and allowed domains

* language tweaks

* Update app/scenes/Settings/Security.tsx

Co-authored-by: Tom Moor <tom.moor@gmail.com>

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-07-15 16:13:41 -07:00
Tom Moor e509719c77 Add ability to quickly create test users in development (#3764) 2022-07-15 16:11:30 -07:00
Tom Moor a16cf72b73 feat: Error state for paginated lists (#3766)
* Add error state for failed list loading

* Move sidebar collections to PaginatedList for improved error handling, loading, retrying etc
2022-07-15 16:11:04 -07:00
CuriousCorrelation acabc00643 fix: ToolbarMenu popup on inline code selection (#3775)
* fix: `ToolbarMenu` popup on inline code selection

* fix: Replace `isCode` checks with single `isInCode`

* feat: Only relevant options on `code_inline` selection

* Change special case with item visibility toggle

* fix: `formattingMenuItems` visibility in `code_inline`
2022-07-15 16:10:47 -07:00
Tom Moor e989999d6e fix: Upgrade prosemirror-view fixes duplicate lines, closes #3371
Note: That this bump of prosemirror-view also includes typescript types for the first time ever, these conflict with the @types packages and cause the need for extensive changes throughout the codebase. To prevent this becoming a massive PR with days of testing these new types are being removed for now. In the future we will bump all of the pm dependencies and restore the package types here
2022-07-15 10:34:03 +01:00
dependabot[bot] c3e149eb86 chore(deps): bump @babel/core from 7.17.10 to 7.18.6 (#3771)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.17.10 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-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-07-13 12:48:57 -07:00
dependabot[bot] 4c05fe422c chore(deps): bump http-errors from 1.4.0 to 2.0.0 (#3772)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-13 00:59:56 -07:00
Tom Moor 47e73cee4e feat: Cleanup api keys and webhooks for suspended users (#3756) 2022-07-13 00:59:31 -07:00
CuriousCorrelation d1b01d28e6 fix: svg+xml image type ext not assigned properly (#3774) 2022-07-13 00:59:17 -07:00
Tom Moor 973cfc3fa3 Do not show suspended users to non admins (#3776) 2022-07-13 00:59:06 -07:00
dependabot[bot] dd6084d044 chore(deps-dev): bump @types/formidable from 2.0.0 to 2.0.5 (#3773)
Bumps [@types/formidable](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/formidable) from 2.0.0 to 2.0.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/formidable)

---
updated-dependencies:
- dependency-name: "@types/formidable"
  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>
2022-07-12 11:07:17 -07:00
Tom Moor 206545f350 fix: Ensure signed attachment urls are always downloaded rather than loaded in browser 2022-07-12 17:14:22 +01:00
Tom Moor e92d68a0a3 Create dependabot.yml 2022-07-12 09:40:44 +02:00
CuriousCorrelation 66dbcde29b feat: Redirect on unpublished share access (#3760)
* feat(WIP): Redirect on unpublished shares

* feat[WIP]: add redirect with test notice

* Revert to `Login` display, no redirects
2022-07-10 23:59:45 -07:00
Tom Moor 465a8bd505 fix: Version tag should open new tab, related type improvements
closes #3737
2022-07-10 11:22:45 +02:00
Tom Moor aef62d1356 fix: Publish click from editing heading, closes #3759 2022-07-10 10:23:00 +02:00
Tom Moor 35e82beaf7 chore: Upgrade koa- dependencies (#3761) 2022-07-09 10:23:42 -07:00
Tom Moor 8bb88b8550 chore: Audit of all model column validations (#3757)
* chore: Updating all model validations before the white-hatters get to it ;)

* test

* Remove isUrl validation, thinking about it need to account for minio and other weird urls here
2022-07-09 08:04:40 -07:00
Tom Moor da4a10e877 chore: Remove shares.info apiVersion 1 (#3758)
* chore: Remove shares.info apiVersion 1

* fix: Sporadic test failure
2022-07-09 04:28:56 -07:00
Tom Moor caaf6dd76b fix: Enter at beginning of collapsed heading should create a new heading above (#3754) 2022-07-09 02:23:12 -07:00
Tom Moor 2893924e9a fix: Must check length before passing to timingSafeEqual 2022-07-09 11:19:40 +02:00
Tom Moor 32b7a7df00 fix: Handle sanitizeUrl can receive non-string value
closes #3746
2022-07-08 21:15:07 +02:00
Tom Moor 97f8c0813c fix: Use crypto.timingSafeEqual, closes #3740 2022-07-08 21:10:51 +02:00
CuriousCorrelation 746dc30aeb feat: Add pending migrations check during startup (#3744)
* feat: Add pending migrations check during startup

* fix: migration pending log message

Co-authored-by: Tom Moor <tom.moor@gmail.com>

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-07-08 11:30:16 -07:00
Tom Moor 4a46d19846 fix: Improved model validation for Collection (#3749)
* fix: Added improved model validation for Collection attributes

* sp

* fix: Enforce title length in UI
2022-07-08 11:10:22 -07:00
Tom Moor 98106e7f6f Update 20220702132722-add-webhooks-deleted-at.js 2022-07-08 02:22:48 -07:00
Nan Yu 1e808fc52c Feat: add auth provider to users on sign in (#3739)
* feat: merge a new authentication method onto existing user records when emails match

* adds test for invite acceptance and auth provider creation

* addresses comments
- test existing user and invites in different test cases
- update lastActiveAt syncronously when an invite is accepted

* sort arrays in test to prevent nondeterministic test behaivior when doing array compare
2022-07-08 00:24:46 -07:00
Tom Moor ec8c0645ba fix: Correct annotation order 🙈 2022-07-07 12:23:27 +02:00
Tom Moor f90309e781 fix: Unneccessary restrictive avatarUrl length 2022-07-07 12:16:54 +02:00
Paul Lessing d8f125f413 Fix: Move logic inline 2022-07-07 11:01:32 +01:00
Tom Moor c36e7bfbb6 fix: Add 10 domain limit per team (#3733)
* fix: Validate team domains are FQDN's
Add 10 domain limit per team
fix: Deletion of domains not happening within request lifecycle

* tests

* docs
2022-07-05 12:27:02 -07:00
Tom Moor 831df67358 feat: Adds route-level role filtering. (#3734)
* feat: Adds route-level role filtering. Another layer in the onion of security and performance

* fix: Regression in authentication middleware
2022-07-05 12:26:49 -07:00
Tom Moor c6fdffba77 chore: Internal request filtering 2022-07-05 11:06:47 +02:00
Tom Moor 4e189b8970 Improved sanitization of href's in editor 2022-07-05 10:14:16 +02:00
Tom Moor 2f3dcb2520 fix: Do not show 'Full width' toggle to viewers
closes #3728
2022-07-04 15:20:01 +02:00
Nan Yu f36f5f13f4 Fix: clear localstore after logout (#3731)
* fix: remove user, team, and policies from auth store and localstorage on logout

* true up the reset everywhere
2022-07-04 01:47:44 -07:00
Tom Moor 5d498632c6 fix: Models are not all removed from local store upon access change (#3729)
* fix: Clean data from stores correctly on 401/403 response

* Convert DataLoader from class component, remove observables and caching

* types
2022-07-03 13:48:50 -07:00
Tom Moor 9cd26168e1 Separates policy for file operations 2022-07-03 18:19:56 +02:00
Tom Moor ee10e1407a fix: Typo of fileOperation -> fileOperations 2022-07-03 16:27:03 +02:00
Tom Moor c9af7ff889 fix: Suppress db validation errors in error reporting 2022-07-03 16:03:53 +02:00
Tom Moor 27978b8fc4 fix: Remove teams.create from audit events 2022-07-03 14:16:49 +02:00
Tom Moor 62d9bf7105 chore: Move initial avatar upload to background worker (#3727)
* chore: Async user avatar upload processor

* chore: Async team avatar upload

* Refactor to task for retries

* Docs
Include avatarUrl in task props to prevent race condition
Remove transaction around upload fetch request
2022-07-03 02:36:15 -07:00
Tom Moor 1f3a1d4b86 fix: Improved websockets error handling (#3726)
* fix: Add websocket client error capturing
fix: Incorrect parsing of documentName will never be empty

* fix: Non-present documentId in collaboration route should trigger an error response

* fix: Close unhandled websocket requests
2022-07-03 00:00:59 -07:00
Tom Moor 8ebe4b27b1 fix: Add additional model validation (#3725) 2022-07-02 14:29:01 -07:00
Tom Moor 0c30d2bb34 fix: share.document can be null when document is deleted
closes #3724
2022-07-02 19:56:15 +02:00
Tom Moor f744d488f6 chore: Soft delete webhooks (#3722) 2022-07-02 10:41:28 -07:00
Tom Moor 8ebf6e884f fix: Startup warning caused by unnecessary compilation of tests and mocks in non-test environments 2022-07-02 15:57:35 +02:00
Tom Moor 4438c80ea1 fix: users.promote + users.demote not available for individual subscription in webhook form 2022-07-02 14:55:07 +02:00
Tom Moor 863f22750f feat: Add optional notification email when invite is accepted (#3718)
* feat: Add optional notification email when invite is accepted

* Refactor to use beforeSend
2022-07-02 05:40:40 -07:00
Tom Moor ee22a127f6 feat: Add email when webhook is disabled (#3721)
fix: Webhook not disabled under some error conditions
2022-07-02 05:36:40 -07:00
Tom Moor c9cd424a8d chore: Remove over-usage of invariant (#3719) 2022-07-02 05:29:39 -07:00
Tom Moor 108b5b934a fix: users.promote & users.demote not handled by DeliverWebhookTask 2022-07-02 14:24:49 +02:00
Tom Moor 94824af6e7 fix: Allow soft-deleted records to be queried from RevisionProcessor
closes #3706
2022-07-02 11:58:22 +02:00
Tom Moor 1c6eef3509 Don't show share link when team sharing disabled (#3714)
fix: Docs appear to be publicly shared when sharing previously enabled
2022-07-02 01:37:10 -07:00
Translate-O-Tron 4e09356982 New Crowdin updates (#3681) 2022-07-01 13:22:01 -07:00
Nan Yu 4b166432e6 fix: show a distinct error message when a user tries to create an account using a personal gmail (#3710)
* fix: show a different error message when a user tries to create an account using a personal gmail

* throw only after attempting to find the team
2022-07-01 13:21:23 -07:00
CuriousCorrelation adb55fa965 feat: Custom Length decorator for UTF-8 chars len (#3709)
* feat: Custom Length decorator for UTF-8 chars len

* fix: Length decorator function return type
2022-07-01 13:21:09 -07:00
Tom Moor 7ce57c9c83 fix: attachments events not recognised by DeliverWebhookTask 2022-07-01 18:40:32 +02:00
Tom Moor b44dc726f3 test: fix fetch related tests 2022-06-30 10:37:06 +02:00
Paul Lessing 117421b4cb Feat: Only show save domains button if changes were made
The logic for this is that we show the button if either:
a) one or more new non-empty domains have been added, or
b) an existing domain was modified, even if the modification was then undone.

The reasoning for b) is as follows:
If a user adds a new domain row, makes changes, then removes the domain row, it is clear to the user that no changes have been made, and therefore the "save" button should not be visible.
However, as soon as the user makes any changes to an existing domain, they want to feel confident that they can hit save and ensure that whatever change they made is persisted; even if the change is identical to the current state, because they may not be able to recall accurately what the current state was. In those situations a user gets more confidence out of being able to hit save, than they would from being told by the system "you haven't made any changes".
2022-06-29 08:33:07 +01:00
Tom Moor 930bfd5391 fix: Must import fetch, log errors, use git short sha for version 2022-06-29 08:28:44 +02:00
Tom Moor 10f86ed218 feat: Webhooks (#3691)
* Webhooks (#3607)

* Get the migration and the model setup. Also make the sample env file a bit easier to use. Now just requires setting a SECRET_KEY and besides that will boot up from the sample

* WIP: Start getting a Webhook page created. Just the skeleton state right now

* WIP: Getting a form created to create webhooks, need to bring in react-hook-forms now

* WIP: Get library installed and make TS happy

* Get a few checkboxes ready to go

* Get creating and destroying working with a decent start to a frontend

* Didn't mean to enable this

* Remove eslint and fix other random typescript issue

* Rename some events to be more realistic

* Revert these changes

* PR review comments around policies. Also make sure this inherits from IdModel so it actually gets an id

* Allow any admin on the team to edit webhooks

* Start sending some webhooks for some User events

* Make sure the URL is valid

* Start recording webhook deliveries

* Make sure to verify if the subscription is for the type of event we are looking at

* Refactor sending Webhooks and follow better webhook schema

This creates a presenter to unify the format of webhooks. We also
extract the sending of webhooks and recording their deliveries to a
method than can be used by each of the different event type methods

We also add a status to WebhookDelivery since we need to save the record
before we make the HTTP request to get its id. Then once we make the
request and get a response we can update the delivery with the HTTP info

* Turn off a subscription that has failed for the last 25 deliveries

* Get a first spec passing. Found a bug in my returning of promises so good to patch that up now

* This looks nicer

* Get some tests added for the processor

* Add cron task to delete older webhooks

* Add Document Events to the Processor

* Revisions, FileOperations and Collections

* Get all the server side events added to the processor and make Typescript make sure they are all accounted for

* Get all the events added to the Frontend and work on styling them a bit, still needs some love though

* Get UI styled up a bit

* Get events wired up for webhook subscriptions

* Get delete events working and test at least one variant of them

* Get deletes working and actually make sure to send the model id in the webhook

* Remove webhook secrets from this slice

* Add disabled label for subscriptions that are disabled

* Make sure to cascade the delete

* Reorg this file a bit

* Fix association

* I removed secret for the moment

* Apply Copy changes from PR Review

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Actually apply the copy changes

TIL that if you Resolve a conversation it _also_ removes the 'staged suggestion' from your list on Github

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/Settings/Webhooks.tsx

Missed this copy change before

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Add disabled as yellow badge

* Resolve frontend comments

* Fixup Schema a bit and remove the dependency on the subscription

* Add test to make sure we don't disable until there are enough failures, and fix code to actually do that. Also some test fixes from the json response shape changes

* Fix WebhookDeliveries to store the responses as Text instead of blobs

* Switch to text better for response bodies, this is using the helpers better and makes the code read better

* Move the logic to a task but run in through the processor cause the tests expect that right now, moving the tests over next

* Split up the tests and actually enqueue the events from the WebhookProcessor instead of doing them inline

* Allow any team admin to see any webhook subscription for the team

* Add the indexes based on our lookup patterns

* Run eslint --fix to fix auto correct issues from when I tried to use Github to merge copy changes

* Allow subscriptions to be edited after creation

* Types caught that I didn't add the new event to the webhook processor, also added it to the frontend here

* I think this will get these into the translations file

* Catch a few more translations, use styled components better and remove usage of webhook subscription in the copy

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* fix: tsc
fix: Document model payload empty

* fix: Revision webhook payload
Add custom UA for hooks

* Add webhooks icon, move under Integrations settings
Some spacing fixes

* Add actorId to webhook payloads

* Add View and ApiKey event types

* Spacing tweaks, fix team payload

* fix: Webhook not disabled after 25 failures

* fix: Enable webhook when editing if previously disabled

* fix: Correctly store response headers

* fix: Error in json/parsing/presentation results in hanging 'pending' webhook delivery

* fix: Awkward payload for users.invite webhook

* Add BaseEvent, ShareEvent

* fix: Add share events to form

* fix: Move webhook delivery cleanup to single DB call
Remove some unused abstraction

* Add user, collection, group context to membership webhook events
Some associated refactoring

Co-authored-by: Corey Alexander <coreyja@gmail.com>
2022-06-28 22:44:50 -07:00
Tom Moor 9a6e09bafa feat: Add mermaidjs integration (#3679)
* feat: Add mermaidjs integration (#3523)

* Add mermaidjs to dependencies and CodeFenceNode

* Fix diagram id for mermaidjs diagrams

* Fix typescript compiler errors on mermaid integration

* Fix id generation for mermaid diagrams

* Refactor mermaidjs integration into prosemirror plugin

* Remove unnecessary class attribute in mermaidjs integration

* Change mermaidjs label to singular

* Change decorator.inline to decorator.node for mermaid diagram id

* Fix diagram toggle state

* Add border and background to mermaid diagrams

* Stop mermaidjs from overwriting fontFamily inside diagrams

* Add stable diagramId to mermaid diagrams

* Separate text for hide/show diagram
Use uuid as diagramId, avoid storing in state
Fix cursor on diagrams

* fix: Base diagram visibility off presence of source

* fix: More cases where our font-family is ignored

* Disable HTML labels

* fix: Button styling – not technically required but now we have a third button this felt all the more needed

closes #3116

* named chunks

* Upgrade mermaid 9.1.3

Co-authored-by: Jan Niklas Richter <5812215+ArcticXWolf@users.noreply.github.com>
2022-06-28 22:44:36 -07:00
Paul Lessing c65a88fc9f Fix: Changing security settings should not implicitly save allowedDomains 2022-06-28 19:40:25 +01:00
Tom Moor e24a5adbd5 deps: upgrade nodemon, jpeg-js 2022-06-27 16:45:54 +02:00
Tom Moor cddb6b2c32 deps: upgrade bull-board 2022-06-27 16:42:45 +02:00
Tom Moor ac467b2936 fix: Return direct url to public attachments, closes #3686 2022-06-24 11:24:11 +02:00
Tom Moor 68ce304b48 fix: Language in document notification email, missing collection name 2022-06-24 10:01:54 +02:00
Tom Moor 50456c3b89 fix: Custom domain authentication, regressed in:
https://github.com/outline/outline/pull/3652
2022-06-22 21:58:05 +02:00
Tom Moor 51230a55e5 fix: Post-auth subdomain redirect 2022-06-22 19:51:37 +02:00
Tom Moor 6d4da176d1 chore: Move provisionSubdomain from Team model to teamCreator command 2022-06-22 11:09:20 +02:00
Tom Moor 88b3b50333 Enable turning off collaborative editing when self-hosted with warning 2022-06-22 09:15:14 +02:00
Tom Moor 305de71e8b chore: Block all email providers from being added as team domains (#3678) 2022-06-21 01:29:43 -07:00
Tom Moor 9cd3ec0868 chore: Simplify model save codepath, prevents text from being sent ever when collab editing enabled 2022-06-20 22:55:37 +02:00
Tom Moor 6975d76faf fix: Paste without formatting not respected
closes #3675
2022-06-20 15:58:07 +02:00
Tom Moor 4b27feff61 fix: Enable documents.update with collab editing (#3647)
* fix: Enable documents.update with collab editing

* jest cannot deal with ESM deps
2022-06-20 06:36:25 -07:00
Nan Yu e0d2b6cace feat: allow personal gmail accounts to be used to sign into teams with an existing invite (#3652)
* feat: allow personal gmail accounts to be used to sign into teams with an existing invite

* address comments

* add comment for appDomain

* address comments
2022-06-20 01:33:16 -07:00
Translate-O-Tron 188c1e409b New Crowdin updates (#3648)
* fix: New Chinese Simplified translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Indonesian translations from Crowdin [ci skip]
2022-06-19 14:24:53 -07:00
Nan Yu 9faa5dd011 chore: minor version bump (#3654) 2022-06-12 22:57:59 -07:00
Tom Moor 1a62926909 fix: Allow soft breaks in paragraphs with Shift-Enter 2022-06-09 21:41:15 +02:00
Tom Moor c4edfb8ebc fix: Improve embed option visibility in dark mode 2022-06-09 21:38:24 +02:00
Tom Moor 8421e1f773 fix: Allow soft breaks in paragraphs with Shift-Enter
closes #3276
2022-06-09 21:24:11 +02:00
Tom Moor 118e5da345 fix: Unpublished does not appear in document history
closes #3429
2022-06-09 21:16:37 +02:00
Tom Moor 1c7c478a4a fix: Newlines should be interpreted as paragraphs when pasting
closes #3421
2022-06-09 20:58:52 +02:00
Tom Moor 32cdb3f961 fix: Do not error when moving document into alphabetically ordered collection
closes #3649
2022-06-09 20:33:44 +02:00
Tom Moor d99d84d97d fix: Email cannot be found for some Azure sign-in accounts 2022-06-09 09:22:12 +02:00
Tom Moor aed8d7a649 fix: SSR meta data for nested shared documents (#3646) 2022-06-08 01:38:34 -07:00
Tom Moor 80ad6cfec8 fix: Expired refreshToken should invalidate session, not check SSO retry task 2022-06-08 08:55:58 +02:00
Translate-O-Tron 892146a563 New Crowdin updates (#3631) 2022-06-07 13:57:44 -07:00
Tom Moor 56393f39b7 fix: Previously provisioned JWT's should be revoked on signout (#3639)
* feat: auth.delete endpoint

* test
2022-06-07 13:57:17 -07:00
Tom Moor 0de6650aa5 chore: Suppress unneccessary model warnings from Sequelize upgrade 2022-06-07 09:38:00 +02:00
Tom Moor ac551a3c44 chore: Bump workbox-webpack-plugin dependency 2022-06-06 22:06:37 +02:00
Tom Moor 14b9259a47 fix: Always strip trailing slash on canonical links 2022-06-06 22:04:12 +02:00
Tom Moor e5b524e4c2 chore: Upgrade sequelize dependency 2022-06-06 21:54:54 +02:00
Tom Moor 4bccb4c4ec chore: Bump bull-board dependencies 2022-06-06 21:18:22 +02:00
Tom Moor cdd4f0f315 fix: Add postgresql as valid database protocol 2022-06-06 12:13:03 -07:00
Tom Moor 728790e38f feat: Validate Google, Azure, OIDC SSO access (#3590)
* chore: Store expiresAt on UserAuthentications. This represents the time that the accessToken is no longer valid and should be exchanged using the refreshToken

* feat: Check and expire Google SSO

* fix: Better handling of multiple auth methods
Added more docs

* fix: Retry access validation with network errors

* Small refactor, add Azure token validation support

* doc

* test

* lint

* OIDC refresh support

* CheckSSOAccessTask -> ValidateSSOAccessTask
Added lastValidatedAt column
Skip checks if validated within 5min
Some edge cases around encrypted columns
2022-06-05 13:18:51 -07:00
Tom Moor c4c5b6289e fix: Gap and grammar in Notification settings 2022-06-05 11:47:40 +02:00
Tom Moor e337123cfd fix: Add application/x-zip-compressed as acceptable mimetype for bulk import upload
related #3632
2022-06-05 11:01:37 +02:00
Tom Moor ac07724f21 chore: Synchronizing refactor and small fixes from enterprise codebase (#3634)
* chore: Syncronizing refactor and small fixes from enterprise codebase

* fix
2022-06-05 00:59:41 -07:00
Tom Moor 28439d315d fix: Self-hosted should show signin options for all configured authentication methods (#2986) 2022-06-04 10:46:03 -07:00
Tom Moor 4eb3b61c7a fix: Lazily polyfill ResizeObserver for old iOS (#3629)
* fix: Lazily polyfill ResizeObserver for old iOS

* fix: Prevent child rendering until polyfills are loaded

* tsc
2022-06-04 09:06:07 -07:00
Translate-O-Tron 6fc608c8c1 New Crowdin updates (#3622) 2022-06-04 08:15:54 -07:00
Tom Moor 2dc930bfe2 fix: Context menus not scrollable on iOS (#3626)
closes #3588
2022-06-04 08:15:43 -07:00
Tom Moor bf233b209b fix: Alternative fix to #3583, addresses some bugs that were introduced 2022-06-03 11:03:44 +02:00
Tom Moor 1dfd1e0681 fix: Reference error visiting share link for deleted team 2022-06-03 08:58:31 +02:00
dependabot[bot] 4054afe6f9 chore(deps): bump protobufjs from 6.11.2 to 6.11.3 (#3623) 2022-06-02 23:17:50 -07:00
Tom Moor 2d7dd558a1 fix: Unable to delete user via API (#3619)
Remove requirement to pass 'confirmation' to users.delete
closes #3604
2022-06-02 12:56:27 -07:00
Tom Moor 68dd76cfa3 chore: Update documentImporter with changes from enterprise, improved Confluence compat 2022-06-02 21:42:32 +02:00
Tom Moor 9113989635 fix: Members list does not update when viewing while underlying users changes
closes #3616
2022-06-02 18:43:07 +02:00
Translate-O-Tron 293ce2ba72 New Crowdin updates (#3608) 2022-06-02 09:30:28 -07:00
Nan Yu fa1ce950e8 fix: infinite redirects when hosted subdomain is changed back and forth between two values (#3615) 2022-06-02 09:30:13 -07:00
Tom Moor 0a77733500 fix: Update canonical url when moving between pages of shared document 2022-06-01 21:27:18 +02:00
Nan Yu 41e425756d chore: refactor domain parsing to be more general (#3448)
* change the api of domain parsing to just parseDomain and getCookieDomain
* adds getBaseDomain as the method to get the domain after any official subdomains
2022-05-31 18:48:23 -07:00
Translate-O-Tron 876f788f59 New Crowdin updates (#3597)
* fix: New German translations from Crowdin [ci skip]

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

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

* fix: New German translations from Crowdin [ci skip]
2022-05-30 10:33:47 -07:00
Lennart Lösche 0ae559f7bf Update redis port in sample env file (#3596)
* fix redis port

The wrong Redis port is specified in the sample file, we fixed that

* adjust redis port in docker-compose
2022-05-30 10:06:10 -07:00
Tom Moor da87fd422d Remove hover styles on mobile context menus 2022-05-28 10:05:17 +02:00
Tom Moor 1e84872bab fix: Only consider enabled AuthenticationProviders for Slack hooks 2022-05-28 09:36:22 +02:00
Tom Moor 4f0051ed5e fix: Right click on links in editor opens them
closes #3594
2022-05-28 09:23:18 +02:00
Tom Moor 317ed1f041 fix: More env validation improvements
closes #3593
2022-05-28 09:11:02 +02:00
Tom Moor 8a29a3523a 0.64.3 2022-05-25 06:07:02 +01:00
Tom Moor 2babf42cda fix: Headings missing in TOC on publicly shared pages
closes #3583
2022-05-24 22:11:49 +01:00
Tom Moor df14da01b0 fix: Allow docker urls for OIDC, closes #3582 2022-05-24 21:20:18 +01:00
Tom Moor 62bb13047a 0.64.2 2022-05-24 08:00:08 +01:00
Tom Moor 6413797c34 fix: Empty string not parsed as false boolean in env validation
closes #3581
2022-05-24 07:59:52 +01:00
Tom Moor ef5e3f0b29 fix: Empty environment variables should not trigger validations
Add deprecation notice for SLACK_KEY, SLACK_SECRET
closes #3578
2022-05-23 21:37:27 +01:00
Baptiste Mille-Mathias 51249fd6f7 upgrade CodeQL action to v2 (#3572)
v1 will be declared deprecated starting dec' 22
https://github.blog/changelog/2022-04-27-code-scanning-deprecation-of-codeql-action-v1/
2022-05-23 12:51:33 -07:00
Tom Moor 151c2c731a 0.64.1 2022-05-23 13:19:49 +01:00
Tom Moor 519ed1ac2c fix: Environment variables always interpreted as true,
closes #3573
2022-05-23 13:19:38 +01:00
Tom Moor f1ce28cd8f fix: Allow underscores in Postgres and Redis hostnames for docker support
closes #3574
2022-05-23 13:11:52 +01:00
Tom Moor adb56a3c31 Update LICENSE 2022-05-23 01:56:46 -07:00
Tom Moor 280e1c1d86 0.64.0 2022-05-23 09:55:20 +01:00
Baptiste Mille-Mathias 3c8b9725e1 Fix github action for stale issues (#3569) 2022-05-23 01:42:30 -07:00
Tom Moor 73de15fd5d fix: documentUpdater called without change can result in lastModifiedById being updated 2022-05-22 22:39:54 +01:00
Tom Moor a78ad8dec2 fix: Escape user defined values (regressed just now bc7052b7ca) 2022-05-22 11:10:59 +01:00
Tom Moor 45c082f137 fix: Notices dark theme 2022-05-22 09:33:30 +01:00
Tom Moor 4a9892c2e1 robots 2022-05-22 08:58:44 +01:00
Tom Moor 6d7f008af0 fix: Sidebar missing on public documents when accessing with valid team token 2022-05-22 08:51:47 +01:00
Tom Moor bc7052b7ca feat: Inject description and canonical url into public share links 2022-05-22 08:46:57 +01:00
Tom Moor c4006cef7b perf: Remove markdown serialize from editor render path (#3567)
* perf: Remove markdown serialize from editor render path

* fix: Simplify heading equality check

* perf: Add cache for slugified headings

* tsc
2022-05-21 12:50:27 -07:00
Tom Moor 2a6d6f5804 chore: Restore more flexible SMTP env email validation 2022-05-21 14:01:57 +01:00
Tom Moor bf0ff6c823 chore: Casing of logger -> Logger as it's an instantiated class 2022-05-21 13:59:23 +01:00
Tom Moor 6c8b127ff9 chore: isHosted -> isCloudHosted for clarity 2022-05-21 13:34:52 +01:00
Tom Moor f2be756cf4 feat: Improved error for community edition when database columns cannot be decrypted 2022-05-21 13:25:55 +01:00
rusakovdenis 67049a7868 fix: simplify transformation (#3548)
* fix: simplify transformation

Functions (isDragging, isOver, canDrop) always return a boolean value

* fix: type

In browserslist must be either an array or an object
2022-05-21 05:14:53 -07:00
Translate-O-Tron d9706d4735 New Crowdin updates (#3556) 2022-05-21 05:14:34 -07:00
Tom Moor ec748f9914 fix: Floating toolbar should not appear until mouseup when selecting with mouse
closes #3564
2022-05-21 12:57:29 +01:00
Tom Moor ef668c2fa0 Tweak design of notices 2022-05-21 11:06:35 +01:00
Tom Moor 594a004c0f chore: Move to GitHub action from Probot for stale issue/pr management 2022-05-21 10:05:41 +01:00
Tom Moor 468478d06d fix: Another timestamp crash 2022-05-21 10:05:41 +01:00
Tom Moor 02caf88d2a chore: AuthenticationProvider component to function 2022-05-21 10:05:41 +01:00
github-actions[bot] 50f26929a1 chore: Compressed inefficient images automatically (#3563)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2022-05-21 01:44:17 -07:00
Tom Moor 0f93e92bc6 feat: Add 'Scribe' embed support 2022-05-21 09:28:04 +01:00
Tom Moor c08940ca3c feat: Add optional replyTo for email sending 2022-05-21 08:36:37 +01:00
Tom Moor ee8324ad73 fix: Remove additional scope requests for now 2022-05-20 23:59:33 +01:00
Tom Moor 96a32c98e7 fix: Remove email validation to allow for Name <email> format 2022-05-20 22:18:21 +01:00
Tom Moor 5c741e3d98 fix: Crash render timestamp on some languages 2022-05-20 18:58:23 +01:00
Tom Moor ba7b3fff05 fix: Emojis and embeds cannot be copied to plain text clipboard (#3561) 2022-05-20 09:47:13 -07:00
Tom Moor 90ca8655af fix: Collapsed header button unclickable when full-width document option is selected
closes #3558
2022-05-20 10:04:36 +01:00
Tom Moor 0577c73f06 fix: Links with anchors are broken when pages are renamed
closes #3553
2022-05-20 09:43:54 +01:00
Tom Moor 39e146b4e6 fix: Minor usability improves to team domain management 2022-05-19 18:28:19 +01:00
Tom Moor 34576dd008 fix: Allow COLLABORATION_URL set with websocket protocol 2022-05-19 16:34:58 +01:00
Translate-O-Tron 585a34d27e New Crowdin updates (#3535) 2022-05-19 08:05:35 -07:00
Tom Moor 3c002f82cc chore: Centralize env parsing, validation, defaults, and deprecation notices (#3487)
* chore: Centralize env parsing, defaults, deprecation

* wip

* test

* test

* tsc

* docs, more validation

* fix: Allow empty REDIS_URL (defaults to localhost)

* test

* fix: SLACK_MESSAGE_ACTIONS not bool

* fix: Add SMTP port validation
2022-05-19 08:05:11 -07:00
Corey Alexander 51001cfac1 feat: Migrate allowedDomains to a Team Level Settings (#3489)
Fixes #3412

Previously the only way to restrict the domains for a Team were with the ALLOWED_DOMAINS environment variable for self hosted instances.
This PR migrates this to be a database backed setting on the Team object. This is done through the creation of a TeamDomain model that is associated with the Team and contains the domain name

This settings is updated on the Security Tab. Here domains can be added or removed from the Team.

On the server side, we take the code paths that previously were using ALLOWED_DOMAINS and switched them to use the Team allowed domains instead
2022-05-17 20:26:29 -04:00
Tom Moor 18e0d936ef feat: Match incoming search requests using confirmed email as fallback (#3538) 2022-05-17 13:49:23 -07:00
Limezy 5658090d7e Trying to chase missing translations (#3441) 2022-05-17 13:01:00 -07:00
Tom Moor 19de348c85 fix: null ref usage, closes #3456 2022-05-16 22:58:59 +01:00
Tom Moor b8a02df7ba chore: utils.gc -> cron.daily (#3543) 2022-05-16 12:44:22 -07:00
Tom Moor 4c15f27bb2 fix: Focus submit button by default in confirmation dialogs
fix: Move collection delete to use confirmation dialog
closes #3446
2022-05-15 16:21:42 +01:00
Tom Moor b152b9f17b fix: Possible extra separator in filtered context menus
Todo: We need to combine this logic with the menus in the editor, but not today
closes #3506
2022-05-15 15:40:49 +01:00
Tom Moor 40e41b26a1 fix: Missing not found page
closes #3476
closes #3531
2022-05-15 15:10:34 +01:00
Translate-O-Tron 4c01f6268e New Crowdin updates (#3462) 2022-05-15 06:46:40 -07:00
Tom Moor 8815a58ff5 perf: Requesting less db columns when calculating collection permissions (#3498)
perf: Not looping collection documentStructure for unpublish permission calculation
2022-05-15 06:46:24 -07:00
Tom Moor 36a3ae4b01 fix: Don't show suspended users in document facepile or list of viewers (#3497) 2022-05-15 06:05:40 -07:00
Tom Moor bca66f7415 fix: Exports show as 0 bytes 2022-05-15 07:10:35 +01:00
Tom Moor 06d966ad0c fix: Spacing on login form
fix: signup query params overridden unneccessarily
closes #3516
2022-05-15 06:57:35 +01:00
Tom Moor c205ffbfe9 Merge branch 'main' of github.com:outline/outline 2022-05-11 09:30:08 +01:00
Tom Moor b75a6928cb Revert "fix: Fade out navigation when editing and mouse hasn't moved (#3256)" (#3502)
This reverts commit e0cf873a36.
2022-05-06 13:28:37 -07:00
Tom Moor 0ba792317b Merge branch 'main' of github.com:outline/outline 2022-05-06 13:01:15 -07:00
Saumya Pandey e0cf873a36 fix: Fade out navigation when editing and mouse hasn't moved (#3256)
* fix: hide header when editing

* fix: settings collab switch

* Update app/hooks/useMouseMove.ts

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* fix: accept timeout parameter

* fix: don't hide observing banner

* fix: hide on focused and observing

* perf: memo

* hide References too

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-05-07 00:17:09 +05:30
Tom Moor 1782c08195 fix: Touch lastViewedAt timestamp on document to prevent flash of order repositioning 2022-05-05 23:51:47 -07:00
Tom Moor d9e7baf072 chore: Update caniuse browser support 2022-05-05 22:29:10 -07:00
Tom Moor ec1bc801a4 fix: Write revision on document publish 2022-05-04 22:03:04 -07:00
Nan Yu 9117b7479f fix: paginated list history headings were not rendering when there was only one unique heading (#3496)
* fix: paginated list history headings were not rendering when there was only one unique heading

* minor bug
2022-05-04 21:08:50 -07:00
Tom Moor eeb8008927 chore: Refactor collection export to match import (#3483)
* chore: Refactor collection export to use FileOperations processor and task

* Tweak options
2022-05-01 21:06:07 -07:00
Tom Moor 669575fc89 fix: Account for null collection.documentStructure again 2022-05-01 09:30:47 -07:00
Felix Heilmeyer 247208e5f5 feat: make ioredis configurable via environment variables (#3365)
* feat: expose ioredis client options

* run linter

* refactor redis client init into class extension

* explicitly handle constructor errors

* rename singletons
2022-05-01 08:44:35 -07:00
Tom Moor 25dce04046 perf: Move collection sorting to frontend (#3475)
* perf: Move collection sorting to frontend, on demand, memoized

* fix: Add default
2022-05-01 08:30:16 -07:00
Tom Moor 5cd4ecd34a fix: CRDT creation touches document updated timestamp (#3482)
fix: Race condition in collaboration document persistence
2022-05-01 08:30:07 -07:00
Tom Moor bb074edb0d perf: Improve speed of Azure login (parallelize two slow API requests)
chore: Improved types around passport
2022-04-30 16:57:58 -07:00
Tom Moor a736022c39 chore: cleanup 2022-04-30 09:10:35 -07:00
Emir Boyacı 677ca10b2b chore: fix i18n type error (#3473) 2022-04-29 22:57:10 -07:00
Tom Moor 32c1d2e2f8 fix: Opensearch should mirror correct team subdomain
closes #3470
2022-04-29 22:53:39 -07:00
Tom Moor c7e4f491eb fix: Correctly escape RegExp in import tasks
closes #3460
2022-04-27 23:58:01 -07:00
Tom Moor 5f6b6e2879 Turkey -> Turkish 2022-04-27 22:46:17 -07:00
Tom Moor 7aeb9c2cd2 chore: cleanup ApiClient 2022-04-27 22:45:01 -07:00
Tom Moor 4177031d0b fix: Collection names with slashes produce invalid export output
closes #3368
2022-04-27 19:33:36 -07:00
Tom Moor 7fa0199dca fix: Applying a template should not overwrite an existing title
closes #3430
2022-04-27 19:18:45 -07:00
Tom Moor 78da5e2335 fix: Navigate to settings should not be displayed to non-admins
closes #3432
2022-04-27 19:12:38 -07:00
Tom Moor 964b4ef97d fix: Allow authorized signups to hosted-only setting 2022-04-27 19:04:06 -07:00
Tom Moor d8fed83736 chore: Add tracing around key presenters 2022-04-27 18:59:17 -07:00
Tom Moor 576497eca1 feat: Allow override default Task options on schedule 2022-04-27 18:54:54 -07:00
Tom Moor 4fd0307814 Revert: Enable web search query syntax 2022-04-26 21:34:33 -07:00
Corey Alexander 2449434fef feat: Allow Document to be fetched without Slug (#3453)
* Allow Document to be fetched without Slug

Fixes #3423

This PR refactors the `Document.findByPk` method to not require the
`slug` portion of the urlID.

Before this function accepted two different 'formats' for the ID.

 - The `uuid` ID of the Document
 - The full `urlID` which looked something like
   `some-document-1234567890`

However the `some-document` slug portion of this identifier wasn't
actually used when looking for a document.

We now allow searching by JUST the postfix of the `urlID`, in the above
example that is `1234567890`.
We do this via a new Regex pattern to match on that just looks for the
right looking id alone, without the prefix.

This codepath looks the same as when we find it by the full `urlID`
besides the different regex that we match on.

The issue #3423 mentions that this should apply to all the API
endpoints. I believe that this `findByPk` method is all that should be
needed for that change. But if this is incorrect, OR you would like more
test coverage on the API endpoints as a more 'end to end test' please
let me know!

* Change original regex to make the slug optional

This has the, I believe to be good, side-effect of making the same logic
apply to `Collection` as well. Since `Collection` was always doing the
same stripping of the slug before the lookup I believe it should be just
as safe to do there.

We don't have to touch the code in Collections but we add a test of this
behavior there as well.

* No reason to rename this now that we aren't doing two matches
2022-04-26 20:49:37 -07:00
Tom Moor 11477a1185 chore: Centralize clientside logging 2022-04-25 23:31:30 -07:00
Tom Moor 38409ff4ec fix: Enable web search query syntax 2022-04-25 21:58:24 -07:00
Tom Moor 2a11a23d5b fix: Updated design of api tokens to clarify, closes #3422 2022-04-25 21:34:36 -07:00
Tom Moor e49897ab5a fix: Account for rare case where file.name is unavailable 2022-04-25 21:13:06 -07:00
Tom Moor ceebc922cf fix: Error attempting to import .docx files, closes #3455 2022-04-25 21:07:22 -07:00
Tom Moor 7436d4c5c1 fix: Truncate stored error message for file ops
closes #3459
2022-04-25 21:00:31 -07:00
Tom Moor 5cbea1eab2 feat: Add Turkish translations
closes #3461
2022-04-25 20:07:49 -07:00
Translate-O-Tron 93f770c4d4 New Crowdin updates (#3377) 2022-04-25 17:16:23 -07:00
Tom Moor fcd4a2566a Merge branch 'main' of github.com:outline/outline 2022-04-23 18:33:25 -07:00
Tom Moor 0cdf1f791e fix: Permission select should have border 2022-04-23 18:33:14 -07:00
Gerardo Mathus 19ffff6fd2 Allow Downloads From Embeds (#3447)
* add flag to iframe

* ignore changes

* remove double space
2022-04-23 17:28:35 -07:00
Limezy 044d551b60 fix : translation strings in DocumentMeta component (2955) (#3417)
* fix issue 2955

* Linter

* Linter

* Linter

* Fix stupid mistake to run my own tests
2022-04-23 10:12:38 -07:00
github-actions[bot] 26d4040cb5 chore: Compressed inefficient images automatically (#3443)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2022-04-23 10:12:23 -07:00
Limezy 3b62c76207 Add tldraw embed (#3439)
* Test Tldraw embed

* Correct regex

* Correct alt for image

* Resize image to 120x120
2022-04-23 10:10:33 -07:00
Tom Moor 33ce49cc33 chore: Refactor data import (#3434)
* Complete refactor of import

* feat: Notion data import (#3442)
2022-04-23 10:07:35 -07:00
Tom Moor bdcfaae025 fix: Timestamps updated on closing document 2022-04-20 10:43:18 -07:00
Tom Moor 0245451501 perf: Caught a debounced hook re-rendering continously 2022-04-20 08:44:17 -07:00
Maksim Eltyshev e162e67396 ref: Fix small typo (#3428) 2022-04-20 08:11:40 -07:00
Nan Yu 233f3af667 feat: allow admins to require invites before user accounts can be created (#3381)
* allow admins to require invites before user accounts can be created
* use new dialog component for general confirmation dialogs
2022-04-19 12:27:23 -07:00
Tom Moor 1b913054e8 chore: Move i18n generation, pre-commit hooks (#3410) 2022-04-17 13:29:08 -07:00
Tom Moor b10802a0aa fix: Document empty placeholder changes when focused 2022-04-17 11:58:46 -07:00
Tom Moor 48893f727e fix: Tabs on document references don't show active state
'Referenced by' -> 'Backlinks'
2022-04-17 11:42:55 -07:00
Tom Moor 2fb0182e16 tom/use-event-listener 2022-04-17 11:00:28 -07:00
Tom Moor e4e98286f4 fix: Embed disabled state should persist (#3407)
* Normalize code around localStorage
Persist disabled embed state

* fix: Cannot view more than 10 starred items on load

* More tidying of sidebar state
2022-04-17 10:24:40 -07:00
Tom Moor 1e1a57d246 chore: Move document embed switching to toggle 2022-04-16 21:22:45 -07:00
Tom Moor b1aba32b62 chore: Bringing across edits from enterprise codebase 2022-04-16 19:46:01 -07:00
Tom Moor 0b5e48621a fix: Show resizable border on long-hover 2022-04-16 19:22:24 -07:00
Tom Moor 5b0a45c159 fix: Entirety of document title should have text cursor 2022-04-16 18:47:59 -07:00
Tom Moor 0883a56311 feat: Additional embed integrations (#3398)
* feat: Gliffy integration

* feat: JSFiddle integration

* feat: Otter.ai integration

* Optimised images with calibre/image-actions

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-04-16 15:04:49 -07:00
Tom Moor 4c4b80ba9b fix: Collaboration debounce shared between docs (#3401)
* fix: Collaboration debounce shared between docs

* Rename, Tracing -> Metrics

* Add tracing

* tsc

* fix: Lock document row when loading document in collaboration service incase state needs writing

* fix: Incorrect service name regression
2022-04-16 14:58:17 -07:00
Tom Moor 1a8f2c3bb0 Update LICENSE 2022-04-15 17:24:14 -07:00
Tom Moor c4046b1be5 0.63.0 2022-04-15 17:23:50 -07:00
Tom Moor cf58d8e3e1 fix: Capture drop events in clickable padding below editor (#3376)
* fix: Capture drop events in clickable padding below editor

* fix: Inconsistency in drop handling
2022-04-15 09:03:25 -07:00
Tom Moor 0ecfa95efc fix: Search params are not considered on first load
closes #3378
2022-04-14 17:50:20 -07:00
Tom Moor 7f58fbe71b fix: Save title change immediately on field blur
closes #3374
2022-04-13 16:26:22 -07:00
Tom Moor 9e08717d25 feat: Two more cases of typing in code marks, closes #3375 2022-04-13 15:17:47 -07:00
Translate-O-Tron 5c7ebea14b New Crowdin updates (#3345) 2022-04-13 08:59:57 -07:00
忽如寄 9fe5148113 feat: refactor resolve ♻️ (#3358)
Change-Id: Ib229549e114db67b04f2039b80c9015f78310cc8
2022-04-13 08:59:41 -07:00
Tom Moor f23f0d57de fix: Link editor should reset when selection changes
closes #3362
2022-04-13 08:55:43 -07:00
Tom Moor d3ecab3489 fix: Lowercase email from auth providers to match any outstanding invites (#3369)
* fix: Lowercase email from auth providers to match any outstanding invites

* fix
2022-04-12 21:31:55 -07:00
Tom Moor 1de732c82a fix: CommandMenu height when filtered 2022-04-12 20:58:39 -07:00
Tom Moor abbc3bdb30 fix: Consistent menus in editor (#3363)
* Use scrollable in context menu

* fix: Remove old blockToolbar styles
2022-04-12 20:12:45 -07:00
Tom Moor 86f1645199 feat: Automatic invite reminder email (#3354)
* feat: Add user flags concept, for tracking bits on a user

* feat: Example flag usage for user invite resend abuse

* wip

* test

* fix: Set correct flag
2022-04-12 20:12:33 -07:00
Nan Yu 5520317ce1 fix: prevent the interactive gutter elements from interfering with the sidebar collapse button (#3350)
* fix: prevent the interactive gutter elements from interfering with the sidebar collapse button

* keep mobile padding the same on documents

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-04-11 19:48:05 -07:00
Tom Moor 7f5bf6c6b3 feat: User flags (#3353)
* feat: Add user flags concept, for tracking bits on a user

* feat: Example flag usage for user invite resend abuse
2022-04-11 19:42:50 -07:00
Tom Moor 11c009bdbf fix: Don't create new document when opening browser window with cmd+n 2022-04-11 08:08:13 -07:00
Tom Moor f399c9d38c chore: More tracing cleanup 2022-04-11 08:04:13 -07:00
Tom Moor 27597727ee chore: More tracing cleanup 2022-04-10 20:11:18 -07:00
Tom Moor 31b95b5f17 fix: BaseProcessor should not be pushed onto queues 2022-04-10 20:05:59 -07:00
Tom Moor 963475d2b0 fix: Queue retry behavior (#3359)
* fix: Queue retry behavior

* Add default options for task queue
2022-04-10 17:50:42 -07:00
Nan Yu cfa71762c2 feat: adds "/" keyboard shortcut to share, focus content body on search selection (#3347)
* feat: adds "/" keyboard shortcut to focus search input on share screen; auto-focus content body on search item selection

* usekeydown instead of registerkeydown
2022-04-10 07:54:02 -07:00
Tom Moor 4de0389055 Update config.yml 2022-04-10 07:46:31 -07:00
Yggdrasil80 9390434dde feat: add arm64 docker image build (#3262)
* Add arm64 docker image build

* add arm64 docker image build

* fix: install missing docker buildx

* fix: new cimg orbs not working with this config

* fix misstake on qemu image name

* fix node:16 image not supported on arm/v5 and arm/v6

* add timeout to avoir errors

* fix docker buildx multiarch auto removing

* remove useless platforms, and keep only most used to reduce CI duration

* fix context issues

* fixed multiarch CI
2022-04-10 07:45:57 -07:00
Tom Moor b7a6a34565 fix: Flash of empty state on paginated lists (#3351)
* fix: Flash of empty state on paginated lists
fix: Typing of PaginatedList to generic

* test

* test
2022-04-09 20:31:51 -07:00
Tom Moor 9281287dba one 2022-04-09 20:25:54 -07:00
Tom Moor 48fad5cfa0 fix: Link preview and search should work on collection descriptions (#3355) 2022-04-09 19:00:56 -07:00
Tom Moor a47427de9e fix: Tweak commit message for calibre action to be semantic 2022-04-09 18:56:21 -07:00
github-actions[bot] e40f106dbb Compress Images (#3356)
Co-authored-by: tommoor <tommoor@users.noreply.github.com>
2022-04-09 18:55:52 -07:00
Tom Moor b82176bae4 fix: Replace example in github workflow config 2022-04-09 18:52:07 -07:00
Tom Moor 2d159d683b chore: Add auto image compression action 2022-04-09 18:49:34 -07:00
Tom Moor 8f23504c64 fix: Archived documents should be filtered from getChildDocumentIds when searching and loading share data (#3352)
closes #3343
2022-04-09 18:34:18 -07:00
Tom Moor ae34570648 chore: Add metrics logging for emails 2022-04-09 15:09:01 -07:00
Tom Moor 5c1888b0a4 feat: Adds menu item to resend outstanding invites (#3348)
* feat: Adds menu item to resend outstanding invites

* i18n

* snapshots
2022-04-09 11:34:27 -07:00
Nan Yu 75a868e5e8 feat: Search shared documents (#3126)
* provide a type-ahead search input on shared document pages that allow search of child document tree
* improve keyboard navigation handling of all search views
* improve coloring on dark mode list selection states
* refactor PaginatedList component to eliminate edge cases
2022-04-08 10:40:51 -07:00
Tom Moor 5fb5e69181 fix: Use of lookbehind regex crashes Safari, added lint rule to prevent future accidental regression 2022-04-08 10:16:55 -07:00
Tom Moor 58a059ae33 fix: CI should fail if yarn.lock is out of date 2022-04-08 08:49:34 -07:00
Tom Moor 1f93027c97 feat: Add date and time slash commands to block menu 2022-04-07 18:50:50 -07:00
Tom Moor 63ed015a86 fix: Loosen italic markdown matching a little
see: https://github.com/outline/outline/discussions/3336
2022-04-07 17:33:15 -07:00
Tom Moor 902cef8100 docs 2022-04-07 17:00:25 -07:00
Translate-O-Tron 6aa680a41d New Crowdin updates (#3258) 2022-04-07 16:51:23 -07:00
Tom Moor 5c24f9e1d5 chore: Email + mailer refactor (#3342)
* Huge email refactor

* fix: One rename too many

* comments
2022-04-07 16:50:04 -07:00
Tom Moor 15375bf199 fix: users.info request flood (#3334)
* feat: Add user id filter to users.list endpoint

* fix: Remove users.info request loop
2022-04-06 22:00:11 -07:00
Tom Moor 9b5df51625 chore: Add APM tracing around queues 2022-04-06 21:59:52 -07:00
Tom Moor f10cfbbd9e fix: Missing user scope in collection mailer 2022-04-06 21:35:45 -07:00
Tom Moor 4f358032eb chore: CircleCI Images (#3341)
* chore: Upgrade from deprecated images

* img

* fix: No default postgres user/pass anymore

* parallel

* config

* migrate

* split frontend/backend tests

* fix

* resource_class

* node

* node
2022-04-06 20:59:40 -07:00
Tom Moor 448f94ed04 fix: Allow admin edit/update access to all collections (#3335)
* fix: Allow admin edit/update access to all collections

* test
2022-04-06 16:49:07 -07:00
Tom Moor dbfdcd6d23 chore: Refactor worker, emails and data cleanup to task system (#3337)
* Refactor worker, all emails on task system

* fix

* lint

* fix: Remove a bunch of expect-error comments in related tests

* refactor: Move work from utils.gc into tasks

* test

* Add tracing to tasks and processors
fix: DebounceProcessor triggering on all events
Event.add -> Event.schedule
2022-04-06 16:48:28 -07:00
Tom Moor 9c766362ed fix: Hanging separators in filtered block menu 2022-04-04 22:35:28 -07:00
Tom Moor 10fff7811f fix 2022-04-04 22:01:58 -07:00
Tom Moor cefceaac3e chore: Combine z-index from editor 2022-04-04 21:50:52 -07:00
Tom Moor 0d87de9f80 fix: Hide document popover on mobile 2022-04-04 21:32:31 -07:00
Tom Moor 2e41ace386 refactor: Move depths and breakpoints out of theme 2022-04-04 21:20:38 -07:00
Tom Moor 20a69b711a fix: Some spots where navigation state was not preserved
fix: Collection in main nav pops open when moving from starred collection
2022-04-04 19:04:28 -07:00
Tom Moor 26b5fa82e3 fix: Heroku post-deploy overwrites default locale file 2022-04-04 18:23:34 -07:00
Tom Moor b50c7beba3 fix: Migrations should account for old rows 2022-04-03 20:16:09 -07:00
Tom Moor 84d6bf8ddf feat: Add ability to star collection (#3327)
* Migrations, models, commands

* ui

* Move starred hint to location state

* lint

* tsc

* refactor

* Add collection empty state in expanded sidebar

* Add empty placeholder within starred collections

* Drag and drop improves, Relative refactor

* fix: Starring untitled draft leaves empty space

* fix: Creating draft in starred collection shouldnt open main

* fix: Dupe drop cursor

* Final fixes

* fix: Canonical redirect replaces starred location state

* fix: Don't show reorder cursor at the top of collection with no permission to edit when dragging
2022-04-03 18:51:01 -07:00
Tom Moor 3de06b8005 fix: Missing separtor between notices and integrations in block menu
fix: Memory leak in block menu

closes #3330
2022-04-03 17:07:55 -07:00
Tom Moor cf71fc1108 fix: Text relayout caused by external link decorations rendered async 2022-04-03 16:48:40 -07:00
Tom Moor 41579eb4bf fix: Cleanup totally empty drafts on leave (#3310)
* fix: Cleanup totally empty drafts on leave

* cleanup

* fix: Add check the doc has never been saved after creation when auto-deleting
2022-04-03 11:51:38 -07:00
Tom Moor 5cd002bb88 fix: Remove forced white background on self hosted team logo
closes #3315
2022-04-01 19:59:51 -07:00
Tom Moor 1b89959fc1 fix: Clarify language on magic link success message
closes #3242
2022-04-01 19:59:25 -07:00
Tom Moor fde053ebc8 fix: Add stricter validation around image file type uploads (#3324)
* fix: Add stricter validation around image file type uploads

* revert backend restrictions, we want to allow unsupported images as file attachments
2022-04-01 19:26:27 -07:00
Tom Moor aa05b483fd i18n 2022-04-01 18:40:03 -07:00
Tom Moor 4907169cfb fix: Hint when all invites were not sent
closes #3317
2022-04-01 18:04:13 -07:00
Tom Moor cca3d114ad fix: Clicking 'profile' option from account menu routes to blank screen 2022-04-01 17:55:46 -07:00
Tom Moor f48c86c56d fix: Improve paste handler parsing for more cases, specifically Google Docs (#3322) 2022-04-01 15:13:44 -07:00
Tom Moor d119ed8963 fix: :: symbols appearing between lines when pasting plaintext (#3323)
closes #3319
2022-04-01 15:13:34 -07:00
Tom Moor c66aca063e feat: Add patterns to insert current date and time into doc (#3309)
* feat: Add patterns to insert current date and time into doc

* Add commands to title input too

* lint: Remove console.log
2022-03-31 19:51:55 -07:00
Tom Moor 4c0cd3d893 perf: More decoration caching 2022-03-31 19:51:30 -07:00
Tom Moor f457bf2019 Remove hanging console.log 2022-03-31 19:45:49 -07:00
Tom Moor 7a1870f81f fix: Blockquote missing from editor extensions after refactor 2022-03-31 18:12:36 -07:00
Tom Moor a1f69b97b0 perf: Fix unneccessary re-rendering of link decorations affecting perf in documents with lots of links 2022-03-31 18:07:48 -07:00
Tom Moor a4c8c7d709 fix: Cannot edit icon in collection edit dialog
closes #3313
2022-03-31 12:26:06 -07:00
Ferran Celades 9fef7fc5ec feat: Adding Solidity support (#3303)
* Adding Solidity support

* Update CodeFence.ts

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-03-31 08:39:09 -07:00
Tom Moor fea5f69a38 fix: Potential for settings sidebar badge to read '-1 releases behind' 2022-03-30 21:28:16 -07:00
Tom Moor 6f2a4488e8 chore: Editor refactor (#3286)
* cleanup

* add context

* EventEmitter allows removal of toolbar props from extensions

* Move to 'packages' of extensions
Remove EmojiTrigger extension

* types

* iteration

* fix render flashing

* fix: Missing nodes in collection descriptions
2022-03-30 19:10:34 -07:00
Tom Moor c5b9a742c0 fix: Cannot import from app in shared 2022-03-30 18:21:45 -07:00
Tom Moor 6c25f8fc72 feat: Small confirmation dialogs (#3293)
* wip

* refinement
2022-03-30 17:11:19 -07:00
Tom Moor 7f3b602259 feat: Berrycast embed support 2022-03-30 17:09:19 -07:00
Tom Moor 7216551164 Update LICENSE 2022-03-29 09:46:30 -07:00
Nan Yu 096b35e08e chore: change the way that share permissions are checked on child documents to use the parentId field of documents rather than the collection structure (#3294) 2022-03-28 10:18:59 -07:00
Tom Moor 3d478246bf fix: Remove 'full width' option from document menu on mobile 2022-03-27 19:52:11 -07:00
Tom Moor 72614ea090 chore: Bringing some changes across from enterprise fork 2022-03-27 19:50:27 -07:00
dependabot[bot] 6fc7f7b287 chore(deps): bump minimist from 1.2.5 to 1.2.6 (#3295)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-27 19:26:56 -07:00
忽如寄 9f400af73b refactor: ♻️ refactor isHosted && type clean up (#3290)
* refactor: ♻️ refactor isHosted && type clean up

Change-Id: I4dfbad8a07607432801de78920ce42bf81e46498

* refactor: ♻️ code clean up

Change-Id: I8f487a33d332a2acaff84397a97371b56ace28a1

* feat: 💄 lint

Change-Id: I776b1a5e249bdb542f8e6da7cb2277821cf91094

* feat:  ci type

Change-Id: I486dde7bf60321238e9a394c40ad8cdb8bfc54c8

* feat: some code sugession

Change-Id: I4761d057344b95a98e99068d312a42292977875b
2022-03-27 15:18:37 -07:00
CommanderRoot f7b1f3ad6d refactor: replace deprecated String.prototype.substr() (#3285)
.substr() is deprecated so we replace it with .slice() which works similarily but isn't deprecated

Signed-off-by: Tobias Speicher <rootcommander@gmail.com>
2022-03-25 11:57:42 -07:00
Tom Moor 3d88ebc3d7 chore: New teams get collaborative editing by default 2022-03-24 19:15:38 -07:00
忽如寄 396836dedd refactor: ♻️ del children type (#3283)
* refactor: 🔧 del unnecessary children type

Change-Id: I3dea5e07f5401bdbdd168eb959fe361c57784167

* feat: 💄 eslint

Change-Id: Ie173adeca9e3112d8cdfc1f85964332105dcb424

* feat: 🔧 add css type

Change-Id: I8850c4d09b152f4d9c4d98e6eebca58bd9eecd37

* fix: 💄 ci lint

Change-Id: I69ff89c7a30e2bdcd26475ec83f3f5ec143121b6
2022-03-24 17:45:36 -07:00
Tom Moor 6af9246f26 feat: Allow disabling collection creation for members (#3270) 2022-03-24 16:02:50 -07:00
忽如寄 53d96d2cb3 refactor: ♻️ Flex type (#3282)
* refactor: ♻️ Flex type

Change-Id: I9043fa71a94c6d691e075b983c263be39b5a4b9b

* fix: 💄 eslint

Change-Id: I2c41ea588b8152a354998ec69ae85798cd6f3ff4

* fix: 💄 lint

Change-Id: I9467ca89b3a3c83dbfa0422869528e86db8d4fab
2022-03-24 15:57:11 -07:00
Tom Moor 8aa25fd7d6 fix: Add ability to convert between checklist and other types of list 2022-03-23 07:57:58 -07:00
Tom Moor 7f15eb287d fix: Redundant quotes
closes #3272
2022-03-22 23:20:53 -07:00
Tom Moor 5047be9898 fix: Attachments on public share links broken when using AWS Accelerate
fix: Attachments broken when using non-collab and AWS bucket on the same host
(https://github.com/outline/outline/discussions/3274\)
2022-03-22 22:58:29 -07:00
Tom Moor e6eb43144c chore: Hardcode service name for APM tagging 2022-03-18 22:15:56 -07:00
Tom Moor 04f1daeec9 fix: Do not enqueue event until db transaction committed 2022-03-18 22:06:26 -07:00
Tom Moor 3aaaf73a28 Add mouse safe area for when moving between contextual submenus 2022-03-18 20:53:41 -07:00
Tom Moor ff49c507db fix: Direct to contact page rather than mailto: link
closes #3265
2022-03-18 20:19:07 -07:00
Tom Moor dc9c45ef6c fix: Add extra span naming closes #3266 2022-03-18 20:12:49 -07:00
Tom Moor 4b626de24e perf: Add createdAt index to events table 2022-03-18 19:32:29 -07:00
Tom Moor 5e655e42f6 chore: documentStructure database locking (#3254) 2022-03-18 08:59:11 -07:00
Tom Moor c98c397fa8 feat: Add optional config of database connection pooling 2022-03-17 18:18:35 -07:00
Tom Moor 018593a6aa fix: Toasts hang on screen 2022-03-17 18:11:57 -07:00
Tom Moor 203980c845 fix: ARIA fixes, missing button labels 2022-03-16 23:41:06 -07:00
Tom Moor adb7e99321 i18n 2022-03-16 23:04:25 -07:00
Saumya Pandey 52358073e0 fix: settings collab switch 2022-03-16 15:18:24 -07:00
Tom Moor 76e1869ebf fix: Catch error when emoji combinations cause document to be unable to persist (#3250)
* fix: Catch and warn of rare error when emoji combinations cause document to be unable to persist changes
closes #3230

* addEventListener -> removeEventListener
2022-03-16 15:18:16 -07:00
Tom Moor a27af88d4a perf: Stop copying attachments when moving documents (#3251)
* perf: Stop copying attachments when moving documents

* lint
2022-03-16 15:18:04 -07:00
Nan Yu ac2a124714 fix: prevent history from crashing due to missing EditorView (#3257)
* put the editor into read only mode when examining history
2022-03-16 15:01:25 -07:00
Nan Yu d1b28499c6 chore: new arrow key navigation (#3229)
* rebuild keyboard navigation lists
* add new keyboard navigation components
* remove references to boundless-arrow-key-navigation
* fix aria-labels on paginated lists everywhere
2022-03-15 10:36:10 -07:00
Translate-O-Tron 093158cb11 New Crowdin updates (#3233) 2022-03-15 08:42:54 -07:00
dependabot[bot] 864e33959f chore(deps): bump lodash-es from 4.17.15 to 4.17.21 (#3246)
Bumps [lodash-es](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21)

---
updated-dependencies:
- dependency-name: lodash-es
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-15 08:42:07 -07:00
Tom Moor 15cecf1e53 Upgrade dd-trace, add APM tracing around key commands, fix tags should be attached to root spans (#3243) 2022-03-14 20:03:12 -07:00
Tom Moor f3705b4a22 fix: Tweaks to share links management 2022-03-14 20:02:26 -07:00
Tom Moor 896f3700d0 fix: Cannot useCurrentUser in Sidebar as it is used unauthenticated on shares 2022-03-14 18:35:37 -07:00
Tom Moor a08f433c24 fix: Small text under subdomain setting 2022-03-14 17:55:25 -07:00
Tom Moor d63326066f feat: Improve settings layout (#3234)
* Setup, and security settings

* Settings -> Details

* Settings -> Notifications

* Profile

* lint

* fix: Flash of loading on members screen

* align language input

* feat: Move share links management to sortable table

* Add account menu to sidebar on settings page

* Aesthetic tweaks, light borders between settings and slight column offset
2022-03-14 17:44:56 -07:00
Tom Moor 1633bbf5aa cleanup search documents action 2022-03-14 17:41:55 -07:00
Tom Moor 40e84ed481 i18n 2022-03-14 16:15:20 -07:00
Tom Moor 4fd48d9e4c fix: utils.gc constraint issue, closes #3228 2022-03-14 16:15:10 -07:00
Tom Moor de15f901b8 fix: Rare serialization error for image nodes without a src. Honestly not sure how these get inserted – perhaps API 2022-03-14 16:08:35 -07:00
Tom Moor 5977fe4caa fix: Editor title does not autoFocus on first load (#3238)
* fix: Editor title does not autoFocus on first load

* Detect IntersectionObserver for IE support
2022-03-13 22:08:26 -07:00
Tom Moor 10cc6ed154 fix: Sidebar cannot collapse after visiting settings (#3235) 2022-03-13 09:35:04 -07:00
Tom Moor da8714a4f6 chore: Drive settings sidebar from new config (#3236) 2022-03-13 09:34:50 -07:00
Saumya Pandey c979d003e4 fix: navigate to all the pages of settings through command bar (#3226)
* fix: create useAuthorizedSettingsConfig

* use config to render routes

* translations and icon

* mount in CommandBar

* memo

* Update app/hooks/useSettingsAction.tsx

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* fix: add actions into settings action

* remove comment

* fix: update shares

* fix: Remove Slack/Zapier from translations

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-03-13 09:38:36 +05:30
Tom Moor e30f6e937c fix: Automatically disable email sign-in when SMTP is not configured
fix: Do not show email signin as enabled when SMTP configured
closes #3227
2022-03-12 17:01:46 -08:00
Tom Moor f44b5708c3 fix: Show error when auth.config fails rather than blank screen, useful as part of self-hosted setup in particular 2022-03-12 16:17:29 -08:00
Translate-O-Tron f867704106 New Crowdin updates (#3176)
* fix: New French translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Korean 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 Chinese Simplified translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Thai 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 Chinese Simplified 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]
2022-03-12 15:46:25 -08:00
Tom Moor b7097654b5 chore: Allow Button s to take action prop (#3204)
* Add ability for NudeButton to take action+context

* Add example usage

* Refactor to ActionButton, convert another example

* Remove dupe label
2022-03-12 15:46:13 -08:00
Tom Moor d8104c6cb6 fix: Detect Pomerium proxy (#3219)
* chore: Remove unused DocumentList component

* fix: Add support for detecting Pomerium

* Refactor to avoid reading cookies on every request

* refactor: Just enable cookies for all self-hosted builds

* Remove unused userAgent

* test: Add window.env to mock
2022-03-12 15:45:57 -08:00
Tom Moor 36f90b3a46 perf: Additional missing index 2022-03-10 18:50:28 -08:00
Tom Moor 2ef827ee6f perf: Add teamId to search query to help with query planning 2022-03-10 18:13:18 -08:00
Tom Moor 503598e16d perf: Add missing indexes to views table 2022-03-10 18:10:33 -08:00
Tom Moor f36e18e3a6 perf: Document.state still queried in documents.search endpoint 2022-03-10 09:17:29 -08:00
Tom Moor fd9ef3ab22 perf: Document.state still queried in documents.search endpoint 2022-03-10 09:02:23 -08:00
Tom Moor d399e1048a perf: Don't load CRDT state from database by default (#3215) 2022-03-09 20:07:10 -08:00
Tom Moor 5efeb90fdd fix: SVGs without a natural px width are invisible (#3220) 2022-03-09 20:07:01 -08:00
Tom Moor 31e15f798c chore: Remove unused DocumentList component 2022-03-09 17:33:55 -08:00
Tom Moor c1e8b6c823 perf: Remove unneccessary join from documents.viewed 2022-03-08 16:51:47 -08:00
Tom Moor 79ba8dad30 chore: Improve tracing 2022-03-08 16:41:02 -08:00
Tom Moor 85f333b2fd fix: Finicky clicking on file attachments #2 2022-03-06 22:52:41 -08:00
Tom Moor 80be26b2de fix: Border of file attachment not rounded in Safari (outline -> box shadow) 2022-03-06 21:56:52 -08:00
Tom Moor 9a7090d528 fix: Finicky clicking on file attachments 2022-03-06 21:49:44 -08:00
Tom Moor cf446be2df fix: Dragging strings into document can attempt (and file) to insert as attachment 2022-03-06 21:47:30 -08:00
Tom Moor 631d600920 feat: File attachments (#3031)
* stash

* refactor, working in non-collab + collab editor

* attachment styling

* Avoid crypto require in browser

* AttachmentIcon, handling unknown types

* Do not allow attachment creation for file sizes over limit

* Allow image as file attachment

* Upload placeholder styling

* lint

* Refactor: Do not use placeholder for file attachmentuploads

* Add loading spinner

* fix: Extra paragraphs around attachments on insert

* Bump editor

* fix build error

* Remove attachment placeholder when upload fails

* Remove unused styles

* fix: Attachments on shared pages

* Merge fixes
2022-03-06 13:58:58 -08:00
Saumya Pandey 8b0b383e9e fix: don't hide sidebar when menu is open (#3203) 2022-03-05 23:00:41 +05:30
Tom Moor f69bcc7578 fix: Suppress errors from users that attempt to run saved pages from their local computer (happens a surprising amount) 2022-03-04 16:47:21 -08:00
Tom Moor edbcd3d4d2 fix: Tooltips on sidebar items are sometimes miss-positioned on mouseleave 2022-03-03 23:23:15 -08:00
Tom Moor 4f0ee2c3f8 fix: No reserved space for submenu arrow
fix: Submenu arrow miss-positioned when menu is scrollable
closes #3191
2022-03-03 22:40:12 -08:00
Tom Moor 7e930dd1c9 fix: Regression in actions background on sidebar links
closes #3194
2022-03-03 22:11:43 -08:00
Tom Moor d2848c9000 chore: Move to fork of y-prosemirror, new fixes and exposing updateYFragment method 2022-03-03 21:53:42 -08:00
Tom Moor 6dab8ead8e Merge branch 'main' of github.com:outline/outline 2022-03-03 21:51:40 -08:00
Tom Moor 03fdb846cd fix: Hide TOC toggle on publicly shared links if there are no headings in the document (#3172)
closes #3006
2022-03-03 21:46:53 -08:00
Tom Moor 111b78ffc4 fix: .env.sample should use standard ports 2022-03-03 21:31:27 -08:00
Tom Moor 4c5d22084f Update outline-icons with fixes 2022-03-03 07:37:23 -08:00
Tom Moor c2889950d5 i18n 2022-03-02 21:12:44 -08:00
Tom Moor 5e96145277 feat: Add support for S3 transfer acceleration 2022-03-02 21:12:38 -08:00
Tom Moor 4468d29740 perf: Navigation of shared trees feels slow (#3171)
* perf: Navigation of shared trees feels slow

* remove redundant call to setActiveDocument

Co-authored-by: Nan Yu <thenanyu@gmail.com>
2022-03-01 21:51:51 -08:00
Tom Moor 3ac125d560 0.62.0 2022-03-01 07:39:19 -08:00
Saumya Pandey 3115152dfd fix: editing collections should not forward to collection on save (#3187) 2022-03-01 12:22:29 +05:30
Tom Moor eb7f8a8da0 Revert command bar launch from Search sidebar 2022-02-27 23:53:59 -08:00
dependabot[bot] 21dd380d89 chore(deps): bump url-parse from 1.5.7 to 1.5.10 (#3181)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.7 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.7...1.5.10)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-27 20:44:05 -08:00
Tom Moor 4c138ed585 feat: Add "new doc" button on collections in sidebar (#3174)
* feat: Add new icon button on collections in sidebar, move sort into menu

* Remove unused menu, add warning when dragging in a-z collection

* fix: Add hover background to sidebar actions, add tooltip to new doc button

* Retain 'active' state on buttons when related context menu is open

* fix: Two more spots that deserve active background
2022-02-26 11:48:32 -08:00
Tom Moor 31c84d5479 fix: Reuse InputSearch style for move dialog (#3173)
closes #3121
2022-02-26 11:48:14 -08:00
Tom Moor 6cbc30172c fix: Search takes too much priority from cmd+k trigger 2022-02-26 11:47:48 -08:00
Tom Moor 7f05fe0127 chore: Combine 'pin' menu items into submenu
fix: Submenu should not appear when all items are not visible
2022-02-26 11:37:48 -08:00
Tom Moor 42bf1530ac fix: Missing padding at the bottom of settings screens 2022-02-25 21:21:10 -08:00
Saumya Pandey ad2bce9c10 fix: sync the correct collection with edit action (#3166)
* fix: sync the correct collection with edit action

* fix: remove action suggestions on undefined

* Update app/hooks/useCommandBarActions.ts

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-02-25 20:39:03 -08:00
Tom Moor ccacb65d9e fix: Inset icon in collection headers, minor ContentEditable refactor (#3168) 2022-02-25 20:38:46 -08:00
Tom Moor 7bb12b3f6d fix: Collection icons should retain color in menus 2022-02-23 22:40:34 -08:00
Tom Moor 4713ea3680 fix: Alignment of sidebar loading placeholders 2022-02-23 22:22:35 -08:00
Tom Moor 99d233c703 fix: Remove metadata on nested docs, use EmojiIcon component 2022-02-23 21:36:01 -08:00
Translate-O-Tron a777bbec16 New Crowdin updates (#3136)
* fix: New French translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Thai 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 French translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Thai translations from Crowdin [ci skip]
2022-02-23 21:33:43 -08:00
Tom Moor a3b8e7a65e chore: Quick refactor to usePolicy hook (#3161) 2022-02-23 21:33:18 -08:00
Saumya Pandey 4c95674ef0 fix: Add ability to collapse and expand collections that are not active (#3102)
* fix: add disclosure and transition

* fix: keep collections expanded

* fix: tune transition and collapsing conditions

* fix: collectionIcon expanded props is no longer driven by expanded state

* fix: sync issue

* fix: managing state together

* fix: remove comment

* fix: simplify expanded state

* fix: remove extra state

* fix: remove animation and retain expanded state

* fix: remove isCollectionDropped

* fix: don't use ref

* review suggestions

* fix many functional and design issues

* don't render every single document in the sidebar, just ones that the user has seen before

* chore: Sidebar refinement (#3154)

* stash

* wip: More sidebar tweaks

* Simplify draft bubble

* disclosure refactor

* wip wip

* lint

* tweak menu position

* Use document emoji for starred docs where available

* feat: Trigger cmd+k from sidebar (#3149)

* feat: Trigger cmd+k from sidebar

* Add hint when opening command bar from sidebar

* fix: Clicking internal links in shared documents sometimes reroutes to Login

* fix: Spacing issues on connected slack channels list

* Merge

* fix: Do not prefetch JS bundles on public share links

* fix: Buttons show on collection empty state when user does not have permission to edit

* fix: the hover area for the "collections" subheading was being obfuscated by the initial collection drop cursor

* fix: top-align disclosures

* fix: Disclosure color PR feedback
fix: Starred no longer draggable

* fix: Overflow on sidebar button

* fix: Scrollbar in sidebar when command menu is open

* Minor alignment issues, clarify back in settings sidebar

* fix: Fade component causes SidebarButton missizing

Co-authored-by: Nan Yu <thenanyu@gmail.com>

Co-authored-by: Tom Moor <tom.moor@gmail.com>
Co-authored-by: Nan Yu <thenanyu@gmail.com>
2022-02-23 21:26:38 -08:00
Tom Moor ce33a4b219 fix: Scrollbar in sidebar when command menu is open 2022-02-23 18:48:16 -08:00
Tom Moor 06ed6cfe9c fix: Buttons show on collection empty state when user does not have permission to edit 2022-02-22 23:57:46 -08:00
Tom Moor a24cb9987c fix: Do not prefetch JS bundles on public share links 2022-02-22 21:02:38 -08:00
Tom Moor 8832808fbe fix: Spacing issues on connected slack channels list 2022-02-22 20:14:07 -08:00
Tom Moor f244e864e1 fix: Clicking internal links in shared documents sometimes reroutes to Login 2022-02-22 20:14:07 -08:00
Tom Moor 63265b49ea feat: Trigger cmd+k from sidebar (#3149)
* feat: Trigger cmd+k from sidebar

* Add hint when opening command bar from sidebar
2022-02-22 20:13:56 -08:00
Tom Moor d75af27267 feat: Hold toast on screen while mouse over 2022-02-19 22:15:49 -08:00
Tom Moor c1df8c2162 Add danger background to dangerous menu items on hover (#3148)
closes #3105
2022-02-19 18:13:05 -08:00
Tom Moor 4b688e4ca0 fix: Minor styling issues on simple embeds 2022-02-19 11:14:45 -08:00
Saumya Pandey 5db73726f7 fix: create a generic notice component (#3144)
* fix: use unstable_fixed option

* fix: add icons in notice

* fix: create generic Notice component

* Refactor: Pull document notices into component

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-02-19 11:05:56 -08:00
Tom Moor 64d4462412 fix: Allow removing title via API
fix: Empty document title continously autofocuses
closes #3108
2022-02-19 09:10:06 -08:00
Tom Moor 34c5b60656 i18n 2022-02-18 18:23:26 -08:00
dependabot[bot] 2a6f640ebb chore(deps): bump url-parse from 1.5.3 to 1.5.7 (#3145)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.7.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.7)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-18 18:06:35 -08:00
Saumya Pandey e779f43d79 fix: use unstable_fixed option 2022-02-18 16:58:21 -08:00
Tom Moor 6815269372 fix: Regular clipping of metadata on pinned documents #critfeedback 2022-02-18 16:55:29 -08:00
Tom Moor d8a15b8389 fix: Height of user status filter on Members page 2022-02-18 08:59:53 -08:00
Tom Moor 72ca231931 fix: 'Never viewed' sometimes appears for document creators 2022-02-18 08:55:38 -08:00
Tom Moor b9c7694b21 Updated placeholders, minor editor tweaks 2022-02-18 08:42:24 -08:00
Tom Moor 2a0ff2fe41 fix: Truncated timestamps in document history sidebar, useless tooltip, confusing more menus #critfeedback 2022-02-17 23:42:05 -08:00
Tom Moor 2ca68c2c80 fix: Cancel editing shortcut on Windows
fix: Improve display of symbols in keyboard shortcuts dialog
closes #2733
2022-02-17 23:10:11 -08:00
Tom Moor 9db6951434 fix: Server side validation for #3112 2022-02-17 22:51:18 -08:00
Tom Moor 3d5bf56d09 fix: It is possible to have a recent search item with no content, closes #3112 2022-02-17 22:45:30 -08:00
Tom Moor 9588ffc81e fix: Timestamp under doc title should toggle history sidebar, closes #3120 2022-02-17 22:36:46 -08:00
Tom Moor df01e0dfbd fix: Disabled primary buttons should have a lighter appearance, closes #3110 2022-02-17 21:51:11 -08:00
Tom Moor 6a26e062d0 Round badges completely, tweak border #critfeedback 2022-02-17 21:46:47 -08:00
Tom Moor ab573ba02c Stars are now yellow instead of depressing grey 2022-02-17 21:39:58 -08:00
Tom Moor e109d5629f lint find and replace 2022-02-17 21:35:12 -08:00
Tom Moor d5763233ca HelpText -> Text 2022-02-17 20:59:40 -08:00
Tom Moor 4efdbf7253 fix: Inconsistent header padding, closes #3115 2022-02-17 20:45:43 -08:00
Tom Moor 261cac950b fix: Capture Tab within editor, remove custom key handling in favor of keymaps
closes #3118
2022-02-17 20:41:13 -08:00
Tom Moor 27f9172750 fix: Collection with only draft shows empty state, closes #3119 2022-02-17 20:17:02 -08:00
Tom Moor cbe65ddcd7 fix: Clicking links when editor hasn't been focused should navigate 2022-02-17 20:08:04 -08:00
Tom Moor b23f7b0953 fix: Allow private, domain-restricted, Vimeo embeds 2022-02-17 09:12:02 -08:00
Translate-O-Tron 196c59f34c New Crowdin updates (#3085)
* fix: New French translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Persian translations from Crowdin [ci skip]
2022-02-16 18:06:08 -08:00
Tom Moor d7ee801fe4 feat: Show icon on external links (#3100)
* feat: External links get treatment

* cache decorations
2022-02-16 18:05:02 -08:00
Nonpawit Teerachetmongkol 3760a03c44 feat: Add DBdiagram (dbdiagram.io) embed (#3124)
* Add dbdiagram embed

* clean variable name
2022-02-16 18:04:44 -08:00
Tom Moor 7e216109dc fix: Remove single-usage restriction on magic link tokens as these were consumed by link scanning software 2022-02-16 13:15:06 -08:00
Tom Moor 229f01513c fix: Export includes documents that have identical names (#3098) 2022-02-12 13:35:57 -08:00
Tom Moor 289f01970f fix: 'Alt' should be displayed as '⌥' on Mac 2022-02-12 09:16:17 -08:00
Tom Moor 0c716bf974 fix: Disable <a> as button showing default button styles in Safari only, closes #3101 2022-02-12 09:01:11 -08:00
Tom Moor 7807e3ac03 fix: Todo list items not showing as checked on Firefox 2022-02-12 08:45:04 -08:00
Tom Moor f4af702492 lint 2022-02-11 18:55:39 -08:00
Tom Moor 4255dd24da editor: Open link toolbar automatically when editable and link in selection 2022-02-11 18:34:56 -08:00
Tom Moor 2dd86bbc2b fix: Flash of uncolored pinned documents if pinned docs load before collections 2022-02-11 18:22:21 -08:00
Tom Moor 09810f554f fix: Private vimeo embeds 2022-02-11 16:20:57 -08:00
Tom Moor e5c8176ee6 Update email.ts 2022-02-10 21:20:58 -08:00
Tom Moor 25568c101c improves: Make command menu larger, darken toolbar, order image + link higher up menu 2022-02-10 20:15:28 -08:00
Tom Moor 590c23d539 Focus link selection on click rather than navigate when editing 2022-02-10 20:00:50 -08:00
Tom Moor b5424f7af4 deps: Update refractor 2022-02-10 19:40:58 -08:00
Tom Moor 25fd8466e0 perf: Move to passive scroll listeners where supported 2022-02-10 19:29:25 -08:00
Tom Moor af6c5a1f45 fix: Email authentication callback catches all errors as expired-token 2022-02-10 19:18:06 -08:00
Tom Moor 652f432785 fix: Mod+Enter does not exit code block
closes #3089
2022-02-10 19:14:10 -08:00
Tom Moor d1e805dfc8 fix: Link to export page in admin section to avoid redirect 2022-02-09 23:00:43 -08:00
Saumya Pandey 42061edbd1 feat: add the ability to choose default collection (#3029)
Co-authored-by: Tom Moor <tom@getoutline.com>
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-02-10 10:06:10 +05:30
Tom Moor 9dfd1ec2dd chore: Dependency updates (#3084)
* Update node-fetch, i18next-http-backend

* Update nodemon

* Update react-refresh-webpack-plugin, remove old ansi-html dep
2022-02-09 20:29:28 -08:00
Tom Moor b3f33c1101 perf: Remove withStarred scope and starred property on documents
closes #3081
2022-02-09 19:51:51 -08:00
Tom Moor 5bc4405b23 fix: Alignment of team name in settings header, closes #3083 2022-02-09 19:47:57 -08:00
Tom Moor a578d3449b fix: Copy/paste of notices, closes #3082 2022-02-09 19:43:15 -08:00
Tom Moor 8490cab9b1 fix: Export collections produces empty zip, regressed in #3064 2022-02-09 19:40:40 -08:00
Tom Moor 9da493902c lint 2022-02-08 23:14:54 -08:00
Tom Moor 193ca910f8 Remove Permissions-Policy header, FLOC has now been abandoned 2022-02-08 23:06:04 -08:00
Tom Moor f42a09be0d fix: Reduce movement of Home header on first load 2022-02-08 22:46:24 -08:00
Tom Moor 4e0f3e79c5 fix: Expired export state missing icon 2022-02-08 22:40:17 -08:00
Tom Moor 9d77baccfd fix: Pinned documents animate out when navigating between collections 2022-02-08 22:21:16 -08:00
Tom Moor 9cf3469b81 fix: Even more flexibility in LucidChart embed matching. It really is incredible how many variations this company has for share urls.
closes #3074
2022-02-08 22:11:35 -08:00
Tom Moor bc2556d004 fix: Document title allows pasting rich text, closes #3079 2022-02-08 22:07:53 -08:00
Translate-O-Tron 342bec5211 New Crowdin updates (#2988)
* fix: New Vietnamese translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New Korean 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 French translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New German 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 French translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* fix: New French translations from Crowdin [ci skip]
2022-02-08 21:15:02 -08:00
Tom Moor 156b47b1b5 fix: Auth persistence to localStorage (#3078)
* fix: user, team, and policies should be persisted to localStorage for faster boot

* capture instead of ignore errors
2022-02-08 21:14:15 -08:00
Tom Moor aa09dc39fb fix: NudeButton should always have button height 2022-02-08 20:22:08 -08:00
Tom Moor d643c9453e feat: Import improvements (#3064)
* feat: Split and simplify import/export pages in prep for more options

* minor fixes

* File operations for imports

* test

* icons
2022-02-06 22:29:24 -08:00
Tom Moor a4e9251eb7 fix: Images no longer in original document not included in export archive (#3063)
closes #2578
2022-02-05 17:13:02 -08:00
Tom Moor 1bb57bf15a fix: Theme changes do not propagate to custom editor components in realtime
see TODO in #3031
2022-02-05 15:48:17 -08:00
Tom Moor c5a11fe17b chore: Enable eslint to enforce curly (#3060) 2022-02-05 10:15:40 -08:00
Tom Moor c7df74fcc4 fix: Improvements to image positioning (#3061)
* fix: Empty paragraph below images that confuses block insertion

* Remove spacing for caption when unused
2022-02-05 10:14:10 -08:00
Nan Yu ae0644177b fix: make mobile popover dialog styling nice (#3059)
* fix: make mobile popover dialog styling nice
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-02-04 16:32:22 -08:00
Tom Moor 4cc7af7874 fix: Do not parse 😄 style emoji in Markdown paste handler (#3056) 2022-02-04 07:37:18 -08:00
Tom Moor 0bee0bbade fix: Remap event name for Slack integration 2022-02-02 21:31:51 -08:00
Saumya Pandey b14867c67e fix: error from api rate limiting (#3050) 2022-02-03 09:13:46 +05:30
Tom Moor c10236f7a9 fix: ESC on shared docs goes to login page, closes #3044 2022-02-01 21:33:17 -08:00
Nan Yu 735aaa668a fix: add toc to mobile views and account for branding on shared view layouts (#2997)
* fix: add toc to mobile views and center the branding

* add padding to bottom of sidebar

* put the mobile branding inline

* finesse the padding

* make spelling of sign-in email less crazy looking

* move mobile sidebar button into header

* adds scene to search and 404 pages

* fix title alignment

* make filter buttons tight

* clean up unused imports

* lint

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-02-01 20:58:24 -08:00
Louis Phan 516e2f1b6e fix: issue 3030 HelpText layout (#3034)
* fix helptext layout

* remove unnecessary css property - word-break

Co-authored-by: Louis Phan <louisphan@notreallouisss.local>
2022-02-01 16:36:40 -08:00
Tom Moor 2d1c9c1a93 fix: Regression in header spacing 2022-01-31 23:11:10 -08:00
Tom Moor cc19e45caf fix: list editing regression (#3041)
* working state

* Selective deps upgrade, still working

* Update more deps, still working

* fix: Tweak checkbox items too bright while we're here

* Avoid prosemirror-view downgrade
2022-01-31 22:01:48 -08:00
Tom Moor 187f036c80 fix: Editing image caption broken 2022-01-30 20:45:52 -08:00
Tom Moor fac86a2a28 fix: Don't show share button on trashed docs
closes #2999
2022-01-28 21:59:29 -08:00
Tom Moor 26c73116b0 fix: Prevent navigation of document history in trash, closes #2995 2022-01-28 21:44:42 -08:00
Tom Moor eafb9c5225 fix: Truncate long titles in import 2022-01-28 21:00:52 -08:00
Tom Moor 76d83b5e82 Remove duplicative Toggle component (#3028)
fix: Tidy some styling and spacing issues in settings
2022-01-28 20:23:02 -08:00
Tom Moor 1cd770e38d fix: Disabling editor embeds should work with collaborative editing (#2968)
* fix: Disabling editor embeds should work with collaborative editing

* Design tweaks, fixed dragging
2022-01-28 18:27:27 -08:00
Tom Moor e7867e52e0 chore: Database index improvements (#3027) 2022-01-27 19:51:31 -08:00
Tom Moor 0203b2bc17 fix: Ensure copy code button appears in collab editing (#3021)
* fix: Ensure copy code button appears in collab editing

* fix: code actions should not flip in RTL doc (code is always left aligned)
2022-01-27 17:14:47 -08:00
Tom Moor bcd6e17781 fix: Cannot view history with view-only permissions and collab editing enabled (#3024)
closes #3016
2022-01-27 17:14:36 -08:00
Tom Moor 051d58011e fix: Regression in collapsible headings
closes #3010
2022-01-27 08:00:57 -08:00
Tom Moor 6d987975bc lint 2022-01-27 07:55:02 -08:00
Tom Moor 16277d1074 fix: Document search results in editor now show full path
closes #3007
2022-01-27 07:29:59 -08:00
Tom Moor 76e98c31e3 fix: Team logo shows as white in settings (#3015)
* fix: Team logo shows as white in settings
fix: Team logo doesnt update in sidebar immediately after updating
refactor to ImageUpload component

* text
2022-01-26 22:47:26 -08:00
Tom Moor afb0dad0a5 fix: Code block background on mobile, closes #2998 2022-01-26 21:17:10 -08:00
Tom Moor af8e74c373 fix: Should be able to unstar archived and trashed documents (#2983) 2022-01-26 19:39:06 -08:00
Saumya Pandey 9d82bf2a69 fix: remove scrollbar on x-axis in toc (#3008)
* fix: remove overflow x in toc

* fix: use useMemo

* fix: parsing /settings/integrations/slack

* fix: no transparency in firefox

* fix: remove debounced fn
2022-01-26 19:36:11 -08:00
Tom Moor dc29fb475d snapshot 2022-01-25 23:51:15 -08:00
Tom Moor 175857753e fix: Bag 'o fixes
Remove menu hover styles on mobile
Fixed duplicate hover+active behavior on editor menus
Fixed editor menus visibly scroll to the top when reopened
Fixed some minor editor spacing issues
Renamed shred routeHelpers -> urlHelpers
2022-01-25 23:43:11 -08:00
Tom Moor 13b8ed58fd fix: Improved pasting behavior from Dropbox Paper 2022-01-25 22:01:51 -08:00
Tom Moor bc40a0074a fix: Paragraph spacing 2022-01-25 20:02:03 -08:00
Charlie Jonas 36ee42084c fix: issue-2974 reparent nested document when dropped on current collection (#2975) 2022-01-24 19:40:42 -08:00
Tom Moor c8a67c374f Merge branch 'main' of github.com:outline/outline 2022-01-23 21:02:12 -08:00
Translate-O-Tron cd3393585c New Crowdin updates (#2924) 2022-01-23 20:52:01 -08:00
Tom Moor 797e5b63e7 tsc 2022-01-23 20:50:48 -08:00
Tom Moor 39268f471e fix: Excessive spacing at top of editor 2022-01-23 20:43:37 -08:00
Eugene Sokolov b52b1b02fe Fix: consistently check allowed domains (#2985)
* fix: ensure consistency of checking allowed domain

* chore: update comment to match the logic
2022-01-23 17:40:18 -08:00
Tom Moor 390a1343b7 docs: Remove contradicting message from .env comments 2022-01-23 09:46:29 -08:00
Tom Moor 37a29934ec fix: Reduce clickable area on star in document header, make entire line clickable to focus title
closes #2966
2022-01-22 18:25:06 -08:00
Tom Moor e8c88b3c33 fix: Flash of content when selecting text on RHS of document (#2981)
fix: Double portal
2022-01-22 18:10:23 -08:00
Tom Moor 80c6e57aa3 fix: Share popover incorrectly displays draft as publicly shared when parent document is (#2982)
closes #2978
2022-01-22 18:04:05 -08:00
Tom Moor e4dbd67ae1 feat: Support SSL without reverse proxy (#2959)
* Enable (optional) reading SSL certificates on startup

* Update gitignore

* fix: Expect ssl environment variables to be Base64 encoded

* docs: Add env variables to .env.sample
2022-01-22 17:40:55 -08:00
Tom Moor 50547ae355 fix: Increase default breathing room in documents
closes #2878
2022-01-22 17:32:07 -08:00
Tom Moor 88fcf8cb44 docs: Update README to point to new docs 2022-01-22 13:18:29 -08:00
Tom Moor 0d66055441 fix: More lenient Lucidchart embed matcher
closes #2017
2022-01-22 08:41:51 -08:00
Nan Yu f4619e0e77 fix: truncate a very long team name with ellipses (#2963) 2022-01-21 18:36:13 -08:00
Tom Moor 79e2cad5b9 feat: Add reordering to starred documents (#2953)
* draft

* reordering

* JIT Index stars on first load

* test

* Remove unused code on client

* small unrefactor
2022-01-21 18:11:50 -08:00
Tom Moor 49533d7a3f Enable 'Features' settings item on cloud hosted 2022-01-20 20:21:22 -08:00
Tom Moor 8c6ab3db37 fix: Don't show drag handle on pins when there is only 1 2022-01-20 20:18:28 -08:00
Nan Yu c2c7a7190c fix: trim collection name on save rather than on change (#2962)
* fix: trim collection name on save rather than on change

* move trim to server
2022-01-20 18:53:29 -08:00
Tom Moor 703708e5d2 fix: A couple of dark mode styling issues 2022-01-20 18:50:05 -08:00
Andy Rossmeissl 090e5f2849 fix: Missing space character (#2961)
* Fix typo

* Update Templates.tsx

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-01-20 18:31:48 -08:00
Tom Moor 062016b164 chore: Move editor into codebase (#2930) 2022-01-19 18:43:15 -08:00
Nan Yu 266f8c96c4 fix: issue-2956 (#2957) 2022-01-19 18:24:25 -08:00
Nan Yu 8bced69828 fix: changing the title and body content in quick succession would trigger unsaved changes warning prompt (#2950)
changing the title and body content in quick succession would trigger unsaved changes warning prompt
2022-01-19 12:57:44 -08:00
Tom Moor d0e7f2de65 fix: Emoji in title positioning (#2927)
* wip

* fix measure on first render

* wip

* refactor

* tsc

* remove fragment

* refactor (again)

* cleanup
2022-01-16 17:02:33 -08:00
Tom Moor 5abc73fabc fix: Editor shortcut conflicts (#2943)
* fix: ctrl+n shortcut conflicts

* Update kbar with fix for ctrl-k on macOS
2022-01-15 17:47:53 -08:00
Tom Moor 49718f2894 fix: Submenus get stuck open, closes #2938 2022-01-15 16:21:39 -08:00
Tom Moor bb29dcaccc tsc 2022-01-14 21:04:51 -08:00
Tom Moor 19704e15ba fix: Pin icons different colored, closes #2939 2022-01-14 21:02:35 -08:00
Tom Moor 7fa2644caf chore: Allow immediate login for invites in development 2022-01-14 20:41:20 -08:00
Nan Yu 71820fb3ad feat: Add navigation sidebar to shared documents (#2899)
Co-authored-by: Tom Moor <tom@getoutline.com>
2022-01-14 19:02:01 -08:00
Tom Moor 2ad32e5009 fix: Remove innerHTML usage 2022-01-09 21:44:53 -08:00
Tom Moor 7c5514ae10 fix: Remove usage of direct HTML access 2022-01-09 21:19:18 -08:00
Max Mykhailenko ce27332ccb docs: Update instructions (#2895)
* Update instructions

Additional details for using redis or postgres installed outside docker

* Update README.md

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update README.md

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2022-01-09 09:56:10 -08:00
Tom Moor 86e171442d fix #2906 2022-01-08 16:19:57 -08:00
Tom Moor fc564cfc1a fix: Templates menu does not appear in collab editing (#2915)
* fix: Templates menu does not appear in collab editing

* Improved logic for display templates menu
2022-01-08 16:04:50 -08:00
Tom Moor c6cc04cad8 chore: More typescript FIXME's removed 2022-01-06 21:25:42 -08:00
Translate-O-Tron 8d05c752ea New Crowdin updates (#2897) 2022-01-06 19:24:59 -08:00
Tom Moor b20a341f0c chore: Typescript database models (#2886)
closes #2798
2022-01-06 18:24:28 -08:00
Tom Moor d3cbf250e6 0.61.0 2022-01-05 20:53:07 -08:00
Tom Moor ece879b2cc fix: Unresponsiveness of select inputs post-click 2022-01-05 20:10:51 -08:00
Tom Moor 3cee22da89 Add Vietnamese to language options
closes #2889
2022-01-05 19:09:42 -08:00
Tom Moor 917167cf1b fix: Spacing too large beneath 'Home' heading when no docs pinned 2022-01-05 18:58:34 -08:00
Tom Moor a01dded55a fix: Catch no path passed to /static/ route 2022-01-04 22:18:03 -08:00
Translate-O-Tron 09df6fa0d1 New Crowdin updates (#2890) 2022-01-04 21:42:42 -08:00
Translate-O-Tron 6cdf255074 New Crowdin updates (#2863) 2021-12-31 17:55:30 -08:00
Tom Moor eb0c324da8 feat: Pin to home (#2880) 2021-12-30 16:54:02 -08:00
Tom Moor 5be2eb75f3 fix: Incorrect text color on 'full width' menu item 2021-12-20 18:36:06 -08:00
Tom Moor ce614ca170 chore: Minor typescript improves 2021-12-19 22:08:25 -08:00
Tom Moor 448694a561 ui: Remove heavy underline on subheading text 2021-12-19 21:29:23 -08:00
Tom Moor 4998421cc0 fix: '+' button display in sidebar in Safari 2021-12-19 17:43:46 -08:00
Tom Moor 36c0372d62 fix: Loop loading GitHub Gist embeds in Safari
closes #2520
2021-12-19 17:38:03 -08:00
Tom Moor 66d5a567c2 feat: Optional full-width toggle for document display (#2869)
* Migration, model, presenter

* Working implementation

* fix: Account for table of contents

* Checkbox -> Toggle

* Checkbox -> Toggle
2021-12-19 13:58:16 -08:00
Tom Moor 73bc7d9f2a fix: Reduce loading jank on recent searches screen 2021-12-19 13:07:22 -08:00
Tom Moor 5507295a36 fix: '+' button display in sidebar in Safari 2021-12-19 12:58:08 -08:00
Tom Moor 6fc1b5cc22 feat: Show recent searches (#2868)
* stash

* root hookup

* recent searches UI

* feat: Add search query deletion

* simplify no results state

* lint
2021-12-19 11:08:28 -08:00
Tom Moor 81f3347ecf fix: Don't show create a group option to those without permission
closes #2621
2021-12-18 11:21:07 -08:00
Tom Moor 791be77867 feat: Add '+' button to create new doc in sidebar (#2864) 2021-12-18 11:14:17 -08:00
Tom Moor 80b2ba886a fix: Improved inline code display in dark mode
closes #2835
2021-12-18 11:08:17 -08:00
Tom Moor 0a89b7b5b9 closes #2747 2021-12-18 11:02:06 -08:00
Tom Moor 39018f16b5 Show collaborators on mobile, normalize margins 2021-12-17 16:50:34 -08:00
Tom Moor f8736758f1 fix: Redirect loop in shared documents
closes #2867
2021-12-17 16:42:12 -08:00
Tom Moor e7c3028ef2 fix: Views should be recorded for drafts closes #2862 2021-12-17 16:27:06 -08:00
Tom Moor 8b73f98b9a fix: Document titles in RTL script not correctly aligned 2021-12-17 11:29:40 -08:00
Translate-O-Tron 93efedb912 New Crowdin updates (#2852)
* fix: New German translations from Crowdin [ci skip]

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

* fix: New Japanese 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 Italian translations from Crowdin [ci skip]

* fix: New Korean 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 Chinese Traditional translations from Crowdin [ci skip]

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

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

* fix: New Thai 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 Chinese Simplified translations from Crowdin [ci skip]

* fix: New Japanese 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 Italian translations from Crowdin [ci skip]

* fix: New Korean 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 Chinese Traditional translations from Crowdin [ci skip]

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

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

* fix: New Thai translations from Crowdin [ci skip]
2021-12-16 22:30:34 -08:00
Tom Moor d4695f3b5b feat: Add event selection to Slack post integration (#2857) 2021-12-16 22:30:23 -08:00
Tom Moor 9a7b5ea1f4 feat: Added ability to click another user to observe them (sync scroll position) (#2858)
* feat: Added ability to click another user to observe them, mainly for fun

* language, lower debounce, prevent tooltip from hiding when toggling observation

* fix: Don't allow observing self, added banner at top of screen

* Dont edit tooltip as it's confusing between our actions and theirs

* snapshots
2021-12-16 17:36:39 -08:00
Tom Moor 4266b2eb3c feat: New heading behavior in editor 2021-12-15 23:02:34 -08:00
Tom Moor 88ce043438 fix: Revert cdnPath change 2021-12-14 18:30:57 -08:00
Tom Moor e2ee6e16d7 fix: Incorrect import syntax 🤦 2021-12-14 18:14:44 -08:00
Tom Moor 32126602fd fix: Duplicate notification for publish event, closes #2757 2021-12-14 17:21:11 -08:00
Tom Moor 0079ac90e7 chore: Remove unused screenshots from repo 2021-12-14 16:17:16 -08:00
Tom Moor 1e3f3ff047 fix: Integration icons should load from CDN if available 2021-12-14 16:14:50 -08:00
Tom Moor 632799fea6 feat: Add 'Whimsical' as embed provider 2021-12-14 16:06:31 -08:00
Tom Moor 0a7723a10f fix: Frameless embeds
fix: Vimeo embed alt url style
2021-12-14 15:54:07 -08:00
Tom Moor 6b1a1750c6 fix: Emoji text selection behavior 2021-12-14 15:32:27 -08:00
Tom Moor 2f4531ff49 fix: History sidebar behavior (more leftover bugs from TS conversion) 2021-12-13 23:42:47 -08:00
Tom Moor 74615bfe37 fix: Server error if X-Editor-Version is not valid semver string 2021-12-13 20:28:29 -08:00
Tom Moor 1a3badbb8a feat: Add collection icons: Lightning, Database, Smiley
fix: Icons Vehicle, Bicycle
2021-12-13 20:23:22 -08:00
Nan Yu 6f73cb4939 fix: various bugs on draft sidebar items (#2856)
- show children when the only child is the active draft
- disable drop onto draft items
- fix danger button hover color
2021-12-13 13:21:03 -08:00
Tom Moor e1903c4016 fix: command palette opens when editor is active 2021-12-12 21:51:42 -08:00
Tom Moor 0340149457 chore: More type improvements 2021-12-12 18:44:32 -08:00
Tom Moor 46f839431b feat: Add replace image functionality
fix: Hide image caption when not directly editing
Update iconography
2021-12-12 17:23:07 -08:00
Tom Moor 60223f4404 fix: Presenter for empty collection returns undefined for documentStructure 2021-12-11 13:53:11 -08:00
Tom Moor 19e85c63c2 lint, tsc 2021-12-11 12:48:32 -08:00
Tom Moor ca0a900c21 fix: Improved display of editing titles in sidebar 2021-12-11 12:48:32 -08:00
Translate-O-Tron 5ebfdf7b8a New Crowdin updates (#2842)
* fix: New Dutch translations from Crowdin [ci skip]

* fix: New Dutch translations from Crowdin [ci skip]
2021-12-11 09:43:00 -08:00
Zero King ff662acfe0 chore: Update Node.js version (#2849) 2021-12-11 09:34:57 -08:00
Tom Moor 7aa4709e69 feat: Show drafts in sidebar when viewing (#2820) 2021-12-11 09:34:36 -08:00
Tom Moor e5b4186faa feat: Add searching of sub actions in command menu (#2845) 2021-12-11 09:34:16 -08:00
Tom Moor 7c6ce44fe1 fix: Incorrect styling of icon color picker in dark mode 2021-12-10 23:44:03 -08:00
Zero King 6713dfcb89 fix: Bind context to util.promisify (#2844) 2021-12-10 19:40:02 -08:00
dkkb 724f641d44 fix: Document icon overflow in ReferenceListItem (#2811)
* fix: Document icon overflow in ReferenceListItem

* fix: Icon shrinking

* fix: RTL document titles

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-12-10 19:24:13 -08:00
dependabot[bot] 0a40b3a7e2 chore(deps): bump nodemailer from 6.4.16 to 6.6.1 (#2843)
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 6.4.16 to 6.6.1.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v6.4.16...v6.6.1)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-10 17:19:43 -08:00
Zero King 11e14bc4f5 feat: Support IAM role authentication for S3 (#2830)
closes #2829
2021-12-10 17:08:03 -08:00
Zero King 05b9ae3e63 chore: Remove outline service in docker-compose.yml (#2824)
Commit 18cf148bd1 made Yarn run locally outside of Docker, so there is no need for an outline container.
2021-12-10 11:03:22 -08:00
Translate-O-Tron 79d27e9684 fix: New Japanese translations from Crowdin [ci skip] (#2839) 2021-12-10 08:24:00 -08:00
Saumya Pandey cda43b5c7f fix: focus input when page refresh (#2814)
* fix: focus input when page refresh

* fix: increase to 100ms
2021-12-09 22:50:06 -08:00
Translate-O-Tron 7f8db01168 New Crowdin updates (#2825)
* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]
2021-12-09 22:49:51 -08:00
David Zhuang 29b75f84c2 fix: Optimizing Heroku deployment: more configs, add collaboration support (#2838) 2021-12-09 22:49:38 -08:00
Tom Moor 355013a160 fix: reassignment to const (from typescript conversion)
closes #2837
2021-12-09 22:48:00 -08:00
Zero King 09afe7137d feat: Support custom CDN in Dockerfile (#2833) 2021-12-08 09:13:40 -08:00
Tom Moor 8b4bd29515 fix: Typescript dependency bundled in prod causes websocket connections to fail 2021-12-06 19:48:24 -08:00
Tom Moor ac5d47e35b Update stale.yml 2021-12-06 08:00:27 -08:00
Tom Moor 6550d89d9b fix: Unable to access icon picker (from ts migration) 2021-12-05 23:20:07 -08:00
Tom Moor b16e27a790 fix: Error opening folded document breadcrumb (from ts migration) 2021-12-05 22:48:02 -08:00
Translate-O-Tron f87ac36d57 New Crowdin updates (#2816)
* fix: New Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]
2021-12-05 20:58:02 -08:00
Zero King 986ccdf355 fix: Keep tsconfig.json in Docker build (#2823)
closes #2822
2021-12-05 20:46:42 -08:00
Tom Moor 891671a45b lint 2021-12-05 19:54:21 -08:00
Tom Moor 6e371f0d03 fix: HoverPreview not showing on collaborative editing teams
types
2021-12-05 19:31:08 -08:00
Tom Moor ce2a58e83b fix: Math.random -> crypto.randomBytes
closes #2818
2021-12-05 18:42:03 -08:00
Tom Moor d9cb40ae84 fix: Error at table size in dark mode 2021-12-05 18:30:21 -08:00
Zero King 2db49820f9 fix: Catch error in promise and fix typo (#2817) 2021-12-04 10:25:05 -08:00
Tom Moor e4f0ef6ddf chore: Upgrade outline-icons (typescript) 2021-12-03 17:32:19 -06:00
Tom Moor 7c37724f88 types 2021-12-03 10:34:41 -06:00
Tom Moor 9eb72a3485 fix: Nested list items escape page boundaries 2021-12-03 10:34:41 -06:00
Tom Moor 332ab4cd40 fix: Display sidebar toggle by default on tablets 2021-12-03 10:34:41 -06:00
Tom Moor 8085c16d32 fix: Odd document header state on exact media query boundary 2021-12-03 10:34:41 -06:00
Translate-O-Tron 10da62a4e8 fix: New German translations from Crowdin [ci skip] (#2813) 2021-12-03 07:48:49 -08:00
Tom Moor 11c714e47d fix: Remove star option on publicly shared docs (#2804) 2021-12-03 06:44:21 -08:00
Tom Moor 82bc6ef45b fix: Clickable area for docs in sidebar is obstructed (#2809)
closes #2808
2021-12-03 06:44:06 -08:00
Nan Yu d8d3e2bef2 fix: adds done and publish options to document.update, this got taken out on accident during the switchover to ts (#2812) 2021-11-30 11:12:14 -08:00
ꌗᖘ꒒ꀤ꓄꒒ꀤꈤꍟ e8aed2e6c9 chore: Let dev redis, pgsql and s3 listen on localhost only. (#2776) 2021-11-30 06:36:07 -08:00
Tom Moor 77d24dd7f8 fix: Allow use of email providers with no username, closes #2767 2021-11-30 08:21:15 -06:00
Tom Moor d13254b543 fix: No reserving space in sidebar for overflow (#2807)
* fix: No reserving space in sidebar for overflow
closes #2486

Co-authored-by: Charles Harries <charles@harries.me>
2021-11-30 05:56:04 -08:00
Tom Moor e2841aebcd fix: Emoticons converted to emojis post-save, closes #2785 2021-11-30 07:26:18 -06:00
Translate-O-Tron 4545b625fe New Crowdin updates (#2691) 2021-11-29 19:53:36 -08:00
Tom Moor 98daf62a5c feat: Upgrade editor, more code block language support 2021-11-29 21:01:39 -06:00
Tom Moor 15b1069bcc chore: Move to Typescript (#2783)
This PR moves the entire project to Typescript. Due to the ~1000 ignores this will lead to a messy codebase for a while, but the churn is worth it – all of those ignore comments are places that were never type-safe previously.

closes #1282
2021-11-29 06:40:55 -08:00
Tom Moor 25ccfb5d04 lint 2021-11-26 17:16:39 -06:00
Tom Moor 5b27c0f84d fix: Background error on public shared pages 2021-11-26 17:10:45 -06:00
Tom Moor c64387668d Merge fix/path-parsing 2021-11-17 21:02:53 -08:00
Nan Yu ec5e3120d2 fix: visible groups (#2729)
* updated readme to give some light testing instructions
* updated tests to accept new behavior for group memberships
* use test factories in more places
* add debug logs for mailer events in development
2021-11-15 16:05:58 -08:00
Tom Moor 8a76dd49a0 Bump RME: Fix content in notices 2021-11-14 18:34:26 -08:00
Tom Moor 33524a1322 feat: Add 'Pitch' embed support 2021-11-14 18:33:30 -08:00
dkkb b616292fce feat: Highlight active ListItem in outline. (#2760) 2021-11-12 17:22:37 -08:00
dkkb 94a2e453eb fix: fix issue where the title can be modified in read-only mode (#2761)
The title can be changed (but not saved) when the document is in read only mode.
2021-11-12 08:21:56 -08:00
Tom Moor a674a8668b Update LICENSE 2021-11-11 07:27:39 -08:00
Tom Moor 28ab3402ac 0.60.1 2021-11-11 07:21:24 -08:00
Tom Moor 8a9c09c646 fix: Collaborative sync issue due to doc being prematurely removed in server memory 2021-11-10 17:55:20 -08:00
Tom Moor 30a80fa92d 0.60.0 2021-11-09 21:45:20 -08:00
Tom Moor e899616081 fix: Changing team settings should update in other tabs 2021-11-09 17:28:59 -08:00
dependabot[bot] 411a76f9ff chore(deps): bump y18n from 4.0.0 to 4.0.3 (#2752)
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.3.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/y18n-v4.0.3/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/compare/v4.0.0...y18n-v4.0.3)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-09 07:10:48 -08:00
Tom Moor 87125223de chore: Various dependency updates (#2751) 2021-11-09 07:03:36 -08:00
Tom Moor 6a64dfe4b2 fix: code scanning alerts (#2750) 2021-11-08 22:46:30 -08:00
Tom Moor 87e8ef8fe6 Merge branch 'main' of github.com:outline/outline 2021-11-08 20:52:39 -08:00
Tom Moor c597f2d9a2 feat: Seamless Edit (#2701)
* feat: Remove explicit edit

* Restore revision remains disabled for now

* Bump RME, better differentiation of focused state

* fix: Star not visible in edit mode

* remove stray log

* fix: Occassional user context not available in collaborative persistence
2021-11-08 20:52:17 -08:00
Tom Moor 37be7f99c4 fix: UI flash when loading history sidebar 2021-11-08 20:43:19 -08:00
Tom Moor 9865eab61c fix: Occassional user context not available in collaborative persistence 2021-11-08 18:56:36 -08:00
Tom Moor a600a897c3 fix: Clash between history and table of content shortcuts
related #2733
2021-11-08 18:03:03 -08:00
Tom Moor e170a63094 Missing association cascades 2021-11-07 21:53:40 -08:00
Tom Moor c30908e858 fix: Code highlighting with collaborative editing 2021-11-07 18:48:48 -08:00
Tom Moor 3ac7a839ad fix: Improve share popover focus behavior 2021-11-07 15:48:32 -08:00
Tom Moor 7bc7d7cd6b fix: Incorrect policy returned for parent share 2021-11-07 15:44:37 -08:00
Tom Moor dcec3dd4ec Create codeql-analysis.yml
Testing this out, may revert if it's not useful
2021-11-07 11:27:42 -08:00
Tom Moor b2a1e6b309 feat: Collaborative revision restore (#2721) 2021-11-07 08:58:44 -08:00
dependabot[bot] 5dd5df6268 chore(deps): bump url-parse from 1.4.7 to 1.5.3 (#2740)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 08:30:58 -08:00
dependabot[bot] 8cdb78c94a chore(deps): bump normalize-url from 4.5.0 to 4.5.1 (#2739)
Bumps [normalize-url](https://github.com/sindresorhus/normalize-url) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/sindresorhus/normalize-url/releases)
- [Commits](https://github.com/sindresorhus/normalize-url/commits)

---
updated-dependencies:
- dependency-name: normalize-url
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 08:30:35 -08:00
dependabot[bot] 398c7eb25c chore(deps): bump jszip from 3.5.0 to 3.7.0 (#2738)
Bumps [jszip](https://github.com/Stuk/jszip) from 3.5.0 to 3.7.0.
- [Release notes](https://github.com/Stuk/jszip/releases)
- [Changelog](https://github.com/Stuk/jszip/blob/master/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/compare/v3.5.0...v3.7.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 08:30:05 -08:00
Tom Moor ee270abbe9 fix: Ensure IntegrationAuthentication is deleted with team 2021-11-07 08:29:37 -08:00
dependabot[bot] 70ec8c551e chore(deps): bump tar from 6.0.5 to 6.1.11 (#2737)
Bumps [tar](https://github.com/npm/node-tar) from 6.0.5 to 6.1.11.
- [Release notes](https://github.com/npm/node-tar/releases)
- [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-tar/compare/v6.0.5...v6.1.11)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-05 17:03:53 -07:00
dependabot[bot] 3a29e157b2 chore(deps): bump passport-oauth2 from 1.6.0 to 1.6.1 (#2736)
Bumps [passport-oauth2](https://github.com/jaredhanson/passport-oauth2) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/jaredhanson/passport-oauth2/releases)
- [Changelog](https://github.com/jaredhanson/passport-oauth2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jaredhanson/passport-oauth2/compare/v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: passport-oauth2
  dependency-type: direct:production
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-05 17:02:46 -07:00
Tom Moor ed8334d77a fix: Plug memory leak in collaboration server 2021-11-05 16:55:20 -07:00
Tom Moor 6df8e9e13f Start collaboration service if not otherwise specified 2021-11-04 19:39:41 -07:00
Tom Moor eb9ff990ac feat: Show collab cursor names upon loading document. (#2732)
Second attempt, adds a class to the editor for a couple of seconds when the awareness is loaded to force cursors to display
2021-11-04 17:24:23 -07:00
Tom Moor 1a6921f6c7 fix: Empty doc missing placeholder 2021-11-03 22:02:10 -07:00
Tom Moor 89115a53ca fix: documents.publish event not triggered if nothing else changed in doc (#2728) 2021-11-03 18:43:01 -07:00
Tom Moor ad3bb98087 fix: Various collab cursor issues (#2727) 2021-11-03 17:51:51 -07:00
dependabot[bot] a839f2ed5b chore(deps): bump validator from 5.2.0 to 13.7.0 (#2726)
Bumps [validator](https://github.com/validatorjs/validator.js) from 5.2.0 to 13.7.0.
- [Release notes](https://github.com/validatorjs/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/validatorjs/validator.js/compare/5.2.0...13.7.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-03 11:08:01 -07:00
Nan Yu ea12ebea0e Fix: increase left gutter spacing on mobile edit mode (#2720)
* fix: adds space to the left gutter in edit mode so heading annotations have room on mobile
2021-11-02 18:30:37 -07:00
Tom Moor 57fa1305a6 chore: Remove react-keydown (#2713)
* First steps of remove react-keydown, replace with hook

* RegisterKeyDown component to aid transition away from react-keydown
2021-11-01 19:52:04 -07:00
Tom Moor 5f00e1394d fix: Move notifications to be revision driven (#2709) 2021-10-31 18:36:16 -07:00
Tom Moor b6a058147e chore: Refactor two components away from withRouter 2021-10-30 10:51:33 -07:00
Tom Moor 2c6ec11708 lint 2021-10-30 08:44:36 -07:00
Tom Moor 5900176b58 feat: Show collaborative cursors on load
closes #2704
2021-10-29 23:28:41 -07:00
Tom Moor e2c80e5a28 fix: Correctly show editing tooltip
Remove edit icon
closes #2705
2021-10-29 23:04:23 -07:00
Nan Yu 61d56922d5 fix: small improvements to local dev (#2699)
* dont commit pem files to git
* update readme ngrok instructions
* quote the OIDC scope string
2021-10-28 21:44:14 -07:00
Tom Moor 9a1c5c187e fix: Bump hocuspocus for small js fix (https://github.com/ueberdosis/hocuspocus/pull/235) 2021-10-28 21:28:33 -07:00
Tom Moor f2b007bcf5 fix: Flipped load logic 2021-10-28 20:51:40 -07:00
Tom Moor 578d4c4517 Merge branch 'main' of github.com:outline/outline 2021-10-27 21:03:48 -07:00
Tom Moor 313fd0c1b4 fix: disable multiplayer editing on shared docs when logged in 2021-10-27 20:49:52 -07:00
Tom Moor 1641423106 fix: Prevent user.info request loop, keep track of requested users in component state (#2693) 2021-10-27 20:12:22 -07:00
dkkb 67f06895e7 fix: Support uppercase letters in gist link (#2696) 2021-10-27 08:20:39 -07:00
dkkb 030419fa80 fix: Remove redundant scrollbar from iframe. (#2697) 2021-10-27 08:19:13 -07:00
Tom Moor 3987de1d7e Bump kbar, related #2688 2021-10-26 18:12:20 -07:00
Tom Moor 12b9e750e9 chore: Avoid buffer alloc 2021-10-26 18:05:50 -07:00
Tom Moor 1819920c04 fix: React warning size of memo changing between renders 2021-10-26 00:20:32 -07:00
Tom Moor a33bac66e4 fix: Remove invariant from visible calculation 2021-10-25 22:47:14 -07:00
Tom Moor 043a7b41b5 feat: Add print, duplicate, template to command bar 2021-10-25 20:41:28 -07:00
Tom Moor 4266a95569 chore: Bump BME (#2690) 2021-10-24 21:28:15 -07:00
Tom Moor 1d6bae05e6 fix: After renaming collection, url does not update 2021-10-24 17:57:17 -07:00
Tom Moor bb36425175 feat: Enable 'new document' action 2021-10-24 17:51:25 -07:00
Tom Moor adca894e83 fix: Long titles in command bar should not wrap 2021-10-24 17:32:28 -07:00
Tom Moor 2e56bdc388 fix: Command bar should bust cache when docs and collections are renamed
fix: Command bar should get larger on large screens
fix: Editable titles in sidebar should enforce max length
2021-10-24 17:32:28 -07:00
Translate-O-Tron 7f3df8158a New Crowdin updates (#2673) 2021-10-24 16:40:27 -07:00
Tom Moor 1b539dcf83 lint 2021-10-24 12:42:13 -07:00
Tom Moor 1d22b7ae0c chore: Turn on command bar in prod 2021-10-24 12:40:17 -07:00
Tom Moor b1f04145e5 flow 2021-10-24 12:31:17 -07:00
Tom Moor 2a32a4095d Merge branch 'main' of github.com:outline/outline 2021-10-24 12:30:58 -07:00
Tom Moor 33b6fbdee9 feat: Command Bar (#2669) 2021-10-24 12:30:27 -07:00
Gaston Flores dc92e1ead4 fix: ignore emoji when sorting (#2687)
* fix: ignore emoji when sorting

* fix: use correct flow types

* fix: use emoji-regex
2021-10-24 12:29:57 -07:00
Tom Moor 248c8b3c01 Improve beta note 2021-10-24 10:37:19 -07:00
Tom Moor d9f8d2e6d4 fix: Allow tests to pass when default is collab (#2685) 2021-10-23 16:02:25 -07:00
Tom Moor 99684d0900 Upgrade editor, fixes #2682 2021-10-23 10:34:38 -07:00
Tom Moor 6c2d43075c Update README.md 2021-10-23 09:53:26 -07:00
polemius b44c15c6eb fix: small typo (#2683) 2021-10-22 10:23:23 -07:00
Tom Moor f7b587b5a5 fix: Dont show back link on custom domains
closes #2671
2021-10-21 21:45:57 -07:00
Tom Moor c79a22b857 flow 2021-10-21 21:23:58 -07:00
Tom Moor 63c0daf483 fix: mailto links corrupted on save, closes #1090 2021-10-20 08:56:02 -07:00
Tom Moor 51971d2c9a fix: Various aria and React warnings 2021-10-19 22:12:20 -07:00
Tom Moor d443abfc57 chore: Allow websockets and collaboration service to run in the same process (#2674) 2021-10-19 21:18:20 -07:00
Saumya Pandey 3610a7f4a2 fix: Add default role option for new users (#2665)
* Add defaultUserRole on server

* Handle defaultUserRole on frontend

* Handle tests

* Handle user role in userCreator

* Minor improvments

* Fix prettier issue

* Undefined when isNewTeam is false

* Update app/scenes/Settings/Security.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/Settings/Security.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/Settings/Security.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Remove duplicate validation

* Update Team.js

* fix: Move note out of restricted width wrapper

* Move language setting to use 'note' prop

* Remove admin option

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-10-20 09:26:11 +05:30
Translate-O-Tron 90fdf5106a New Crowdin updates (#2639) 2021-10-18 20:13:31 -07:00
Tom Moor 77fb76ff0c lint 2021-10-15 21:09:55 -07:00
Tom Moor 583353e904 fix: Disable guest signin option with not SMTP setup
closes #2250
2021-10-14 21:59:35 -07:00
Tom Moor 26e2ae4bf1 fix: Hide notification settings when SMTP_ configuration is unset 2021-10-14 21:55:48 -07:00
Tom Moor 4f34b69cfa Display notice instead of hide when Slack integration unavailable 2021-10-14 21:49:35 -07:00
Tom Moor 8c1979465f fix: Slack integration should not display if not configured in self hosted
fix: Alignment of Slack channels in settings
closes #2553
2021-10-14 21:37:04 -07:00
Tom Moor cc7a50fbb1 memoization 2021-10-14 21:23:28 -07:00
Tom Moor 5299ada3c9 feat: Support icon prop in InputSelect 2021-10-14 19:00:30 -07:00
Tom Moor 96fc95a9f3 fix: Increase TOC gutter to allow for offset emoji
closes #2661
2021-10-14 17:04:25 -07:00
Tom Moor 2219cfd83e fix: Increase entropy of state string for OAuth process
closes #2663
2021-10-14 16:52:19 -07:00
Tom Moor 6a1566c275 fix: Regression in image upload, closes #2662 2021-10-14 16:47:16 -07:00
Tom Moor b9346fe6ea fix: Minor collab adjusts 2021-10-13 22:01:30 -07:00
Tom Moor 18572cf9de fix: Facepile appears inactive after idle disconnect 2021-10-13 20:30:16 -07:00
Tom Moor 59f4b3bd97 fix: Server markdown parser failing tests 2021-10-13 19:37:04 -07:00
Tom Moor bb9d7d310b fix: Clicking outside editor should close selection toolbar 2021-10-13 19:15:44 -07:00
Tom Moor 3a19c02e34 fix: In page anchor links not working on shared docs
closes #2652
2021-10-12 23:12:47 -07:00
Tom Moor a6b3dbc894 fix: Reduce sensitivity of dark icon switching
fix: Layout issue in icon picker in dark mode
closes #2658
2021-10-12 23:02:14 -07:00
Tom Moor e0405cca0e fix: Bump hocuspocus (memory leak fix) 2021-10-11 10:53:50 -07:00
Alexander Krantz 09a409b494 feat: add changing appearance for guests (#2632)
* Allow changing appearance when guest

* Apply suggestions from code review

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-10-07 18:43:41 -07:00
Tom Moor ccd947c6e8 fix: Positioning of input select items when seleted item does not fit in available area
fix: Scroll selected item in input select
2021-10-06 23:31:35 -07:00
Tom Moor 4e05728218 fix: InputSelect disabled state 2021-10-06 22:36:45 -07:00
Saumya Pandey 40e09dd829 fix: Implement custom Select Input (#2571) 2021-10-06 21:48:43 -07:00
Tom Moor 99381d10ff translations 2021-10-06 21:17:17 -07:00
Translate-O-Tron 36c73051b4 New Crowdin updates (#2596) 2021-10-06 21:09:29 -07:00
Saumya Pandey 81718c8ee1 fix: Delete collection exports (#2595) 2021-10-06 21:08:45 -07:00
Tom Moor be905a6993 feat: Add idle detection and disconnect collaboration socket (#2629) 2021-10-06 17:37:21 -07:00
Tom Moor b39d4aade7 Bump editor, minor emoji trigger fixes and adds Perl language support 2021-10-06 08:38:43 -07:00
Tom Moor c5fb5f875f flow 2021-10-04 22:08:16 -07:00
Tom Moor 552755dace feat: Add admin UI for enabling collab editing 2021-10-04 22:00:47 -07:00
Tom Moor e61c71766f Add guard against overwriting text when collaborative editing enabled 2021-10-04 19:20:48 -07:00
Tom Moor df5dc2f691 fix: Improve graceful shutdown 2021-10-04 18:20:42 -07:00
Tom Moor 28097835d0 chore: Remove debounced search (#2625)
* Remove debounced search

* fix hover color on filter options
2021-10-04 08:04:56 -07:00
Tom Moor 3de51c1a67 Bump editor, closes #2620, #2619 2021-10-02 22:21:26 -07:00
Tom Moor 223a47af95 fix: Improve error when email field not returned from OIDC 2021-10-02 22:42:41 -04:00
Tom Moor 7c8675ce17 fix: Creating API token reloads app
fix: API keys unselectable in list
closes #2604
2021-10-02 22:39:37 -04:00
Tom Moor 157c3ce80f fix: Missing cascade on integration -> authentication relationship 2021-10-02 22:22:08 -04:00
Saumya Pandey 0ed7286fc6 fix: Move request helper function (#2594)
* Move request method to passport utils

* Use request method in OIDC provider
2021-09-29 07:20:05 -07:00
Tom Moor 78464f315c fix: Awareness loop in collaborative editing 2021-09-27 18:44:28 -04:00
Tom Moor 79790de9b0 fix: Editor toolbar below fixed header 2021-09-27 10:40:44 -07:00
Tom Moor 252459f1cf fix: Loading flicker in collab editor when no local cache 2021-09-27 10:27:02 -07:00
Tom Moor 20a72481dc Disable embed toggling + collaborative editing 2021-09-26 21:05:32 -07:00
Tom Moor 765c7cdc27 fix: Max menu height should not affect mobile context menus 2021-09-26 17:19:00 -07:00
Tom Moor 6f136e342f fix: Context menus can extend outside of window bounds
closes #2492
2021-09-26 17:07:44 -07:00
Tom Moor 9545113d9e feat: Emoji picker in editor (#2611) 2021-09-26 15:26:32 -07:00
Tom Moor c00001086a fix: IconPicker unclosable on mobile 2021-09-26 15:26:10 -07:00
Tom Moor 95dbc8168c feat: Add 2 collection icons 2021-09-25 14:54:19 -07:00
Tom Moor 0021553518 Typescript, we need you 2021-09-25 08:55:52 -07:00
Tom Moor bcca4b91ee feat: Add 5 new collection icons 2021-09-24 19:39:31 -07:00
Tom Moor c1bd30aac8 Add user to collaboration logs 2021-09-24 19:14:00 -07:00
Tom Moor fd7dd83a4b fix: Updated database references 2021-09-23 20:09:40 -07:00
Tom Moor 26f02cdd05 fix: Table toolbars missing when cells empty 2021-09-23 19:58:16 -07:00
Tom Moor fec2baf361 fix: Memory leak in collaborative editing service 2021-09-23 17:09:15 -07:00
Tom Moor e1601fbe72 chore: Permanent team deletion (#2493) 2021-09-20 20:58:39 -07:00
dependabot[bot] a88b54d26d chore(deps): bump tmpl from 1.0.4 to 1.0.5 (#2601)
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-20 18:43:11 -07:00
Translate-O-Tron 88cc964d69 New Crowdin updates (#2590)
* fix: New Polish translations from Crowdin [ci skip]

* fix: New Polish translations from Crowdin [ci skip]
2021-09-19 19:02:01 -07:00
Saumya Pandey b8efe772fe fix: Warning when dragging document between collections with different user permissions (#2516) 2021-09-19 19:00:54 -07:00
Tom Moor b2f00d71d3 fix: Image zoom doesn't work in read-only 2021-09-19 15:26:52 -07:00
Tom Moor c2edfca6e5 fix: 'undefined' logged 2021-09-19 15:15:13 -07:00
Saumya Pandey 9c3c0fe418 feat: Add Polish to languageOptions (#2593) 2021-09-19 09:45:26 -07:00
Tom Moor 313067ff7b Add additional logging for persistence failure 2021-09-18 20:09:08 -07:00
Tom Moor be64c2b206 fix: Restore load cache, fixes TOC not visible on load 2021-09-18 17:49:00 -07:00
Tom Moor d576ce1734 fix: Remote awareness not available on doc load (collab) 2021-09-17 17:36:48 -07:00
Tom Moor 0f624958bc Use new hocuspocus hooks for collaboration metrics 2021-09-17 17:35:20 -07:00
Tom Moor 162da9a3ad fix: Can't edit title in collaborative mode 2021-09-16 22:47:58 -07:00
Tom Moor d7e9ad4f13 Remove usage of internal api 2021-09-16 21:27:37 -07:00
Tom Moor bcf773a1d6 Billibilli default hidden 2021-09-16 18:49:05 -07:00
Tom Moor 97082e8cba Merge branch 'main' of github.com:outline/outline 2021-09-16 18:48:25 -07:00
Su Yang bc3f2e4876 Add bilibili Embed Service (#2550)
* feat: Add bilibili Embed Service

* chore: code format

* chore: update bilibili icon
2021-09-16 18:48:13 -07:00
Translate-O-Tron 49a9b91708 New Crowdin updates (#2566) 2021-09-16 18:45:55 -07:00
Greg Linklater 01cea549a5 feat: map preferred_username claim to user record (#2569) 2021-09-16 18:45:37 -07:00
Tom Moor a9df3f64cf fix: Headings and code should be toggleable 2021-09-16 18:42:42 -07:00
Tom Moor e6cc8f5550 fix: Include log level in development 2021-09-16 17:22:23 -07:00
Tom Moor f6c2a95a55 Bump i18next-parser for true --silent fix 2021-09-16 16:26:57 -07:00
Tom Moor 27736f66ef fix: Various fixes for collaborative editing beta (#2586) 2021-09-15 23:27:22 -07:00
Tom Moor cde2909296 fix: Missing translation tag 2021-09-14 20:15:37 -07:00
Tom Moor 1f6e1a71f9 fix: List reverting to '0' indexing 2021-09-14 18:34:34 -07:00
Tom Moor 15ef8f7dff chore: Upgrade i18next related deps 2021-09-14 18:15:16 -07:00
Tom Moor 83a61b87ed feat: Normalized server logging (#2567)
* feat: Normalize logging

* Remove scattered console.error + Sentry.captureException

* Remove mention of debug

* cleanup dev output

* Edge cases, docs

* Refactor: Move logger, metrics, sentry under 'logging' folder.
Trying to reduce the amount of things under generic 'utils'

* cleanup, last few console calls
2021-09-14 18:04:35 -07:00
Tom Moor 6c605cf720 fix: Forward to incorrect collection url on first signin (#2565)
closes #2560
2021-09-13 21:35:52 -07:00
Tom Moor fb335887cb preventBodyScrollhideOnEsc 2021-09-13 21:00:28 -07:00
Translate-O-Tron 88e7d4c539 New Crowdin updates (#2449) 2021-09-13 20:09:52 -07:00
Tom Moor 400e32da70 fix: Various fixes for collaborative editing beta (#2561)
* fix: Remove Saving… message when collab enabled

* chore: Add tracing extension to collaboration server

* fix: Incorrect debounce behavior due to missing timestamps on events, fixes abundence of notifications when editing in realtime collab mode

* fix: Reload document prompt when collab editing
2021-09-13 17:36:26 -07:00
Tom Moor a699dea286 fix: Cleanup forking model (#2559)
* fix: Cleanup forking model
2021-09-12 21:45:52 -07:00
Tom Moor 2aca760ee0 fix: Double document highlight in sidebar (#2551)
* fix: Single highlighted doc when starred
closes #2544

* fix: Collection expand/collapse as navigating starred docs
2021-09-11 15:54:05 -07:00
Tom Moor f1c9c6fdf9 Update LICENSE 2021-09-11 09:48:19 -07:00
Tom Moor 801f6681ba Collaborative editing (#1660) 2021-09-10 22:46:57 -07:00
Tom Moor 0a998789a3 chore: Support Redis v6 on Heroku 2021-09-10 21:05:06 -07:00
Tom Moor 92016bbd06 fix: List behavior when ordered list starts at number other than 1
fix: Image improvements
fix: Image upload race condition
2021-09-10 19:06:54 -07:00
Tom Moor 231ab2da03 fix: Add recording of job errors, remove from queues on failure, centralize options 2021-09-09 22:38:34 -07:00
Tom Moor bd880ee984 chore: Add basic logging of metrics to event queue (#2545)
* chore: Add basic logging of metrics to event queue
closes #2524

* Better naming for multiple queue types

* Add stalled event
2021-09-09 21:55:45 -07:00
Tom Moor 995c6f90b7 fix: Mount _health route before catch-alls
closes #2536
2021-09-09 21:08:34 -07:00
Tom Moor 8ac853bb8b fix: Printing from doc menu is blank in Firefox
closes #2543
2021-09-09 20:41:56 -07:00
Tom Moor 2f5cf90cb7 0.59.0 2021-09-07 22:10:29 -07:00
Tom Moor c709e54738 fix: Init dd trace sooner, closes #2528 2021-09-02 23:22:31 -07:00
Tom Moor 47953b3354 Yarn.lock 2021-09-02 23:17:41 -07:00
Tom Moor d96099b5b8 Move OIDC provider to routes directory 2021-09-02 19:55:06 -07:00
Greg Linklater 4b2bf28531 feat: Generic OAuth2 Authentication (#2388)
* chore: additional dependency

* feat: OAuth2 authentication provider

* docs: add env vars

* chore: lock file

* feat: add malformed user info error and notice

* feat: configurable scopes

* fix: explicitly enable state and disable pkce

* chore: remove externally supplied username from account provisioner use

* chore: remove upstream error

* chore: add explicit import for fetch

* chore: remove unused env var from sample

* docs: openid connect claims

* fix: forward fetch errors

* feat: configurable team claim name

* docs: move OIDC env vars together

* refactor: change provider name

* refactor: rename error to match provider

* fix: resolve claim using lodash.get

* refactor: remove OIDC_TEAM_CLAIM and hard code team name
2021-09-02 19:50:17 -07:00
Tom Moor a3df9e868f fix: Server error when loading documents.info with shareId and user token and child documents shared
closes #2527
2021-09-01 23:38:43 -07:00
Tom Moor 476b5e03f9 perf: Move exports to worker service (#2514)
* first pass

* fixes

* fix: Move export related emails to queue

* i18n
2021-08-31 17:41:57 -07:00
Tom Moor 23a6459ae8 fix: Make GoogleDrive embed links more lenient
closes #2405
2021-08-30 22:43:13 -07:00
Saumya Pandey 4929fbaccb fix: Move "public document sharing" to "Permissions" (#2496)
* Convert to functional component

* Move public sharing to permissions

* Add collections.permission_changed event

* Account for null

* Update server/events.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Add collections.permission_changed event

* Remove name

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-30 11:43:42 +05:30
Tom Moor 08a8fea69a chore: Add /_health endpoint to all services
closes #2506
2021-08-29 19:44:06 -07:00
Tom Moor 2024c6e64f chore: Graceful server shutdown, closes #2507 2021-08-29 14:48:12 -07:00
Tom Moor 3dfd336f59 chore: Move all routes under routes directory (#2513)
closes #2504
2021-08-29 13:25:06 -07:00
Tom Moor 9a875920ac chore: Remove 'attachments' option from mailer 2021-08-29 12:35:55 -07:00
Saumya Pandey f389ac6414 fix: Improvements in share feat (#2502)
* Make request only when popover is visible

* Update policies required for shares.create shares.update

* Create withCollection scope

* Remove team share check from shares.create

* Update tests
2021-08-29 10:44:09 +05:30
Saumya Pandey e4b7aa6761 fix: Add ability to choose user permission level when inviting (#2473)
* Select user role while sending invite

* Add tests to check for role

* Update app/scenes/Invite.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Use select

* Use inviteUser policy

* Remove unnecessary code

* Normalize rank/role
Fix text sizing of select input, fix alignment on users invite form

* Move component to root

* cleanup

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-29 03:05:37 +05:30
Saumya Pandey 00ba65f3ef fix: Refactor collection exports to not send email attachment (#2460)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-29 02:57:07 +05:30
Tom Moor 28aef82af9 chore: Refactoring event processors and service architecture (#2495) 2021-08-27 21:42:13 -07:00
Saumya Pandey 86f008293a fix: Return memberships of collections (#2501) 2021-08-27 20:03:57 -07:00
Tom Moor 835fd26a95 Squashed commit of the following:
commit ebe2fe07d1a9110a99a21772b79f189dd13b4ca8
Author: Tom Moor <tom.moor@gmail.com>
Date:   Thu Aug 26 20:18:52 2021 -0700

    fix: regex, formatting

commit 1fd17b6f8a
Author: Matheus Breguêz <matbrgz@gmail.com>
Date:   Thu Aug 26 09:37:12 2021 -0300

    fix: change image size

commit 30e9bad0f5
Merge: ef99201c cc9468e2
Author: Matheus Breguêz <matbrgz@mail.com>
Date:   Thu Aug 26 09:28:34 2021 -0300

    Merge branch 'main' into feat/google-calendar-embed

commit ef99201c9d
Author: Matheus Breguêz <matbrgz@mail.com>
Date:   Fri Jul 9 11:53:56 2021 -0300

    Update GoogleCalendar.js

commit 0e91084756
Merge: e98f94c0 ec5c47e0
Author: Matheus Breguêz <matbrgz@gmail.com>
Date:   Wed Jul 7 14:49:06 2021 -0300

    Merge remote-tracking branch 'origin/feat/google-calendar-embed' into feat/google-calendar-embed

commit e98f94c02d
Author: Matheus Breguêz <matbrgz@gmail.com>
Date:   Wed Jul 7 14:29:49 2021 -0300

    feat: Add Google Calendar Embed

commit ec5c47e0c8
Author: Matheus Breguêz <matbrgz@gmail.com>
Date:   Wed Jul 7 14:29:49 2021 -0300

    feat: Add Google Calendar Embed
2021-08-26 20:20:15 -07:00
Tom Moor cc9468e2c5 Add 4 additional collection icons, closes #2482 2021-08-25 21:44:30 -07:00
Saumya Pandey 22ba4d0f48 fix: prevent access to docs in trash from deleted private collections (#2431)
* Check for collection in deleted document

* Add tests

* Use update policy

* Set paranoid to false when fetching deleted doc

* Update policy
2021-08-26 09:35:59 +05:30
Tom Moor d335670b91 fix: Starred untitled draft has no title in sidebar
fix: Double click to edit starred document titles
2021-08-24 23:30:55 -07:00
Tom Moor cabaee2d0a Bump editor
closes #2441
closes #2459
2021-08-24 23:23:38 -07:00
Saumya Pandey f6d889f759 fix: Show starred docs in sidebar (#2317)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-23 13:07:28 +05:30
Wesley a50471959b feat: Always show share button (#2469)
This is to enable the share page also for internal team members.

closes #2444
2021-08-22 23:20:29 -07:00
Tom Moor d8ad2fc1a2 fix: Theme in account menu does not update 2021-08-22 22:19:20 -07:00
Wesley 0c48227b57 Feat: add diagrams.net/draw.io embed (#2464)
* feat: Add diagrams.net/draw.io embed

* Rename Diagrams integration to include .net

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-21 11:11:47 -07:00
Tom Moor 72da0653cc Revert "feat: Add hosted domain hint when signing in through Google SSO from subdomain (#2458)" (#2467)
This reverts commit e613ec732b.
2021-08-21 11:11:01 -07:00
Tom Moor e613ec732b feat: Add hosted domain hint when signing in through Google SSO from subdomain (#2458)
* feat: Add hosted domain hint when signing in through Google SSO from subdomain

closes #2454
2021-08-20 14:03:52 -07:00
Tom Moor 0be40609ed feat: Add UI to switch teams where signed in to multiple (#2457)
* feat: Add UI to switch teams where signed in to multiple

* fix: Do not display current team in switch menu

* Refactor to hook
2021-08-18 18:37:50 -07:00
Saumya Pandey ec8fde0a5f fix: Improvements in table component (#2450) 2021-08-18 03:27:23 +05:30
Saumya Pandey 2c52a8cb8b fix: Add icons to menu items (#2373)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-13 14:21:25 -07:00
Tom Moor 1db31eed41 fix: Incorrect empty state text for /created Home tab 2021-08-13 09:57:20 -07:00
Tom Moor 8ba8013c6a fix: Suppressed notification causes missing notifications for other users on the same team 2021-08-13 09:40:43 -07:00
David Herman 1521d4dbac fix: Suppress notifications for suspended users (#2448)
* fix: Supress notifications for suspended users

* spelling

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-08-13 09:32:19 -07:00
Saumya Pandey a1a4fd1baf fix: Redirect to collection on self-hosted (#2438) 2021-08-13 12:32:18 +05:30
Tom Moor 31f4424018 fix: Time/LocaleTime should default to relative humanized timestamps (regression) 2021-08-12 22:47:14 -07:00
Translate-O-Tron 1f5b83aaeb New Crowdin updates (#2413) 2021-08-12 15:24:40 -07:00
Tom Moor 77db0c2e95 fix: Document history event headings (#2433)
* fix: Document history events from last year but within 12 months shown as 'this year'
fix: Events older than a year have repeated headings

* lint
2021-08-12 15:24:13 -07:00
dependabot[bot] 4cbae1cf7d chore(deps): bump path-parse from 1.0.6 to 1.0.7 (#2439)
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-08-12 15:23:43 -07:00
Tom Moor e985078b80 fix: JS error scrolling overflowed templates page
closes #2445
2021-08-12 11:26:28 -07:00
Saumya Pandey 09b73401de fix: Sidebar links highlighting issue when a template is deleted or archived. (#2420) 2021-08-06 23:01:25 +05:30
Saumya Pandey 42b384688d fix: Options to create a document is available when the policies of collection in the context doesn't permits the user (#2424) 2021-08-06 22:58:26 +05:30
Tom Moor 5bdee1204e fix: Copying header results in '#' copied
fix: urls in text become linked when reloading doc
fix: Allow creation of links to anchors from link toolbar
2021-08-06 09:39:03 -07:00
Tom Moor 9db72217af feat: Include more events in document history sidebar (#2334)
closes #2230
2021-08-05 15:03:55 -07:00
Tom Moor 57a2524fbd fix: /public directory missing in new docker releases (#2417)
closes #2416
2021-08-04 09:21:25 -07:00
Tom Moor bd148f4790 fix: Paste handler should default to HTML when paste source is Outline editor
related #2416
2021-08-04 09:20:51 -07:00
Tom Moor 28d32af613 perf: Remove unused database indexes according to a month of data in production (#2395) 2021-08-03 20:51:12 -07:00
Tom Moor f2f550e1d2 fix: Policies missing on documents.viewed endpoint 2021-08-03 20:02:11 -07:00
Translate-O-Tron dad21b2186 New Crowdin updates (#2400) 2021-08-03 19:32:51 -07:00
Tom Moor 5fb5f1e8b5 perf: Remove backup column migration (#2397)
* perf: Remove no-longer-used 'backup' columns

These were added as part of the move to the v2 editor over a year ago incase any text was not correctly converted. After a year of use no cases of failed conversion have occurred that required the use of this column

* Remove migration, will do in 2-step release

* perf: Remove no-longer-used 'backup' columns

These were added as part of the move to the v2 editor over a year ago incase any text was not correctly converted. After a year of use no cases of failed conversion have occurred that required the use of this column
2021-08-03 18:55:52 -07:00
Tom Moor 2d0690697c 0.58.0 2021-08-03 15:17:06 -07:00
Tom Moor 6b551749d4 chore: Remove version- prefix from docker tags 2021-08-03 14:23:14 -07:00
Jack Baron 52fc861bcf feat: Optimize Dockerfile (#2337)
* feat: optimize dockerfile
use new dockerfile syntaxes
leverage multi-stage builds
strip yarn cache from image
use stricter yarn install command
run as a non-root user

* fix: mark yarn-deduplicate as a required dep
`yarn --production` will fail on a clean install otherwise

* fix: add sequelize required files for migrations

* fix: use correct ARG syntax for multistage builds

* revert: mark yarn-deduplicate as a required dep
no longer required as of 0b3adad751
2021-08-03 13:22:41 -07:00
Tom Moor c81c9a9d2d chore: CI Automated Builds (#2409)
closes #2408
2021-08-02 23:35:13 -07:00
Tom Moor 29c742a673 fix: Settings on 'Security' tab not persisting correctly after refactor (#2407)
* fix: Settings on 'Security' tab not persisting correctly after refactor
closes #2406
2021-08-02 13:37:53 -07:00
Tom Moor dd249021e7 fix: GoogleDrive embeds stopped working with new share urls
closes #2405
2021-08-02 11:09:16 -07:00
Tom Moor 21d3b9c7e0 fix: Formatting of welcome docs :rolleyes: 2021-08-01 13:03:21 -07:00
Tom Moor 6665dfff28 Merge branch 'main' of github.com:outline/outline 2021-08-01 12:55:03 -07:00
Tom Moor cdfe3a7fc3 chore: Add new 'getting started' onboarding document (#2391)
Remove support document
Remove confusing images
Added onboarding checklist
2021-08-01 12:54:41 -07:00
Tom Moor 401c91f90b perf: Correctly parallelize count query in users.list 2021-07-30 12:20:19 -04:00
Tom Moor ed5320507d perf: Separate slow joins (#2394) 2021-07-30 08:50:02 -07:00
Translate-O-Tron e34581d25f New Crowdin updates (#2372) 2021-07-30 07:45:58 -07:00
Tom Moor 65a1e2630c perf: Remove no-longer-used 'backup' columns (#2396)
* perf: Remove no-longer-used 'backup' columns

These were added as part of the move to the v2 editor over a year ago incase any text was not correctly converted. After a year of use no cases of failed conversion have occurred that required the use of this column

* Remove migration, will do in 2-step release
2021-07-30 07:22:17 -07:00
Tom Moor 59de4a7db0 feat: Default to "recently viewed" (#2390)
* feat: Default user to first collection on first app open

* Default home tab to 'recently viewed'

* fix: Styling of inactive tab
2021-07-30 07:16:03 -07:00
Tom Moor 63eb8aadaf fix: Flow, remove misused withTranslation on functional component 2021-07-30 00:52:42 -04:00
Saumya Pandey 37fd7ec97a fix: Enable offline access to google accounts (#2392)
* Enable google offline access

* Prevent overriding prompt parameter
2021-07-29 20:04:57 -07:00
Tom Moor 928106067f chore: Tone down notices (#2393) 2021-07-29 20:04:45 -07:00
Tom Moor cb7c27690f fix: Slow tooltips on timestamps 2021-07-28 20:26:04 -04:00
Tom Moor 26da8c4165 feat: Add 'done' icon when all tasks are complete 2021-07-28 19:55:46 -04:00
Tom Moor 36b8ae859e fix: Bump Editor
fix: Sticky formatting toolbar behavior on iOS
fix: Image caption localized
2021-07-28 18:01:01 -04:00
Tom Moor ad1eaa5210 fix: Jank at beginning of loading indicator bar 2021-07-28 17:56:44 -04:00
Saumya Pandey 98024f6be1 fix: "1 tasks done" incorrectly pluralized (#2382) 2021-07-29 01:39:55 +05:30
falleng0d 37c02a572b feat: Auto detect language on login page access (#2338)
* feat: Auto detect language on login page access

* fix: Apply tommoor suggested changes

* fix: QOL improvements for translators

* fix: consistency fix provider -> authProviderName

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-28 12:00:02 -07:00
Tom Moor e53bb8bfbc fix: Error uploading fallback avatar when name contains characters that need to be escaped (#2387)
* Todo -> Task to match new langauge elsewhere

* fix: Correctly escape characters in Tiley url

* Move encoding to avatars logic, add test
2021-07-28 11:45:47 -07:00
Tom Moor 2a473bf7b4 Todo -> Task to match new langauge elsewhere 2021-07-28 13:15:30 -04:00
Tom Moor f3b09ab56a test 2021-07-27 21:30:00 -04:00
Tom Moor 6eb51a9cb9 chore: Allow passing of page to revisions backfill script 2021-07-27 18:53:39 -04:00
Tom Moor d01c40badb fix: Minor positioning fix of Account menu 2021-07-27 18:16:23 -04:00
Tom Moor fc551c91bd Bump editor
- Fixes enter with horizontal gap cursor
- Improves pasting behavior
- Fixes heading uncollapse when value changes
- Fixes notice blocks not hidden with other collapsed content
closes #2371
2021-07-27 17:50:16 -04:00
Tom Moor fdc1955b91 fix: Mixture of middots with different weights in document meta 2021-07-27 10:33:26 -04:00
Tom Moor b6703671e2 fix: Task progress svg shrinks width in some circumstances 2021-07-27 10:33:11 -04:00
Tom Moor 84f647674a Merge branch 'main' of github.com:outline/outline 2021-07-27 10:24:36 -04:00
Saumya Pandey a81fbd8608 fix: Show tasks completion on document list items (#2342)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-27 11:31:27 +05:30
Tom Moor 8ee018a759 feat: Web concurrency (#2347)
* feat: Fork multiple processes

* Remove boxen

* comment

* chore: Add support for Heroku DATABASE_CONNECTION_POOL_URL
closes #2306
2021-07-26 15:51:50 -07:00
Tom Moor 6815c940b2 fix: Failure case during account provision that can result in no welcome collection 2021-07-26 13:46:55 -04:00
Saumya Pandey c9bd3bbf45 fix: Editing title in sidebar allows removal of title (#2364) 2021-07-26 00:17:39 +05:30
Translate-O-Tron f61f9703f3 New Crowdin updates (#2368) 2021-07-25 08:23:53 -07:00
Tom Moor 48d538b424 fix: Server error when rendering share for deleted document
closes #2352
2021-07-23 11:25:11 -04:00
Tom Moor 84ad7c482c fix: Various editor header and metadata fixes (#2361)
* fix: Publish button disabled on drafts in read-only mode
fix: Template selector appears on edited documents

* fix: Save button does not immediately come available when selecting a template

* fix: Template menu item alignment
closes #2204

* fixes: Use policy for display of star in document title
closes #2354

* fix: Modified time is sometimes bold when last edited user is current user
closes #2355

* fix: Allow starring of drafts
2021-07-22 15:17:18 -07:00
Tom Moor d35b5d2613 tidy for blog post ;) 2021-07-22 13:43:29 -04:00
Tom Moor 3090c2cfa3 chore: Improve perf of new tab loading by caching team policy in localStorage (#2351) 2021-07-21 15:53:57 -07:00
Translate-O-Tron 140b04c126 New Crowdin updates (#2340) 2021-07-21 15:24:45 -07:00
Tom Moor 2aedf4440b feat: Enable Persian language translations (#2341) 2021-07-21 10:41:45 -07:00
Tom Moor 6e07ee3f3e chore: Move animations and globals from shared directory (#2344) 2021-07-21 10:34:55 -07:00
Saumya Pandey bba8cd183b fix: Archive and trash a document by dropping in the sidebar (#2318) 2021-07-21 00:49:41 +05:30
Saumya Pandey 0bc609634c fix: Allow searching of previous document titles (#2326)
* Add migrations

* Handle previousTitles when titles is updated

* Add necessary test cases

* Use previous title while searching

* Rewrite logic to update previousTitles in beforeSave hook

* Update weights

* Update test to match new rank order

* Add tooltip to inform user on document

* Add code comment

* Remove previous title tooltip

* fix: Remove unused string, add model tests

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-20 10:35:29 -07:00
Tom Moor b3b8cb3d9c missing translation string 2021-07-20 12:02:46 -04:00
Saumya Pandey fdb85ec195 fix: Separate toasts storage to own MobX store (#2339)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-20 14:36:10 +05:30
Tom Moor f64ab37d3c fix: Interpolation on archive/delete translationsg 2021-07-19 17:26:48 -04:00
Tom Moor 0b3adad751 chore: Move yarn-deduplicate postinstall -> prepare
should not run in production
2021-07-19 17:12:24 -04:00
Tom Moor 83477de300 fix: Account for revisions.create event being debounced 2021-07-19 17:02:33 -04:00
Tom Moor 1726006858 chore: Pass problematic url to error tracking
towards #2319
2021-07-19 16:57:06 -04:00
Tom Moor 3d9eaeeeeb chore: Add revisions.create backfill script (#2330)
* chore: Add revisions.create backfill script

* fix: Correct timestamp on revisions.create events
2021-07-19 13:32:03 -07:00
falleng0d 2e955353ae feat: translations (#2275)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-19 11:12:53 -07:00
Tom Moor 05aba68457 feat: Add support for collapsible headings (#2327) 2021-07-19 09:19:36 -07:00
Tom Moor 8f6e956bc5 chore: Add documentId index to events table (#2331) 2021-07-19 09:19:26 -07:00
Tom Moor 0cad99c343 chore: Move 'templates' to bottom of sidebar (#2328)
chore: Hide trash and archive for read-only users
2021-07-19 09:18:33 -07:00
Translate-O-Tron 04746f6a2c New Crowdin updates (#2304) 2021-07-16 06:46:32 -07:00
Tom Moor 25907f5c72 chore: Reduce idle CPU usage in development 2021-07-16 09:30:43 -04:00
Jack Baron d7a21db72f fix: Remove duplicate translation key (#2325) 2021-07-16 14:36:34 +05:30
Saumya Pandey 9596979993 fix: Add translation hooks on document and collection pages (#2307) 2021-07-16 01:49:09 +05:30
Tom Moor 31714efb0b feat: useBoolean hook (#2314)
* feat: Add useBoolean hook and example usage

* More example usage

* chore: More useBoolean conversion
2021-07-15 12:27:03 -07:00
Tom Moor 8884da8a4b feat: Add revisionCreator command (#2321)
add revisions.create event
2021-07-15 12:26:43 -07:00
Tom Moor 30cf244610 chore: Loading placeholders (#2322)
* Improve visual of loading mask

* Normalize placeholder naming

* Remove unused file
2021-07-15 12:26:34 -07:00
Saumya Pandey 3f030540b3 fix: Add translation hooks on settings screen (#2298)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-15 14:50:36 +05:30
Saumya Pandey 7ae3addea0 fix: Add space to the valid index characters list (#2316) 2021-07-15 00:35:47 +05:30
Saumya Pandey a9d758bb0c fix: Add translation hooks on remaining files (#2311) 2021-07-15 00:30:08 +05:30
Matheus Breguêz 06e16eef12 feat: Add Google DataStudio embed (#2293)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-14 11:57:12 -07:00
Tom Moor 8e5a2b85c2 feat: Improved UI motion design (#2310)
* feat: Improved UI motion design

* fix: Animation direction when screen placement causes context menu to be flipped
2021-07-12 11:57:17 -07:00
Saumya Pandey 5689d96cc4 fix: Add translation hooks on groups screen (#2303)
* Refactor groups page to functional component and translate strings

* Update app/scenes/GroupNew.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/GroupEdit.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/GroupDelete.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/GroupMembers/GroupMembers.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Format GroupMember.js

* Change Trans usage

* Format GroupDelete

* Revert "Format GroupDelete"

This reverts commit 880128f94d.

* Update app/scenes/GroupNew.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/GroupNew.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update GroupNew

* Remove newlines

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-12 11:54:55 -07:00
Tom Moor 5cd4dbd9d7 fix: Mispositioned TOC control on mobile due to merge conflict
fix: Show message in mobile TOC when no headings in document
fix: MenuItem with level should still have background edge-to-edge
fix: Show developer warning when creating incorrect menu item type
2021-07-11 13:09:10 -04:00
Tom Moor 587a0e0517 chore: Update html import related deps 2021-07-11 10:02:35 -04:00
Tom Moor 686ecdfa92 fix: CSS syntax error 2021-07-09 14:09:52 -04:00
Translate-O-Tron bb019b081f New Crowdin updates (#2281) 2021-07-09 05:55:06 -07:00
Saumya Pandey 7d5fbeb7b0 fix: Add access to document TOC on mobile (#2279)
* Add TOC button for mobile

* Undo NewDocumentMenu changes

* Place the toc button in the correct position.

* Pass menu props to menuitem

* Update app/menus/TableOfContentsMenu.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/menus/TableOfContentsMenu.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Use the existing prop type

* Write menu inside actions prop

* Prevent blank webpage behaviour for toc

* Use href instead of level to determine target

* Update app/scenes/Document/components/Header.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Add heading to menu items

* Use existing Heading component

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-07-09 04:50:27 -07:00
Tom Moor 056f89fcfd fix: Allow TOC to scroll when larger than browser height (#2296) 2021-07-09 04:07:28 -07:00
Tom Moor 0e7d352781 chore: Add fetch-retry, remove isomorphic-fetch (#2297)
* chore: Add fetch-retry, remove isomorphic-fetch

closes #2270

* test: Mock fetch
2021-07-09 04:07:18 -07:00
Tom Moor b5e4e4fe82 fix: Various mobile fixes (#2295)
* fix: Input placeholder ellipsis

* fix: Hide scrollbar on nav tabs on mobile

* fix: Header actions should be fixed on mobile

* fix: Add fade when content in tabs does not fit in available horizontal width
2021-07-08 18:32:14 -07:00
Tom Moor e41f17c701 feat: Enable Japanese translations (#2282) 2021-07-08 18:32:05 -07:00
Tom Moor 9a1c8f07d1 feat: Add documentId filter to events.list (#2287) 2021-07-08 10:12:06 -07:00
Tom Moor 241cb11493 chore: Automate running yarn-deduplicate, see comment:
https://github.com/outline/outline/pull/2283\#discussion_r665301770
2021-07-07 22:26:56 -04:00
Saumya Pandey 8195791bb2 fix: Make search query string user friendly (#2283)
* Upgrade query-string package and skip empty string

* Run yarn-deduplicate command
2021-07-07 18:45:40 -07:00
Saumya Pandey b037ae5dc1 fix: Improve isChildDocument performance (#2284) 2021-07-07 04:53:40 -07:00
Tom Moor aeba8ce4eb fix: Empty context menu when user does not have permission to update collection 2021-07-06 22:02:31 -04:00
Tom Moor 429c5fba85 0.57.0 2021-07-06 09:12:54 -04:00
Tom Moor 9495ddba25 fix: Restore previous WSS CORS behavior 2021-07-05 23:01:25 -04:00
dependabot[bot] 486a60e97c chore(deps): bump socket.io from 2.3.0 to 2.4.0 (#1831)
Bumps [socket.io](https://github.com/socketio/socket.io) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/socketio/socket.io/releases)
- [Changelog](https://github.com/socketio/socket.io/blob/2.4.0/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io/compare/2.3.0...2.4.0)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-05 17:11:40 -07:00
Tom Moor c687745263 fix: E-mail signin on incorrect subdomain should allow the process to continue instead of error
closes #2276
2021-07-05 19:25:21 -04:00
Translate-O-Tron 1b92993b90 fix: New Portuguese, Brazilian translations from Crowdin (#2271) 2021-07-05 13:37:09 -07:00
Tom Moor 181a20a268 fix: More context menu fixes 2021-07-05 16:35:46 -04:00
Tom Moor f8ffa4e25a tweak sidebar item background 2021-07-04 18:44:09 -04:00
Farzad 7e139ca8f7 fix: nested link positions for RTL titles in sidebar (#2272) 2021-07-04 12:08:05 -07:00
Tom Moor bb58db507d fix: ew-resize -> col-resize cursor 2021-07-04 11:54:29 -04:00
Translate-O-Tron 49bf86d6d9 New Crowdin updates (#2268) 2021-07-04 06:54:52 -07:00
Tom Moor 286a15cf10 fix: Clicking dropdown menu items in FF (#2269)
* fix: Clicking dropdown menu items in FF
closes #2264

* fix: Anchor items, add comment

* fix: CI test memory issues
2021-07-04 06:54:40 -07:00
Tom Moor f65469b777 lockfile 2021-07-03 21:22:52 -04:00
Translate-O-Tron fe65a79d66 New Crowdin updates (#2267) 2021-07-03 07:02:01 -07:00
Tom Moor a1d5ac0907 RTL document support (#2263)
* Basic RTL support in documents

* fix: DocumentListItem and ReferenceListItem for RTL content
2021-07-03 07:00:10 -07:00
Tom Moor 04eabe68a7 feat: Enable traditional Chinese translations (#2266) 2021-07-02 12:08:08 -07:00
Tom Moor 1c0c694c22 fix: Email auth should allow same guest user on multiple subdomains (#2252)
* test: Add email auth tests to establish current state of system

* fix: Update logic to account for dupe emails used between subdomains

* test

* test
2021-07-02 12:07:43 -07:00
Translate-O-Tron 2ae74f2834 New Crowdin updates (#2262) 2021-07-02 11:23:02 -07:00
Tom Moor 0f01fc5faa test: Reduce memory usage by not requiring stores into all (#2265) 2021-07-02 11:16:07 -07:00
Tom Moor 7f1322b7ba fix: Down arrow in search input should move focus to results (#2257)
closes #2253
2021-07-01 15:01:30 -07:00
dependabot[bot] 3c98133e24 chore(deps): bump socket.io-parser from 3.3.1 to 3.3.2 (#2258)
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/3.3.2/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-07-01 12:08:57 -07:00
Tom Moor 088353d61f fix: Data loading state not reset when props change to PaginatedList (#2254)
* fix: Data loading state not reset when significant props change to PaginatedList

closes #2251

* test: Add enzyme and component test
2021-06-26 21:49:25 -07:00
Translate-O-Tron 31180619e1 New Crowdin updates (#2182) 2021-06-26 13:43:54 -07:00
Saumya Pandey 9fccc280d7 fix: Add ability to permanently delete documents in trash (#2192)
* Align false conditions before true

* Update documents.delete endpoint for permanent delete

* Add permanent delete to events table and integrate with socket.io

* Add permanent delete to document menu

* Update parentDocumentId of direct child to null

* Add translation

* Add test for permanent delete

* Add space

* Update app/scenes/DocumentPermanentDelete.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/stores/DocumentsStore.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update server/commands/documentPermanentDeleter.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/scenes/DocumentPermanentDelete.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Change socket room from team to collection

* Add translation

* Create log func for commands

* Move tests from utils to permanentDeleter command

* Add additional tests

* Set redirect to trash

* Return promise from beforeEach

* Add undeleted documents validation

* Include deleteAt attribute in db query

* Update server/commands/documentPermanentDeleter.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* tweak language

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-06-25 16:14:40 -07:00
Tom Moor c69b4efc34 fix: Aligned images do not load in publicly shared documents (#2248) 2021-06-25 10:09:44 -07:00
Tom Moor 3cec6b4903 fix: Allow for offline development 2021-06-21 21:40:28 -07:00
Tom Moor ede7f2e3e6 fix: Bump RME (table and image fixes) 2021-06-21 17:39:14 -07:00
Tom Moor cf8fa5ffa3 fix: Bump RME (checkbox list fixes) 2021-06-18 16:28:27 -07:00
Tom Moor 1a2a0f4264 fix: Long search term causes server error writing query to db (#2237)
closes #2234
2021-06-17 23:23:35 -07:00
Tom Moor 5f3a38bf87 fix: todo list checkbox consistency issue
closes #2179
2021-06-17 22:57:55 -07:00
Tom Moor afff3a6f25 fix: Server error when user cancels OAuth process with Azure (#2231) 2021-06-16 21:45:20 -07:00
Tom Moor b5824879a3 Merge branch 'fix/concat-tags' 2021-06-16 18:36:28 -07:00
Tom Moor 1c82e292e0 fix: Allow embed of private mindmeister embeds
fix: Missing right and bottom border of some embeds
2021-06-16 18:36:21 -07:00
Tom Moor 317289ac2a fix: Error in Datadog tracking, if only we had TS :( 2021-06-16 08:52:54 -07:00
Tom Moor 8331026cb3 fix: No search results from link editor search due to error parsing date (date-fns upgrade) 2021-06-16 07:54:56 -07:00
Tom Moor de285f2b63 feat: Add TLS ciphers option (#2217)
closes #2175
2021-06-15 21:37:41 -07:00
G. Santos d205c48296 docs: Fix SECRET_KEY variable description (#2229)
Updated the description of the SECRET_KEY variable in the .env.sample
file to clarify that the key needs to be 32 bytes long and hex-encoded.
The previous description of "32 character hexadecimal" was confusing
as it left open the possibility of a hex-encoded 16-byte key.
2021-06-15 21:37:19 -07:00
Tom Moor 277c37dae6 fix: Metrics lib to account for multiple server instances 2021-06-15 20:34:46 -07:00
Tom Moor 2c39cd6496 chore: Normalize "new" actions in settings (#2226)
* fix: Unauthorized request to views.list from shared documents

* Bump dep styled-components

* chore: Normalize 'new' actions in settings area to top right
chore: Add translation hooks to API tokens screen
chore: Move API tokens loading to paginated list
2021-06-15 19:10:50 -07:00
Tom Moor d85592b5f3 feat: DataDog metrics (#2228)
* wip

* chore: Change event names, add additional events

* fix: Not counting connect events
2021-06-15 19:10:38 -07:00
Tom Moor cdf0df0faa Bump dep styled-components 2021-06-13 18:26:25 -07:00
Tom Moor 48f54b5aa2 fix: Unauthorized request to views.list from shared documents 2021-06-13 18:24:02 -07:00
Tom Moor 2ca57fc7cf fix: 3 locations with return undefined (not compatible with React 17) 2021-06-13 17:47:17 -07:00
Tom Moor 470920e2c3 feat: Allow templates from any collection to be used
fix: Hover state of context menu items with icons
2021-06-13 17:43:50 -07:00
Tom Moor beee8ebee7 fix: Sidebar flash when moving between collection/document due to mobx-react upgrade 2021-06-13 17:22:35 -07:00
Tom Moor 9f05c9bd43 chore: Upgrade React to v17 (#2045)
* chore: Upgrade React v17

* chore: Upgrade additional deps to reduce warnings

* fix: Restore react-table dep

* Bump react-avatar-editor, mobx-react

* Remove unmaintained @rehooks/window-scroll-position dep

* Bump react-waypoint dep for React 17 support

* fix: Syntax error in autotrack chunk name comment
2021-06-13 15:23:53 -07:00
Tom Moor 65be808556 fix: Cause of sporadic test failures in CI, promise not returned for flushdb 2021-06-13 14:52:24 -07:00
Tom Moor 89f8df619c fix: Remove export permission for read-only users (#2220) 2021-06-13 14:41:29 -07:00
Tom Moor 756ec92cdb fix: Link copied to clipboard takes dark mode styles (#2218)
Upgrade copy-to-clipboard
closes #2207
2021-06-12 15:44:58 -07:00
Dave a8e2e349e9 fix: change metaDisplay key to Alt for "Table of contents" (#2187)
* change `metaDisplay` key to Alt for "Table of contents"

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-06-12 15:37:35 -07:00
Tom Moor 25f745e7e5 fix: Text alignment in templates menu
closes #2204
2021-06-12 13:31:22 -07:00
Nainterceptor 07b1811993 feat: Use SMTP_SECURE environment variable to force secure parameter of smtp configuration (#2214) 2021-06-12 11:01:48 -07:00
Saumya Pandey d71f0ae6bd fix: Two restore options when an archived document is deleted (#2194)
* Merge two menu items

* Add deletedAt guard condition in document unarchive policy

* Make the parentDocumentId null

* Update test
2021-06-10 22:52:32 -07:00
Tom Moor f58032d305 fix: Flash of sidebar when first loading Document chunk 2021-06-09 18:01:35 -07:00
Saumya Pandey 6beb6febc4 fix: Use friendly urls for collections (#2162)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-06-09 17:48:48 -07:00
Saumya Pandey a6d4d4ea36 fix: Add Portugese, Brazil to language options (#2164)
* Add Portugese, Brazil to language options

* Upgrade date-fns package

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-06-09 17:42:14 -07:00
Tom Moor a99f6bed42 feat: Return publicly shared document title in SSR HTML (#2191)
* feat: Return publicly shared document title in SSR HTML
closes #2146

* tests
2021-06-09 17:41:39 -07:00
Tom Moor 4cd61db1ea fix: Move views loading to avoid duplicate request 2021-06-08 21:13:56 -07:00
Tom Moor 0db7bb7f3e Bump editor
closes #2156
closes #2067
2021-06-07 20:32:41 -07:00
Tom Moor d8ca9c6111 fix: Server error if non-array passed to users.invite 2021-06-07 20:28:28 -07:00
Dave 4a8d357084 style: add option background for InputSelect (#2188) 2021-06-07 18:34:01 -07:00
Yao Wang e0fb76cb63 documentation: Instructions for local development (#2180)
* Fix the instruction for local development

* update readme for Slack OAuth in local development

* Fix the callback URL setting instruction
2021-06-07 18:11:45 -07:00
Saumya Pandey ffed38bf71 fix: Prevent API request for views (#2193) 2021-06-07 18:10:54 -07:00
Tom Moor b4c08a027b fix: Remove hover state css on sidebar items on mobile
closes #2043
2021-06-06 19:56:31 -07:00
Tom Moor 74e0f4dfb3 fix: Parallelize loading attachments in document presenter (#2184)
closes #2157
2021-06-05 18:40:55 -07:00
Tom Moor 5c7f2cf164 feat: Add optional http logging in production (#2183)
* feat: Add optional http logging in production
closes #2174

* Update app.js
2021-06-05 15:19:54 -07:00
Tom Moor f517a2cecb chore: Add React.StrictMode
closes #2177
2021-06-05 14:59:14 -07:00
Saumya Pandey a19ac6aa5f fix: Failure loading collections on frontend results in loading loop (#2176)
Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-06-05 09:52:49 -07:00
Saumya Pandey ddbbb963b6 fix: Add guard condition for matchMedia usage (#2178) 2021-06-05 09:51:42 -07:00
Viorel Cojocaru ba24a3318e Fix chunks setup (#2181)
* build: Webpack config - use named chunk ids

prevent invalidation across builds by using a deterministic chunkId algorithm

* fix: Autotrack chunk name syntax
2021-06-05 09:50:38 -07:00
Viorel Cojocaru 7a6491cf0d build: Webpack config - allow package.json module field usage (#2173)
- revert resolve.alias to default
- revert bundless-* package aliases to commonjs folder to avoid transpiling
2021-06-04 18:18:17 -07:00
Tom Moor 0c8d4428fc Update stale.yml 2021-06-04 09:11:09 -07:00
Viorel Cojocaru b19fd799ef chore: Update @relative-ci/agent to v2 (#2171) 2021-06-03 22:02:38 -07:00
Viorel Cojocaru 082ced3072 build: Add async chunk names (#2170) 2021-06-03 22:01:23 -07:00
Tom Moor 1f49b35c89 documentation: Improve notes around SECRET_KEY generation 2021-06-03 08:30:53 -07:00
Tom Moor 9817e2f3bf 0.56.0 2021-06-02 12:52:19 -07:00
Translate-O-Tron 04d7c7ac0e New Crowdin updates (#2143) 2021-06-02 12:51:14 -07:00
Tom Moor e625e77a56 fix: Data loading loop on old browsers 2021-06-02 12:45:07 -07:00
Tom Moor 636023aceb fix: Bump RME, improved image download behavior in editor 2021-05-24 20:56:58 -07:00
dependabot[bot] f2dfed4c72 chore(deps): bump browserslist from 4.14.7 to 4.16.6 (#2149)
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.14.7 to 4.16.6.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.14.7...4.16.6)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-24 18:35:53 -07:00
Tom Moor 8cfa724200 feat: Animate disclosure when toggling sidebar items 2021-05-22 21:22:28 -07:00
Tom Moor 6c011eb9b5 fix: Guard empty documentStructure 2021-05-22 21:12:47 -07:00
Tom Moor 7dc11e5b86 fix: Local cache for shared link share trees to reduce render flashing 2021-05-22 20:03:50 -07:00
Tom Moor 44920a25f4 feat: Nested document sharing (#2075)
* migration

* frontend routing, api permissioning

* feat: apiVersion=2

* feat: re-writing document links to point to share

* poc nested documents on share links

* fix: nested shareId permissions

* ui and language tweaks, comments

* breadcrumbs

* Add icons to reference list items

* refactor: Breadcrumb component

* tweaks

* Add shared parent note
2021-05-22 19:34:05 -07:00
Tom Moor dc4b5588b7 feat: Add 'Descript' embed (#2144) 2021-05-22 19:21:56 -07:00
Tom Moor 635910195b i18n 2021-05-22 17:18:10 -07:00
Tom Moor eaf2e50af8 feat: Add 'download image' button
feat: Enable Enter+Shift shortcut in blockquotes
fix: Improve behavior of caret around inline code marks
fix: Disallow pasting embeds in table cells
2021-05-22 17:17:46 -07:00
Tom Moor 505ed3403a fix: Bump RME, improves behavior typing words with underscores 2021-05-20 19:29:59 -07:00
Tom Moor b93d15e967 fix: PaginatedList loading loop 2021-05-20 19:21:30 -07:00
Tom Moor 028eb72f9c fix: Restore behavior of displaying document collaborators in facepile 2021-05-19 22:05:17 -07:00
Tom Moor b0196f0cf0 feat: Rebuilt member admin (#2139) 2021-05-19 21:36:10 -07:00
Translate-O-Tron 833bd51f4c New Crowdin updates (#2120) 2021-05-18 20:00:18 -07:00
Tom Moor 14d9adefe7 test 2021-05-15 18:22:42 -07:00
Tom Moor ec3ea09b2d fix: Return lastActiveAt 2021-05-15 18:14:44 -07:00
Tom Moor 2c0f14f07b fix: Explicit import of fetch-with-proxy 2021-05-13 17:20:24 -07:00
Tom Moor a93d034091 fix: Moving documents between collections does not update attachment permissions (#2136)
* fix: Copy attachments when neccessary and moving between collections

* test: regression
2021-05-12 22:38:24 -07:00
Tom Moor 447371f35a fix: Add server-side proxy support via fetch-with-proxy (#2044)
* fix: Add server-side proxy support via fetch-with-proxy

closes #1893

For some fun discussion on why this is required, see this issue: https://github.com/nodejs/node/issues/8381

* lint
2021-05-12 22:37:32 -07:00
Tom Moor 3bd56fff9e fix: Search query backslash replacement only touched first instance
closes #2111
2021-05-12 20:27:14 -07:00
Tom Moor 9d03c89c02 chore: Return new permissions-policy header on app pages
closes #2040
2021-05-12 20:16:55 -07:00
Tom Moor 9f226cf3b4 fix: Extra space on lhs when printing in Firefox, closes #2128 2021-05-12 20:06:58 -07:00
Tom Moor d01e3f7c72 fix: Print styles in dark mode when OS is light mode
closes #2124
2021-05-12 20:00:10 -07:00
Tom Moor 2cb0bab82a fix: Welcome emails should not be sent when inviting a user (#2132)
* chore: Bump nodemailer

* fix: Welcome email sent to invites

* test: Add regression test for emails from accountProvisioner
2021-05-11 18:59:31 -07:00
dependabot[bot] 456a7e497b chore(deps): bump nodemailer from 4.7.0 to 6.4.16 (#2131)
Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 4.7.0 to 6.4.16.
- [Release notes](https://github.com/nodemailer/nodemailer/releases)
- [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodemailer/nodemailer/compare/v4.7.0...v6.4.16)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-11 18:11:36 -07:00
Saumya Pandey a39f7a4e55 fix: Remove application/octet-stream as valid frontend mimetype (#2126)
* Remove application/octet-stream and add explicit extensions

* Modify the condition to check for extensions too
2021-05-11 08:07:41 -07:00
Tom Moor fed3774cee chore: Bump RME 2021-05-09 22:36:20 -07:00
Saumya Pandey 985f0da674 fix: Move collection index validation logic to a context assert function (#2116)
* Abstract validation logic for readability

* Add index validation in collections.move

* Add tests
2021-05-09 22:30:37 -07:00
dependabot[bot] 721e7466e6 chore(deps): bump hosted-git-info from 2.8.8 to 2.8.9 (#2127)
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-09 19:28:51 -07:00
Tom Moor 8e1d9f0a7d fix: Welcome collection should be visible to all by default 2021-05-05 21:12:49 -07:00
Tom Moor 71de0c7e5f fix: Currently viewing users should be ordered to top 2021-05-05 21:11:09 -07:00
Tom Moor 4f4067c449 fix: Upgrade RME, fixes image flicked post-upload in editor 2021-05-05 20:09:37 -07:00
Tom Moor b945b614f8 fix: Layout of Keyboard Shortcuts guide for languages where definition wraps onto two lines 2021-05-05 20:05:49 -07:00
Tom Moor 896ee5c20d feat: Improved viewers popover (#2106)
* refactoring popover

* feat: DocumentViews popover

* i18n

* fix: tab focus warnings

* test: Add tests around users.info changes

* snapshots
2021-05-05 19:35:23 -07:00
Translate-O-Tron e984a3dcdb New Crowdin updates (#2100)
* fix: New Polish translations from Crowdin [ci skip]

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

* fix: New German translations from Crowdin [ci skip]
2021-05-05 19:35:04 -07:00
Tom Moor 69802cc985 fix: Add application/octet-stream as a valid mimetype for docx uploads (#2105)
* fix: Add application/octet-stream as a valid mimetype for docx uploads

* fix: Include application/octet-stream in frontend filter
fix: Add file size and file type guards

* Validate .docx extension in files with application/octet-stream mimetype

* refactor: Move MAXIMUM_IMPORT_SIZE to an optional environment config
fix: Add file size check on server too

Co-authored-by: Saumya Pandey <sp160899@gmail.com>
2021-05-05 18:48:37 -07:00
Saumya Pandey 6ef8d9ddb3 fix: Handle null case (#2118) 2021-05-05 18:47:23 -07:00
John Viscel M. Sangkal d21594a6f4 fix: Add onClick event listener to show Appearance Menu options in mobile (#2119) 2021-05-05 18:46:57 -07:00
Tom Moor 974d6b2cbe fix: Submenu overflow broken 2021-05-05 09:13:44 -07:00
Tom Moor aa3cb22703 test: Fix tests around utils.gc 2021-05-03 21:39:01 -07:00
Tom Moor 49ffcda8e0 fix: 'Post to channel' functionality does not work unless Slack SSO used (#2099)
* fix: 'Post to channel' functionality does not work unless Slack SSO used

* test: And this is why we have tests
2021-05-01 16:35:00 -07:00
Tom Moor 77d6adb73b feat: Signup query params tracking (#2098)
* feat: Add tracking of signup query params

* fix: Headers already sent to client

* fix: OAuth error wipes previously written query params cookie
2021-05-01 13:46:08 -07:00
Tom Moor 4d68a34897 fix: ReDoS attack vulnerability when searching documents that contain many space characters
see: https://github.com/outline/outline/pull/2097
see: https://snyk.io/vuln/SNYK-JS-REMOVEMARKDOWN-73635
2021-04-28 22:44:05 -07:00
Tom Moor 61b2e63a44 Merge branch 'main' of github.com:outline/outline 2021-04-28 22:40:53 -07:00
Translate-O-Tron ae940dd255 New Crowdin updates (#2048) 2021-04-27 20:30:31 -07:00
Tom Moor b13626631c fix: Space for overflow menu on sidebar items 2021-04-27 18:58:37 -07:00
Tom Moor 7221e51b96 chore: Move settings screens to Scene component (#2092)
* chore: Convert groups and people settings screens to Scene/functional

* chore: ImportExport to Scene component

* Remaining settings scenes
2021-04-27 18:46:58 -07:00
Tom Moor b89f4c36f4 chore: Rename Authentication -> IntegrationAuthentication (#2091) 2021-04-27 18:42:45 -07:00
Tom Moor 829cc14d36 build:i18n 2021-04-27 18:07:11 -07:00
Tom Moor 8009e8f691 fix: Missing bg blur, closes #2082 2021-04-27 17:29:22 -07:00
Tom Moor ab2aaf7b7b feat: Upgrade RME – includes new page break functionality 2021-04-27 17:21:45 -07:00
dependabot[bot] 65b4480e93 chore(deps): bump redis from 3.0.2 to 3.1.2 (#2090)
Bumps [redis](https://github.com/NodeRedis/node-redis) from 3.0.2 to 3.1.2.
- [Release notes](https://github.com/NodeRedis/node-redis/releases)
- [Changelog](https://github.com/NodeRedis/node-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NodeRedis/node-redis/compare/v3.0.2...v3.1.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-27 17:05:32 -07:00
Tom Moor 6de793e94e fix: uuid import broken by dep bump 🤦‍♂️ 2021-04-25 12:54:06 -07:00
Tom Moor 2d22399bbc fix: Correctly guard against last admin deleting their account (#2069)
* fix: Correctly guard against last admin deleting their account

* test
2021-04-24 20:52:46 -07:00
Tom Moor 3fbb3a2403 fix: Continued undefined error in serverWorker registration 2021-04-24 12:50:30 -07:00
Tom Moor d45178cb44 chore: Remove dependency on twemoji 2021-04-23 23:24:54 -07:00
Tom Moor 5786a03f33 chore: Update uuid package, removes dupe dependency 2021-04-23 18:48:47 -07:00
Tom Moor 011a1383ec chore: Upgrade tmp dependency 2021-04-23 18:44:24 -07:00
Tom Moor 72d7b5734d chore: Upgrade slug dependency 2021-04-23 18:40:25 -07:00
Tom Moor b6fe3cb556 chore: Upgrade mammoth for html import fixes 2021-04-23 18:35:54 -07:00
Tom Moor 1e2224cb0d chore: Upgrade dd-trace 2021-04-23 18:32:49 -07:00
Tom Moor 0477060b35 chore: Upgrade relative-ci/agent 2021-04-23 18:31:43 -07:00
Tom Moor a261abcdef Merge branch 'main' of github.com:outline/outline 2021-04-23 18:25:43 -07:00
Tom Moor f64d0ce660 feat: Share flyover (#2065)
* feat: Implement share as flyover instead of modal

* refactor

* i18n
2021-04-23 17:31:27 -07:00
Tom Moor f27072d06e feat: More space for content on larger screens 2021-04-23 16:41:40 -07:00
Tom Moor c8055e40bb fix: Content appearing behind status bar in iOS PWA on some models of phone 🤷 2021-04-23 14:57:38 -07:00
Tom Moor cfae180093 chore: Upgrade Sentry 6.1.0 -> 6.3.1 2021-04-23 12:50:40 -07:00
Tom Moor 094c6418c9 Update LICENSE 2021-04-23 12:50:19 -07:00
Tom Moor 99b1bf0ecb fix: Avoid rare 'undefined is not a function' when attempting to register a server worker on Windows Chrome 2021-04-23 12:31:27 -07:00
Tom Moor 3b696cfa9a fix: Page reloads in Firefox when clicking some menu items (#2060)
* fix: Some context menu items result in page reload in Firefox

closes #1877

* fix: Display of sidebar link actions on hover
2021-04-23 12:25:15 -07:00
Tom Moor eb6acdae20 fix: CMD+F not working on screens with keyboard shortcut guide (#2066) 2021-04-23 12:10:02 -07:00
Tom Moor a818c7a924 fix: Hover card behind subheadings, previously it relied on being a portal without any explicit depth
closes #2062
2021-04-23 12:09:30 -07:00
Tom Moor d157e9bfcd 0.55.0 2021-04-22 20:23:24 -07:00
Tom Moor f2052c2a05 fix: Escape key in keyboard shortcut guide should clear search input if search term 2021-04-22 19:37:40 -07:00
Tom Moor 40b4270e35 chore: Faster source map in dev 2021-04-22 18:59:59 -07:00
Tom Moor 16c60a0d59 fix: URLSearchParams polyfill via core-js upgrade (#2059)
* fix: URLSearchParams polyfill via core-js upgrade

* deduplicate

* testing, remove manual imports

* chore: bump rme
2021-04-22 18:21:27 -07:00
Mark Steve Samson 1a183ba0fc Document and include PGSSLMODE in sample env file (#2052) 2021-04-21 18:15:23 -07:00
Tom Moor 2ffc0ae81c feat: New keyboard shortcuts guide (#2051)
* feat: Add search

* feat: New design for keyboard shortcuts guide
feat: Include quick search
fix: Add missing shortcuts

* tweaks

* fix: Two other spots that should trigger guide-style instead of modal

* sink,lift -> indent,outdent

* fix: Animation should slide out as well as in
2021-04-21 18:15:07 -07:00
Tom Moor 50fdd73610 fix: Remove HMR in test env (#2054) 2021-04-21 17:53:53 -07:00
dependabot[bot] a134773d4e chore(deps): bump ssri from 6.0.1 to 6.0.2 (#2050)
Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-20 17:37:39 -07:00
Tom Moor 317c52df62 fix: Improve error handling for Azure-specific errors not captured in OAuth2 strategy 2021-04-18 22:41:27 -07:00
Tom Moor 04b8d7ae7b Normalize sidebar style 2021-04-18 21:52:54 -07:00
Tom Moor 3569d2fee7 chore: Update caniuse 2021-04-18 19:52:47 -07:00
Tom Moor ab267ce38d fix: Disable polling on custom domain, closes #2041 2021-04-18 18:58:26 -07:00
Tom Moor fa52bc5afd chore: Slack integration screen improvements (#2049)
* feat: Add collection iconography and colors to Slack settings page
fix: Use standardized list components
fix: Slack icon size
chore: Convert to translation strings

* fix: Missing translation, convert to Scene
2021-04-18 18:34:49 -07:00
Tom Moor bf668d6347 fix: Double documents.info request loading public share links 2021-04-18 11:34:11 -07:00
Tom Moor 7f9cba9819 feat: Record share link last accessed time (#2047)
* chore: Migrations

* chore: Add recording of share link views

* feat: Add display of share link accessed date in admin

* translations

* test

* translations, admin pagination
2021-04-18 09:38:13 -07:00
Tom Moor e9f083feb8 fix: Document title with slashes produces folders in exported zip file
closes #2036
2021-04-17 19:30:31 -07:00
Tom Moor 03d90b3f15 fix: Hide secondary actions in document header on mobile
closes #2042
2021-04-17 18:14:24 -07:00
Tom Moor 2432b4dcbd fix: Editor lightbox stacked below sidebar 2021-04-17 18:08:09 -07:00
Translate-O-Tron 2c2c1341f7 fix: New Spanish translations from Crowdin [ci skip] (#2035) 2021-04-17 13:24:17 -07:00
Tom Moor 7a8ccdb229 feat: Microsoft authentication (#1953)
closes #755
2021-04-17 13:22:18 -07:00
Tom Moor b2d703bee4 fix: Improved mobile styling
fix: Severla context menus miss-positioned
fix: Search filters not large enough on mobile
fix: Deep black background on mobile to match native apps
fix: Sticky document header allowing horizontal scrolling on mobile
2021-04-17 10:40:39 -07:00
Tom Moor c46a032f0b fix: CSS stacking context issue with behind menu backdrops on mobile
Moving the animation to the same element that has position: fixed resolves
2021-04-16 19:02:43 -07:00
Tom Moor 940ad8479e perf: Remove collaborators from documents.list response (#2039)
* fix: Remove unused, unperformant query

* lint

* collaborators -> collaboratorIds
2021-04-15 22:49:16 -07:00
Tom Moor c5401a467d fix: Overlapping header, closes #2038 2021-04-15 20:30:05 -07:00
Tom Moor 1dd97c1ddd feat: Show mobile-style (slide from bottom) menus on mobile (#2025)
* feat: Show mobile-style (slide from bottom) menus at responsive viewport sizes

* More mobile improvements

* fix: Safari compatability
2021-04-13 21:43:24 -07:00
Translate-O-Tron f37371c16e New Crowdin updates (#2027) 2021-04-13 21:31:35 -07:00
Tom Moor 62f9262b2c fix: Improved handling of authentication edge-cases (#2023)
* fix: authentication records not cleaned up for deleted user
closes #2022

* fix: Improve debugging for duplicate providerId sign-in requests
2021-04-11 19:39:31 -07:00
Saumya Pandey bc4fe05147 feat: Read-only users (#1955)
* Introduce isViewer field

* Update policies

* Make users read-only feature

* Remove not demoting current user validation

* Update tests

* Catch the unhandled promise rejection

* Hide unnecessary ui elements for read-only user

* Update app/scenes/Settings/People.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Remove redundant logic for admin only policies

* Use can logic

* Update snapshot

* Remove lint error

* Update snapshot

* Minor fix

* Update app/menus/UserMenu.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update server/api/users.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/components/DocumentListItem.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Update app/stores/UsersStore.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>

* Use useCurrentTeam hook in functional component

* Update translation

* Update ternary

* Remove punctuation

* Move the functions to User model

* Update share policy and shareMenu

* Rename makeAdmin to promote

* Create updateCounts function and Rank enum

* Update tests

* Remove enum

* Use async await, remove enum and create computed accessor

* Remove unused variable

* Fix lint issues

* Hide templates

* Create shared/types and use rank type from it

* Delete shared/utils/rank type file

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-04-11 19:39:17 -07:00
Tom Moor cdc7f61fa1 chore: Enable HMR for frontend code (#2024)
* chore: Enable HMR for frontend code
closes #2021

* revert
2021-04-11 15:09:00 -07:00
Tom Moor 2a6dfdea5d fix: Highlight states and dropzones when user does not have permission to import 2021-04-10 13:54:05 -07:00
Translate-O-Tron de25ea0ed9 fix: New Chinese Simplified translations from Crowdin [ci skip] (#2020) 2021-04-09 08:43:23 -07:00
Tom Moor d2227a2488 Update stale.yml 2021-04-08 22:56:22 -07:00
Translate-O-Tron 3e050727cb fix: New Chinese Simplified translations from Crowdin [ci skip] (#2019) 2021-04-08 21:20:10 -07:00
Tom Moor 326518873e fix: Logout suspended users immediately 2021-04-08 21:04:34 -07:00
Translate-O-Tron ed779a250f New Crowdin updates (#2011) 2021-04-08 20:40:34 -07:00
Tom Moor 190f0b6dc5 fix: Improve handling of suspended users signing in with email (#2012)
* chore: Separate signin/auth middleware
fix: Email signin token parsed by JWT middleware
fix: Email signin marked as active when logging in as suspended
fix: Suspended email signin correctly redirected to login screen
closes #1740

* refactor middleware -> lib

* lint
2021-04-08 20:40:04 -07:00
Tom Moor 1a889e9913 fix: Add embed support for lucid.app domain
closes #2017
2021-04-07 21:48:45 -07:00
Tom Moor b3203857d7 Create FUNDING.yml 2021-04-06 19:32:07 -07:00
Tom Moor 5762fb33d9 chore: Improve display of configuration errors (#2014)
* chore: Show all configuration errors at once
fix: Remove requirement for deprecated Slack key
fix: Add requirement for UTILS_SECRET

* chore: Add funding/sponsorship message
2021-04-06 19:29:59 -07:00
Tom Moor 1101ea428b feat: Drop to import onto collection scene (#2005)
* Refactor to functional component

* feat: Basic drag and drop into collection
2021-04-05 19:05:27 -07:00
Translate-O-Tron b4213e498c New Crowdin updates (#1951) 2021-04-05 18:28:27 -07:00
Saumya Pandey f9f76d4438 Format local development instructions (#2007) 2021-04-05 17:19:44 -07:00
Tom Moor 4a9571a174 fix: Alignment of backlinks and references (#2006)
closes #1998
2021-04-05 17:19:31 -07:00
Tom Moor bf856dbafa Merge branch 'main' of github.com:outline/outline 2021-04-04 11:04:46 -07:00
Nilay Sharma 0e54302d75 stretch email login input (#2004)
* stretch email login input

* Update InputLarge.js

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-04-04 09:57:44 -07:00
Tom Moor 4777176d84 fix: User afterCreate hook using deprecated column 2021-04-03 18:37:39 -07:00
Tom Moor 3ffa21b07f fix: Unneeded object keys in API response 2021-04-03 17:18:26 -07:00
Tom Moor 8cbc873451 chore: Clarify flow on /create page 2021-04-03 14:29:08 -07:00
Tom Moor d2e8311b39 chore: Add tracking ref to branding on share links 2021-03-31 21:52:49 -07:00
Tom Moor 810257bcf5 fix: Improve dark mode styling
fix: Improve user and group list styling
fix: Member list reload when changing permissions, closes #1999
2021-03-31 20:57:30 -07:00
Tom Moor 2ef0caba88 fix: Server error when invalid 'sort' field is passed from an API client (#2000) 2021-03-31 18:54:02 -07:00
Tom Moor 2e64972574 fix: Error in shares.info endpoint when user originally creating share has been deleted 2021-03-31 18:04:40 -07:00
Tom Moor 7e1b07ef98 feat: Add read-only collections (#1991)
closes #1017
2021-03-30 21:02:08 -07:00
Tom Moor d7acf616cf chore: Bump rich-markdown-editor 2021-03-30 20:39:41 -07:00
Tom Moor c5569bd365 feat: Add /logout route for SLO support 2021-03-30 20:10:52 -07:00
Tom Moor 25023fb086 chore: Fix modal nesting, remove react-modal (#1996)
* chore: Fix modal nesting, remove react-modal

* tweak

* fix: Janky route jump when accessing Document -> Move from non-document scene
2021-03-30 18:46:14 -07:00
Tom Moor 07425f4243 Minor context menu visual updates 2021-03-29 22:28:40 -07:00
Tom Moor b5dcb1b3fe fix: JS error from #1962 refactor when Google or Slack auth credentials are missing 2021-03-29 22:03:40 -07:00
Tom Moor ae57cdea2a fix: GA should load on public share pages, closes #1992 2021-03-29 22:02:38 -07:00
Tom Moor 8599b60a6c fix: group -> createGroup 2021-03-26 20:17:46 -07:00
Tom Moor e00a437f2f feat: authenticationProviders API endpoints (#1962) 2021-03-26 11:31:07 -07:00
Tom Moor 626c94ecea fix: Bump react-dropzone for eroneous 'green plus' cursor fix
https://github.com/react-dropzone/react-dropzone/issues/1042
2021-03-26 11:17:50 -07:00
Tom Moor 889186e510 fix: Close appearance menu when selecting a theme
fix: Position disclosure correctly when menu has submenu
fix: More reliably close context menus
2021-03-26 11:15:58 -07:00
Tom Moor 4166257283 chore: Improved context menu behavior 2021-03-24 19:23:16 -07:00
Tom Moor 6a7d7af767 fix: Sticky archive header 2021-03-24 18:42:12 -07:00
Tom Moor 46912f8ddb fix: Single share record per document (#1984) 2021-03-24 18:28:38 -07:00
Tom Moor 877c01f723 feat: Show 'Edit' button when visiting share link as signed in user with permission (#1980) 2021-03-23 19:22:15 -07:00
Tom Moor 97158b1337 fix: Invisible list bullets in Firefox 2021-03-23 19:02:19 -07:00
Tom Moor 8d8bde4b8b closes #1784 2021-03-22 22:23:03 -07:00
Tom Moor 059fca27b3 buildUser -> buildAdmin 2021-03-22 20:59:11 -07:00
Tom Moor 9f6ba798c8 Merge branch 'main' of github.com:outline/outline 2021-03-22 20:51:45 -07:00
Tom Moor 349e971a8a chore: Serialize domain policies on team (#1970)
* domain policies exposed on team, consistency

* fix: Remove usage of isAdmin in frontend

* test
2021-03-22 20:50:12 -07:00
Tom Moor 9af9d3a008 chore: Bump ioredis for fixes
chore: Remove sequelize language from user-facing db migrations
2021-03-22 18:41:54 -07:00
Tom Moor bb5443452b flow 2021-03-21 18:52:42 -07:00
Tom Moor b3353f20d5 chore: Move error logging in passport 2021-03-21 18:36:10 -07:00
Tom Moor 200f25c4b2 0.54.0 2021-03-21 10:27:27 -07:00
Saumya Pandey f1296cc8e3 Add import document menuitem (#1966) 2021-03-20 23:20:49 -07:00
Tom Moor ad8c08497c fix: Moving document in private collection returns incorrect policies (#1969)
* fix: Return no policies when collection doesn't change
fix: Return correct policies when it does change

* test
2021-03-19 08:01:51 -07:00
Tom Moor 7891a8ee8b fix: Cannot create collection if all collections deleted 2021-03-19 08:01:13 -07:00
Tom Moor 56c4acc18f fix: Background on error details not correct in dark theme 2021-03-18 23:56:05 -07:00
Tom Moor 1b972070d7 feat: Enforce single team when self-hosted (#1954)
* fix: Enforce single team when self hosting

* test: positive case

* refactor

* fix: Visible error message on login screen for max teams scenario

* Update Notices.js

* lint
2021-03-18 21:56:24 -07:00
Nan Yu 138336639d fix: touch up UI for compact breadcrumbs (#1961) 2021-03-18 19:44:28 -07:00
Tom Moor 8ea746dbe8 Bump RME
fixes: Code does not highlight until editor is focused
fixes: Improved pasting behavior
fixes: Error when pasting iframes from elsewhere
2021-03-18 18:01:07 -07:00
Saumya Pandey 46bcc2e2ae feat: Allow sorting collections in sidebar (#1870)
closes #1759

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-03-18 17:27:33 -07:00
Tom Moor b93002ad93 fix: JS error when pasting gist link, closes #1963 2021-03-16 22:53:32 -07:00
Tom Moor a427d77076 fix #1964 – error when selecting no files to import after previously selecting files 2021-03-16 22:09:19 -07:00
Nan Yu eff56b758c feat: use flexbox to center the floating title (#1959)
* use flexbox to center the floating title

* simplify breadcumb alignment

* small adjustments

* fix alignment on actions
2021-03-15 19:24:14 -07:00
Tom Moor ffc270b567 fix: Incorrect calculation of subdomain when previously used more than once 2021-03-15 18:04:41 -07:00
Saleh Yusefnejad d86b7babb9 fix: correct GoogleSheets component class name (#1960) 2021-03-15 15:36:10 -07:00
Tom Moor ec57951087 feat: Upgrade editor - move list items with keyboard 2021-03-14 15:58:50 -07:00
Tom Moor 2385f41a98 chore: Show 'private' badge on private collections (#1952)
* chore: Show 'private' badge on private collections

* lint

* fix: Missing translation mapping
2021-03-12 16:41:26 -08:00
Translate-O-Tron bdb684a4be New Crowdin updates (#1950)
* 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]
2021-03-11 16:54:24 -08:00
Tom Moor 5d6f68d399 feat: Move to passport for authentication (#1934)
- Added `accountProvisioner`
- Move authentication to use passport strategies
- Make authentication more pluggable
- Change language of services -> providers

closes #1120
2021-03-11 10:02:22 -08:00
Tom Moor dc967be4fc chore: Syncs changes that were erroneously made in enterprise repo (#1949) 2021-03-10 14:56:34 -08:00
Saumya Pandey d530edcc2f fix: Remove double separator in collection menu (#1948)
* Hide separator

* Remove visible logic
2021-03-10 14:56:16 -08:00
Tom Moor 1393d1950e chore: Test performance and warnings (#1946)
* test: Do not request mailer account in test environment

* test: Dupe migrations
2021-03-10 12:04:42 -08:00
Tom Moor 0aa72036d7 fix: Templates should not be visible in collection structure 2021-03-10 09:39:42 -08:00
Tom Moor f50b88716b fix: Handle document Id in document structure does not exist in db
closes #1938
2021-03-09 22:45:40 -08:00
Tom Moor e90c02bec7 feat: Hide less popular services by default in block menu 2021-03-09 22:32:28 -08:00
Tom Moor 504b11576a bump 2021-03-09 22:04:47 -08:00
Tom Moor bac7a364d0 fix: Drag and drop images in editor, conflict with sidebar react-dnd (#1918)
* fix: Drag and drop images in editor, conflict with sidebar react-dnd
see: https://github.com/react-dnd/react-dnd/pull/3052

* Bump to non-canary

* Upgrade react-dnd

* react-dnd api changes

* lint

* fix: dnd doesn't work on first render

* remove unneccessary async

* chore: Update react-dnd (API changed again)

* restore fade
2021-03-09 18:41:30 -08:00
Tom Moor ed2a42ac27 chore: Migrate authentication to new tables (#1929)
This work provides a foundation for a more pluggable authentication system such as the one outlined in #1317.

closes #1317
2021-03-09 12:22:08 -08:00
Saumya Pandey ab7b16bbb9 fix: Centered document title moves when saving (#1943)
closes #1939
2021-03-09 12:21:29 -08:00
Translate-O-Tron d8eefc1972 New Crowdin updates (#1920) 2021-03-08 17:17:13 -08:00
dependabot[bot] b188a8ff30 chore(deps): bump elliptic from 6.5.3 to 6.5.4 (#1941)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-03-08 17:16:33 -08:00
Tom Moor e1c7b07af9 fix: Image in README was removed on Github's servers 2021-03-08 09:19:42 -08:00
Tom Moor eaadeb26e5 fix: Upgrade reakit for better context menu behavior 2021-03-01 19:17:24 -08:00
Tom Moor 0c301fcf0c fix: Enlarge scrollable area in sidebar for improved UX on small screens 2021-02-26 10:51:14 -08:00
Tom Moor a3e95023dc fix: Temporary fix for outline-icons build issue 2021-02-23 22:53:55 -08:00
Tom Moor e08b17561e fix: Capitalize Pусский 2021-02-23 10:35:50 -08:00
Tom Moor ac79a4c4cc fix: Update PWA macOS icon 2021-02-23 08:36:59 -08:00
Tom Moor e085553306 feat: Add tracking of PWA installs 2021-02-22 22:30:47 -08:00
Tom Moor 38bd1d5585 translate: Search filter dropdowns, modal 2021-02-22 22:18:00 -08:00
Tom Moor cd7cbab5ac fixes #1879 – race condition in websockets service 2021-02-22 21:53:20 -08:00
Tom Moor 2195787e7d logistics -> exporter, remove cutesy naming of lib 2021-02-22 21:51:01 -08:00
Tom Moor 04f942141f fix: Tone-down separator for PWA titlebar in dark mode 2021-02-21 22:42:22 -08:00
Tom Moor d0f1fd533a feat: Add Russian language support
closes #1916
2021-02-21 20:42:01 -08:00
Translate-O-Tron a1e885f057 New Crowdin updates (#1913) 2021-02-21 20:35:39 -08:00
Tom Moor 2ad9f69f7f fix: Scrollbars should match theme, closes #1917 2021-02-21 19:59:57 -08:00
Tom Moor 65bca35bbf Merge branch 'main' of github.com:outline/outline 2021-02-21 13:33:17 -08:00
Tom Moor a96993fda9 feat: Add PWA support to subdomains (#1915)
* fix: Remove overscroll
* Remove title from fixed header in PWA as it's displayed immediately above in application title
2021-02-21 13:32:49 -08:00
Tom Moor 9fc03b6ece fix: Cannot upload images into collection description (authentication failure) 2021-02-20 22:38:28 -08:00
Tom Moor 100360adb3 fix: Drop cursor not visible in dark theme 2021-02-20 22:35:07 -08:00
Tom Moor d277d80323 Merge pull request #1914 from outline/fix/issue-1896
fix: Documents in trash should still load their attachments
2021-02-20 13:35:41 -08:00
Tom Moor c79cfbd30d fix: Documents in trash should still load their attachments
closes #1896
2021-02-20 13:22:02 -08:00
Tom Moor e66611e771 fix: Error with search term including %, closes #1891 2021-02-20 13:03:41 -08:00
Tom Moor 903e83a618 feat: Batch Import (#1747)
closes #1846
closes #914
2021-02-20 12:36:05 -08:00
Tom Moor 4ef4ef963a i18n 2021-02-20 12:31:54 -08:00
Translate-O-Tron 51c6a19dc3 New Crowdin updates (#1906) 2021-02-19 09:28:47 -08:00
Tom Moor bbf434e2f4 fix: Disable 'Invite people…' control for non-admins (#1903)
closes #1902
2021-02-18 23:35:55 -08:00
Tom Moor 5b7018058d i18n 2021-02-18 23:30:48 -08:00
Tom Moor fae54c7957 fix: Mispositioned sticky headers in modals 2021-02-18 23:20:12 -08:00
Tom Moor fabfa6a491 Tweak language, remove original attachment once complete 2021-02-18 23:08:48 -08:00
Tom Moor c5f9412ac0 fix: Collection creator not written (bad merge from refactor while this branch has been open)
refactor: Move processing to async queue now that file can be loaded from external storage
2021-02-18 22:55:29 -08:00
Tom Moor f4c871bb62 i18n 2021-02-18 22:36:18 -08:00
Tom Moor df233c95a9 refactor: Upload file to storage, and then pass attachmentId to collections.import
This avoids having large file uploads going directly to the server and allows us to fetch it async into a worker process
2021-02-18 22:36:07 -08:00
Tom Moor 568e271738 lint 2021-02-18 21:05:21 -08:00
Tom Moor 9efed11a3e Merge branch 'main' of github.com:outline/outline into feat/mass-import 2021-02-18 20:57:01 -08:00
PedroSeda c30132e558 feat: Embed Cawemo (#1890) 2021-02-18 18:48:40 -08:00
Tom Moor b152a5595e Merge branch 'main' into feat/mass-import 2021-02-17 23:57:45 -08:00
Tom Moor 887e341e48 Add NODE_ENV to app.json 2021-02-17 19:38:44 -08:00
Tom Moor ae2f1b47e7 0.53.1 2021-02-17 00:08:04 -08:00
Tom Moor 86d9a14c5c fix: is virtual host 2021-02-16 23:52:25 -08:00
Tom Moor 6a8a83610f fix: Input data is not a String when clicking on new collection description 2021-02-16 23:42:31 -08:00
Tom Moor 54bf7a9dea fix: Restore specifying AWS endpoint for non-S3 support 2021-02-16 23:41:39 -08:00
Tom Moor 43ed7d0343 0.53.0 2021-02-16 21:18:06 -08:00
Tom Moor a81a18b173 fix: Remove hard-coded ServerSideEncryption on AWS, configure on AWS or storage provider 2021-02-16 00:16:23 -08:00
Tom Moor f18a2a048d fix: Sticky heading stacking 2021-02-16 00:15:04 -08:00
Tom Moor 7e922d8716 feat: Installable PWA (#1882) 2021-02-15 15:19:51 -08:00
Tom Moor 4b603460cb chore: Standardized headers (#1883)
* feat: Collection to standard header
feat: Sticky tabs

* chore: Document to standard header

* chore: Dashboard -> Home
chore: Scene component

* chore: Trash, Templates, Drafts

* fix: Mobile improvements

* fix: Content showing at sides and occassionally ontop of sticky headers
2021-02-14 13:18:33 -08:00
Tom Moor 32a298054d Bump RME – Editor fixes and improvements 2021-02-13 12:47:44 -08:00
Tom Moor ca2459361e chore: de-dupe lockfile 2021-02-13 09:25:04 -08:00
Tom Moor e49f3ab9fb ResizeObserver loop completed with undelivered notifications 2021-02-13 08:43:22 -08:00
Tom Moor e9338df057 Update README screenshot 2021-02-12 20:29:43 -08:00
Tom Moor 2629d6db23 fix: 'Suspended' badge misaligned on user profiles
closes #1880
2021-02-12 17:34:40 -08:00
Tom Moor b017590033 fix: 'bake' release env variables at build time 2021-02-12 17:18:55 -08:00
Tom Moor 7d244dfa1f 'bake' release env variables at build time 2021-02-12 16:53:16 -08:00
Tom Moor 2a225d81d2 chore: Update Sentry to avoid duplicate packages
chore: Pass current release version to Sentry and Datadog
2021-02-12 16:39:02 -08:00
Tom Moor 41df5c74be Add description -> Add a description 2021-02-12 16:24:31 -08:00
Tom Moor ef026b34fa Return to App -> Back to App 2021-02-12 16:21:32 -08:00
Tom Moor 1dbcc12648 feat: Inline collection editing (#1865) 2021-02-12 16:20:49 -08:00
Tom Moor 2611376b21 chore: Add optional DD tracer 2021-02-11 18:58:56 -08:00
Tom Moor a1b3cfc7de Yarn.lock 2021-02-10 20:25:26 -08:00
Tom Moor 5a478ec127 fix: Incorrect policy returned after document create/import 2021-02-09 21:29:24 -08:00
Tom Moor c0325fcaf3 Merge branch 'main' into feat/mass-import 2021-02-09 20:46:57 -08:00
Tom Moor df472ac391 feat: add total users to people management screen (#1878)
* feat: add total users to pagination

* move this.total in runInAction callback

* add total counts + counts to people tabs

* progress: use raw pg query

* progress: add test

* fix: SQL interpolation

* Styling and translation of People page

Co-authored-by: Tim <timothychang94@gmail.com>
2021-02-09 20:13:09 -08:00
Tom Moor 097359bf7c feat: Added ability to disable sharing at collection (#1875)
* feat: Added ability to disable sharing at collection

* fix: Disable all previous share links when disabling collection share
Language

* fix: Disable document sharing for read-only collection members

* wip

* test

* fix: Clear policies after updating sharing settings

* chore: Less ambiguous language

* feat: Allow setting sharing choice on collection creation
2021-02-09 19:04:03 -08:00
Tom Moor 3739bb7c55 Update translation.json 2021-02-08 21:50:34 -08:00
Tom Moor cc90c8de1c feat: Sidebar Improvements (#1862)
* wip

* refactor behaviorg

* stash

* simplify
2021-02-07 21:51:56 -08:00
Tom Moor ac6c48817c fix: Unable to select .md files by default on some machines depending on installed software 2021-02-07 16:14:03 -08:00
Tom Moor 8e3534dcbc fix: File import via collection menu regression 2021-02-07 16:13:44 -08:00
Tom Moor cada91a135 Merge main 2021-02-07 12:58:17 -08:00
Yaroslav Zhavoronkov e2d7d34f30 fix: Pass credentials with API requests when required to work with Cloudflare Access (#1867) 2021-02-06 22:49:49 -08:00
Tom Moor 0d88a1dfda Update README.md 2021-02-06 21:49:07 -08:00
Tom Moor df5a2e45c5 chore: Improved deployment documentation (#1868) 2021-02-06 21:33:56 -08:00
Tom Moor 1a7a48674b fix: link in README, add ARCHITECTURE document 2021-02-06 17:46:54 -08:00
Tom Moor e23474fa1c feat: Add parameters for filtering events (#1863)
* feat: Add parameters for filtering events

* test
2021-02-04 20:20:56 -08:00
Tom Moor 37fa13d841 fix: flash of 'Deleted Collection' when loading app on doc page 2021-02-02 22:03:02 -08:00
Tom Moor 6d88c02869 chore: Remove unused Popover component 2021-02-02 21:17:17 -08:00
Tom Moor a2fb3bb9f8 fix: Favicon should load from domain root, not current path 2021-02-02 21:13:11 -08:00
Tom Moor fb0b38fb71 fix: Mobile menu toggle button appearing in print media, closes #377 2021-02-02 20:57:08 -08:00
Tom Moor 8ff2f41068 Merge branch 'develop' of github.com:outline/outline into develop 2021-02-01 21:13:51 -08:00
Tom Moor 334dce7984 chore: Add Timing-Allow-Origin header (#1860) 2021-02-01 21:13:44 -08:00
Tom Moor 61b303831f fix: Document history sidebar layout issue 2021-02-01 21:13:31 -08:00
Tom Moor a9d60d288e feat: Automatically scroll to active item in sidebar (#1858) 2021-02-01 19:29:54 -08:00
Translate-O-Tron 3f267d7745 New Crowdin updates (#1848) 2021-01-31 23:24:10 -08:00
Tom Moor e845652cb8 flow: Convert to different <Trans> component syntax for flow compatability 2021-01-31 21:14:14 -08:00
Tom Moor 7066a45323 feat: Improve star/unstarred iconography 2021-01-31 20:53:27 -08:00
Tom Moor 654fdf1c7e fix: Guard unset language 2021-01-31 15:41:33 -08:00
Tom Moor 2a5fd0b332 test 2021-01-31 14:47:28 -08:00
Tom Moor 9ba63c6054 feat: Show nested document count on document list items on collection home 2021-01-31 14:41:18 -08:00
Tom Moor 785e208c6c lint 2021-01-31 14:41:00 -08:00
Tom Moor 9d84652dff fix: Frontend translation library expects dash separated, not underscore separated languages – this fix is required to enable working pluralization 2021-01-31 14:40:50 -08:00
Tom Moor ef6ce72cf5 fix: Recently published redirect 2021-01-31 13:01:56 -08:00
Tom Moor 7777cccf3b fix: Save regression from flow refactor 2021-01-31 12:53:52 -08:00
Tom Moor 620e4942d8 feat: Update default collection tab (#1821)
* feat: Allow listing root level documents only via documents.list

* feat: New tab on collection home

* update tab layout

* fix: Correctly sort index sorted documents.list

* revert: Tab layout changes

* fix: Missing route for recently published
fix: Redirect unknown tabs
2021-01-31 12:37:27 -08:00
Tom Moor 91ee3e62f2 fix: Reassign user on unpublish (#1857)
* findOne -> findByPk
2021-01-30 18:31:08 -08:00
Tom Moor eeb7650941 fix: New documents should sort to the top of manually organized collection 2021-01-30 00:18:56 -08:00
Tom Moor ee57f1ccf5 fix 2021-01-29 23:59:48 -08:00
Tom Moor 32f0589190 chore: Upgrade flow (#1854)
* wip: upgrade flow

* chore: More sealed props improvements

* Final fixes
2021-01-29 21:36:09 -08:00
Tom Moor ce2b246e60 fix: auth.config request should only be made on Login screen (#1852) 2021-01-29 17:54:28 -08:00
Tom Moor ae13347d55 chore: Add flow support for M1 macs 2021-01-28 23:25:37 -08:00
Tom Moor 13205171d7 chore: Improve dev efficient on M1 Mac 2021-01-28 21:01:53 -08:00
Tom Moor a912ea24f6 chore: Remove references to window.Sentry 2021-01-27 22:56:40 -08:00
Tom Moor 6fa760688b fix: Adds support for VirtualHost style AWS S3 buckets (#1847)
* Bump aws-sdk

* support virtual host buckets

* fix

* fix: VirtualHost bucket without explicit AWS_S3_FORCE_PATH_STYLE=false
2021-01-27 07:46:43 -08:00
Tom Moor 2825df29de Merge branch 'develop' of github.com:outline/outline into develop 2021-01-25 20:48:42 -08:00
Translate-O-Tron 604e97a6ce New Crowdin updates (#1835)
* fix: New French translations from Crowdin [ci skip]

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

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

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

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

* fix: New Russian 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 Thai translations from Crowdin [ci skip]

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

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

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

* fix: New Japanese 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 Thai 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]
2021-01-25 20:48:18 -08:00
milesstoetzner dc1bc44c8f feat: Google Drawings Integration (#1814)
* add google drawings integration

* add google drawings image

* update google drawings image and regex

* allow query parameter in google drawings regex

* support CDN for google drawings image
2021-01-25 20:47:23 -08:00
Tom Moor 2a55e78722 fix: Improve some editor alignment 2021-01-25 20:36:20 -08:00
Tom Moor eaf8dc5a3c fix: Text highlight of link in dark mode is impossible to read
closes #1838
2021-01-24 22:47:27 -08:00
Tom Moor f89d5adc37 fix: Ellipisis left in translation string 2021-01-24 12:09:44 -08:00
Tom Moor 978a123122 fix: 16 linting warnings 2021-01-23 10:19:08 -08:00
Tom Moor 96e65f495e chore: Remove custom VisuallyHidden component 2021-01-23 09:47:02 -08:00
Tom Moor 4106f15450 fix: Content jump when leaving edit mode 2021-01-22 23:58:34 -08:00
Tom Moor b3cd78c833 chore: Enable parameterized route profiling 2021-01-22 23:02:12 -08:00
Tom Moor 7b87fea4f4 Merge branch 'develop' of github.com:outline/outline into develop 2021-01-22 21:16:37 -08:00
Tom Moor 7e9bcb0c37 fix: More missing a11y labels 2021-01-22 21:12:25 -08:00
Tom Moor f6370ccf6d chore: Sentry performance monitoring (#1841)
* Hook up performance monitoring

* lint
2021-01-22 20:42:45 -08:00
Tom Moor 11e1108f4a fix: Unneccessary ev.preventDefault 2021-01-22 20:40:26 -08:00
Tom Moor c9fdf48c33 chore: Add missing labels to buttons without text and search inputs 2021-01-22 19:31:30 -08:00
Tom Moor 6a206de6cd chore: Add meta description 2021-01-22 19:12:39 -08:00
Tom Moor c69b393776 fix: JS error when submitting invites from sidebar-triggered modal 2021-01-22 08:57:52 -08:00
Tom Moor 6e9c456147 isMetaKey -> isModKey 2021-01-21 07:28:10 -08:00
Tom Moor 70626ffff0 feat: Organize sidebar (#1834)
* chore: Flip chinese label in language select

* feat: Add settings to sidebar, organize secondary items to bottom
2021-01-21 07:22:20 -08:00
Translate-O-Tron 993aad004e fix: New Korean translations from Crowdin [ci skip] (#1833) 2021-01-21 07:21:23 -08:00
Tom Moor 6fa9e700c8 chore: Flip chinese label in language select 2021-01-20 23:20:06 -08:00
Tom Moor 836b2e310a chore: Missing translation hooks in settings sidebar 2021-01-20 23:13:51 -08:00
Tom Moor 24ecaa8ce4 chore: Reduce default menu width 2021-01-20 23:07:48 -08:00
Tom Moor 40491fafe9 fix: Document star/unstar from list item navigates to document (regression) 2021-01-20 23:07:39 -08:00
Tom Moor 111212b038 feat: Resizable sidebar (#1827)
* wip: First round on sidebar resizing

* feat: Saving setting, animation

* all requirements, refactoring needed

* lint

* refactor useResize

* some mobile improvements

* fix

* refactor
2021-01-20 23:00:14 -08:00
Translate-O-Tron 774c3534d8 fix: New Chinese Simplified translations from Crowdin [ci skip] (#1832) 2021-01-20 22:23:30 -08:00
Malek Hijazi 9759227d73 fix: upgrade command (#1830)
I tested this on the server. Running yarn upgrade will result in yarn self updating. To solve this issue we need to run yarn run upgrade.
2021-01-20 22:19:44 -08:00
Tom Moor f608872c11 chore: Add Chinese and Italian translations 2021-01-20 22:09:36 -08:00
Translate-O-Tron eff9544ef9 New Crowdin updates (#1810)
* fix: New Chinese Simplified translations from Crowdin [ci skip]

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

* fix: New Italian translations from Crowdin [ci skip]
2021-01-20 21:36:03 -08:00
Tom Moor 22fb464b87 lint 2021-01-18 16:11:48 -08:00
Tom Moor 3bace8c9e4 fix: Restore DNS prefetching for static resources (#1820)
* fix: Restore DNS prefetching for static resources

* fix: CDN paths
feat: preload instead of prefetch for key bundles

* csp

* fix: Turns out prefetch-src is still behind a flag in Chrome, not publicly available yet
2021-01-18 15:48:46 -08:00
Tom Moor 27fca28450 fix: Account for rehydrated old users before language
closes #1819
2021-01-17 22:19:54 -08:00
Tom Moor afcce7a0ef fix: Add missing width/height tags to img 2021-01-17 21:49:51 -08:00
Tom Moor f33495dddc fix: Editor mod shortcuts not working on Windows
closes #1745
2021-01-17 18:32:32 -08:00
Tom Moor 51b75fa09d 0.52.0 2021-01-16 14:12:35 -08:00
Tom Moor 522df125aa feat: Add CDN support (#1817)
* chore: CSP

* chore: Optionally use CDN for serving images
2021-01-16 11:12:10 -08:00
Tom Moor 1fd2ec31fd fix: Heading positioning changing between edit/read-only
fix: List items beyond #9 chopped
2021-01-15 08:50:19 -08:00
Tom Moor 1af00a0b3d test 2021-01-14 20:15:46 -08:00
Tom Moor ab40545a01 lint 2021-01-14 20:11:04 -08:00
Tom Moor c8d305aeca fix: Unintended scroll reset when switching between view / edit (#1807)
* fix: Don't remount document when switching between edit/read-only
fix: Button vertical alignment when using as=Link

* fix: Bump RME, fixes issue with image behavior changing between read-only/edit without editor remount

* fix: Heading anchor positioning
2021-01-14 19:50:10 -08:00
Maximilian Zinke 68a65be135 feat: Embed Google Drive (#1804)
* implement google drive extension

* add current logo of google drive

* fix issue when posting gdrive links which are already a preview

* always only show the preview

* Add bottom bar to get to original url for Google Drive embeds

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2021-01-14 19:49:56 -08:00
Tom Moor b4d307b3b4 fix: Confusing breadcrumb collapsing 2021-01-14 19:36:31 -08:00
Tom Moor 03cb6d66e7 fix: Alignment of collection icon in header when collection name is very long 2021-01-14 18:59:43 -08:00
Tom Moor 7b8cbc50d5 fix: Document meta unclickable when first item in a document is a heading 2021-01-14 18:51:58 -08:00
Tom Moor f501da9c0f flow 2021-01-14 18:38:02 -08:00
Translate-O-Tron 74a762a7c7 New Crowdin updates (#1790) 2021-01-14 09:08:38 -08:00
Rubén Moya 93ac9892d5 fix: take into account user lang in Time component (#1793)
This PR takes into account the user selected language to format the time in the Time component.

Co-authored-by: tommoor <tom.moor@gmail.com>
2021-01-14 09:08:14 -08:00
Tom Moor e8b7782f5e fix: Keyboard accessible context menus (#1768)
- Makes menus fully accessible and keyboard driven
- Currently adds 2.8% to initial bundle size due to the inclusion of Reakit and its dependency, popperjs.
- Converts all menus to functional components
- Remove old custom menu system
- Various layout and flow improvements around the menus

closes #1766
2021-01-13 22:00:25 -08:00
Rubén Moya 47369dd968 chore: rename collection creatorId to createdById (#1794) 2021-01-11 23:17:31 -08:00
Tom Moor d258082c5f lint 2021-01-11 18:25:21 -08:00
Tom Moor c0bbae50c4 fix: Search results not updated when changing filters 2021-01-11 00:50:44 -08:00
Tom Moor ac082e4a5f Merge branch 'develop' of github.com:outline/outline into develop 2021-01-11 00:47:48 -08:00
Tom Moor 7504d43452 fix: Add indicator of starred status when viewing a document (#1785)
* fix: Add indicator of starred status when viewing a document
closes #461

* fix: Account for shared document
2021-01-10 23:13:58 -08:00
Tom Moor 5dba68dfd3 fix: Incorrect border color on table of contents in dark mode 2021-01-07 23:50:28 -08:00
Tom Moor 4b85603f30 chore: Text highlight blue -> yellow 2021-01-07 23:25:14 -08:00
Tom Moor 34598b317d fix: Deleting a collection should not deleted archived documents within it automatially (#1776)
closes #1775
2021-01-07 19:46:12 -08:00
Translate-O-Tron cbfa25fa2f New Crowdin updates (#1736)
* fix: New Japanese translations from Crowdin [ci skip]

* fix: New Japanese 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 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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 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 Chinese Simplified translations from Crowdin [ci skip]

* fix: New Chinese Simplified translations from Crowdin [ci skip]
2021-01-07 08:09:44 -08:00
Tom Moor 67a2246e1a fix: Attempting to restore document in deleted collection without a collectionId override results in server error (#1777)
closes #1767
2021-01-07 08:09:19 -08:00
Tom Moor de7bf8c133 fix: Fixes padding on sidebar collection links
closes #1770
2021-01-06 20:35:02 -08:00
Tom Moor 4fda50f4ad feat: Add 'archive' option in delete confirmation modal (#1764)
* feat: Add 'archive' option in delete confirmation modal
chore: Add translation tags to delete confirmation

* i18n

* language
2021-01-03 11:04:09 -08:00
Tom Moor f4c5cc054e chore: Update sorting icons 2021-01-03 09:38:29 -08:00
Tom Moor f799758a6f feat: Allow Google sign-in users to choose account
Alternative to https://github.com/outline/outline/pull/1763
2021-01-03 08:54:47 -08:00
Tom Moor 9df02d6fd4 chore: Improve toasts 2021-01-02 21:47:02 -08:00
Tom Moor bb81aa0065 fix: Improve toast messages to not show multiple of the same 2021-01-02 21:09:43 -08:00
Tom Moor 68bbd9fa34 fix: Hold hover state on DocumentListItem while DocumentMenu is open 2021-01-02 20:02:57 -08:00
Tom Moor 308d4bd797 i18n 2021-01-02 19:19:45 -08:00
Tom Moor 5329474c85 fix: Developer warning batchingForReactDom 2021-01-02 19:13:11 -08:00
Tom Moor d90af48741 fix: Outer error boundary generates more errors as it doesnt have access to store and theme providers 2021-01-02 19:12:51 -08:00
Tom Moor 611e9b97b3 chore: Move collection sort control (#1762)
* feat: Move collection sort menu

* fix: Improve accessibility

* fix: Dedupe outline-icons (temporary until rme is next merged)
2021-01-02 19:11:13 -08:00
Nan Yu eda5adca2c feat: adds hover to expand functionality on sidebar (#1761)
* feat: adds hover to expand functionality on sidebar

* clear hover intent timeout on drag leave
2021-01-02 17:20:13 -08:00
Tom Moor f0b361158e flow 2021-01-02 09:09:06 -08:00
Tom Moor f8ab793053 fix: 'New' badge should never show to document creator, regardless of whether a view has been logged (#1758) 2020-12-31 16:46:33 -08:00
Nan Yu 2cc45187e6 feat: reordering documents in collection (#1722)
* tweaking effect details

* wrap work on this feature

* adds correct color to drop cursor

* simplify logic for early return

* much better comment so Tom doesn't fire me

* feat: Allow changing sort order of collections

* refactor: Move validation to model
feat: Make custom order the default (in prep for dnd)

* feat: Add sort choice to edit collection modal
fix: Improved styling of generic InputSelect

* fix: Vertical space left after removing previous collection description

* chore: Tweak language, menu contents, add auto-disclosure on sub menus

* only show drop-to-reorder cursor when sort is set to manual

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-12-31 12:51:12 -08:00
Tom Moor ba61091c4c fix: Allow soft deletion of teams (#1754)
* fix: Allow soft deletion of teams

* test: regression specs
2020-12-30 09:40:23 -08:00
Tom Moor 8dba32b5e0 fix: Meta key shortcuts not bound correctly in Windows browsers (#1753) 2020-12-30 09:35:33 -08:00
Clifton Cunningham 40bd9aed0a fix: miro - use the incoming domain to ensure access to logged in boards works (#1756) 2020-12-30 09:35:18 -08:00
Tom Moor d4bb04e921 fix: Handle linked documents destroyed when document is published
closes #1739
2020-12-29 10:32:09 -08:00
Nan Yu 8a3a279c0e Merge branch 'develop' of github.com:outline/outline into develop 2020-12-28 21:35:37 -08:00
Nan Yu 37f2cc8d55 closes #1752 2020-12-28 21:35:13 -08:00
Gustavo Maronato 89903b4bbe feat: Compress avatar images before upload (#1751)
* compress avatar images before upload

* move compressImage to dedicated file

* Update ImageUpload.js
2020-12-28 21:08:10 -08:00
Tom Moor 41be18e938 test 2020-12-28 20:43:27 -08:00
Tom Moor caee7afde2 refactor: documents.batchImport -> collections.import 2020-12-28 18:51:12 -08:00
Tom Moor d79933887d fix: Don't trigger email and slack notifications when mass importing
feat: Show success message after import
2020-12-28 18:02:58 -08:00
Tom Moor 2787e56de3 test: Add additional tests and input validation 2020-12-28 15:30:01 -08:00
Tom Moor b932457fd3 fix: Improve single collection export compatability 2020-12-28 10:07:38 -08:00
Tom Moor ea5d2ea9e0 refactor, add preview 2020-12-27 23:00:26 -08:00
Tom Moor 6e9b4e8363 lint 2020-12-27 12:54:58 -08:00
Tom Moor 012e6b320e feat: Allow document metadata to be stored in zip comment 2020-12-27 12:36:06 -08:00
Tom Moor c8cd7fcf4a fix: API response 2020-12-26 23:12:22 -08:00
Tom Moor 7021c2a9e5 Hook up API 2020-12-26 17:53:56 -08:00
Tom Moor 799e639439 Merge branch 'feat/import-export' into feat/mass-import 2020-12-25 18:05:02 -08:00
Tom Moor ba2552f69f fix 2020-12-25 18:04:38 -08:00
Malek Hijazi b6ab816bb3 feat: command to upgrade outline (#1727)
* Add upgrade script to package.json

* Update the docs to include docker and yarn guides
2020-12-25 15:23:55 -08:00
Tom Moor ac1120914a fix: Unable to delete archived and templated documents (#1749)
closes #1746
2020-12-24 13:28:08 -08:00
Tom Moor a51af98d43 refactor 2020-12-24 10:18:53 -08:00
Tom Moor ad7400a4f5 Merge branch 'develop' of github.com:outline/outline into feat/mass-import 2020-12-22 20:43:58 -08:00
Tom Moor ea57cef89c fix: Reduce double reporting of errors 2020-12-21 21:10:25 -08:00
Tom Moor 087ccdd825 stash 2020-12-21 21:03:11 -08:00
Translate-O-Tron 7d44e1aeeb New Crowdin updates (#1725)
* fix: New Japanese translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

* fix: New Russian 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 Japanese translations from Crowdin [ci skip]

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

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

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

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

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

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

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

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

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

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

* fix: New Spanish translations from Crowdin [ci skip]
2020-12-21 19:28:41 -08:00
Tom Moor 25d5ad8a7e chore: Enable automatic generation of email server in non production environments (#1731) 2020-12-21 19:27:14 -08:00
dependabot[bot] e34ba1457e chore(deps): bump node-notifier from 8.0.0 to 8.0.1 (#1734)
Bumps [node-notifier](https://github.com/mikaelbr/node-notifier) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/mikaelbr/node-notifier/releases)
- [Changelog](https://github.com/mikaelbr/node-notifier/blob/v8.0.1/CHANGELOG.md)
- [Commits](https://github.com/mikaelbr/node-notifier/compare/v8.0.0...v8.0.1)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-21 19:26:12 -08:00
Tom Moor e966eb8c9a fix: Error notice not displayed to user when exceeding rate limit on signin attempt 2020-12-20 13:05:16 -08:00
Tom Moor 4684b3a3f3 fix: Server error when invalid JSON passed to API endpoint
Fix is to ensure that the errorHandling middleware is mounted before the body parser so that it can catch and return an error response
2020-12-20 12:08:47 -08:00
Tom Moor 47ce8afcc5 fix: Server Error when requesting invalid locale 2020-12-20 11:53:09 -08:00
Tom Moor decbe4f643 fix: Allow deleting attachments not linked to documents when owned by user
closes #1729
2020-12-20 11:39:09 -08:00
Tom Moor 938f6ba8c5 wip 2020-12-19 23:23:37 -08:00
Tom Moor 7f5a7d7df7 Merge branch 'develop' of github.com:outline/outline into feat/mass-import 2020-12-19 16:01:10 -08:00
Tom Moor 117d278d16 fix: Deprecated Buffer usage, closes #1726 2020-12-19 15:58:21 -08:00
Tom Moor 40ca73e684 feat: Collapsible sidebar (#1721)
* wip

* styling, add keyboard shortcut

* tweak styling
2020-12-17 22:26:04 -08:00
Tom Moor b98e4bb1ff stash 2020-12-17 21:19:31 -08:00
Tom Moor 5012104a10 refactor 2020-12-16 21:39:37 -08:00
Nan Yu 051ecab0fc feat: Moving documents via drag and drop in sidebar (#1717)
* wip: added some basic drag and drop UI for combining items

* refactor: pathToDocument to accept only id

* fix: Multiple drop backends error
fix: Incorrect styling dragging over active collection
fix: Stay in disabled state until save is complete

* Improving display while moving doc

* fix: update by user should be changed when moving a doc

* add move guard to drag

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-12-15 19:07:29 -08:00
Tom Moor 3469b82beb feat: Add Korean as available language choice 2020-12-15 08:11:50 -08:00
Tom Moor f2c3481670 test 2020-12-14 23:04:39 -08:00
Tom Moor bc141dc40c New Crowdin updates (#1718)
* fix: New French translations from Crowdin [ci skip]

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

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

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

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

* fix: New Russian 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 German translations from Crowdin [ci skip]

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

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

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

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

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

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

* fix: New Korean 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 German translations from Crowdin [ci skip]

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

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

* fix: New Russian 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]
2020-12-14 22:28:47 -08:00
Translate-O-Tron 99814f6e2f fix: New Korean translations from Crowdin [ci skip] 2020-12-14 22:19:57 -08:00
Translate-O-Tron 3737f0b42c fix: New Portuguese translations from Crowdin [ci skip] 2020-12-14 22:19:53 -08:00
Translate-O-Tron 9ef27cb436 fix: New German translations from Crowdin [ci skip] 2020-12-14 22:19:50 -08:00
Translate-O-Tron c9fa3f93f2 fix: New Spanish translations from Crowdin [ci skip] 2020-12-14 22:19:48 -08:00
Translate-O-Tron 24ed96c9a5 fix: New French translations from Crowdin [ci skip] 2020-12-14 22:19:46 -08:00
Translate-O-Tron 956cf401bd fix: New Korean translations from Crowdin [ci skip] 2020-12-14 21:17:46 -08:00
Translate-O-Tron 7cb837f478 fix: New Portuguese, Brazilian translations from Crowdin [ci skip] 2020-12-14 21:17:44 -08:00
Translate-O-Tron a3209e9d23 fix: New Chinese Simplified translations from Crowdin [ci skip] 2020-12-14 21:17:43 -08:00
Translate-O-Tron 29582a1bb1 fix: New Russian translations from Crowdin [ci skip] 2020-12-14 21:17:41 -08:00
Translate-O-Tron 4084c91769 fix: New Portuguese translations from Crowdin [ci skip] 2020-12-14 21:17:39 -08:00
Translate-O-Tron 6772f28226 fix: New Japanese translations from Crowdin [ci skip] 2020-12-14 21:17:37 -08:00
Translate-O-Tron c6b110d339 fix: New German translations from Crowdin [ci skip] 2020-12-14 21:17:35 -08:00
Translate-O-Tron 0a43b50c66 fix: New Spanish translations from Crowdin [ci skip] 2020-12-14 21:17:33 -08:00
Translate-O-Tron 4a82cb0658 fix: New French translations from Crowdin [ci skip] 2020-12-14 21:17:31 -08:00
Tom Moor 2f7fca6106 chore: Move formatting out of translation strings 2020-12-14 21:16:02 -08:00
Translate-O-Tron 8f83cfef25 fix: New Korean translations from Crowdin [ci skip] 2020-12-14 20:39:04 -08:00
Tom Moor e2e66954b5 fix: Attachments should not always be deleted with their original document (#1715)
* fix: Attachments should not be deleted when their original document is deleted when referenced elsewhere

* fix: Attachments deleted prematurely when docs are placed in trash

* mock

* restore hook, cascading delete was the issue
2020-12-14 19:55:22 -08:00
Tom Moor 3dbe54ac1e fix: Bump RME, closes #1719 2020-12-14 19:18:46 -08:00
Translate-O-Tron 50577f6f2f fix: New Korean translations from Crowdin [ci skip] 2020-12-14 09:40:18 -08:00
Translate-O-Tron 16d504703d fix: New Korean translations from Crowdin [ci skip] 2020-12-14 08:42:26 -08:00
Translate-O-Tron 173febcaa1 fix: New Korean translations from Crowdin [ci skip] 2020-12-14 07:40:07 -08:00
Translate-O-Tron f92f4cde7a fix: New Korean translations from Crowdin [ci skip] 2020-12-14 06:45:01 -08:00
Translate-O-Tron 23bec75bd0 fix: New Korean translations from Crowdin [ci skip] 2020-12-14 05:49:49 -08:00
Translate-O-Tron 4dd667f68b fix: New Korean translations from Crowdin [ci skip] 2020-12-14 04:47:25 -08:00
Translate-O-Tron 4b3cb77cc7 fix: New Korean translations from Crowdin [ci skip] 2020-12-14 03:48:01 -08:00
Translate-O-Tron 0e83d54f93 fix: New German translations from Crowdin [ci skip] 2020-12-13 23:30:53 -08:00
Translate-O-Tron d867d9fea5 fix: New Spanish translations from Crowdin [ci skip] 2020-12-13 23:30:51 -08:00
Translate-O-Tron 28c8b8acfe fix: New French translations from Crowdin [ci skip] 2020-12-13 23:30:49 -08:00
Translate-O-Tron 51efffe2ce fix: New Korean translations from Crowdin [ci skip] 2020-12-13 22:34:18 -08:00
Tom Moor 4e9ee7249f Update LICENSE 2020-12-13 17:48:15 -08:00
Tom Moor 574fcc4bb3 0.51.0 2020-12-13 17:43:58 -08:00
Tom Moor 5c3000d5cf Bump RME, fixes table after list and image captions in Safari 2020-12-13 17:20:38 -08:00
Translate-O-Tron c0216cbb8d fix: New Portuguese, Brazilian translations from Crowdin [ci skip] 2020-12-12 22:40:33 -08:00
Translate-O-Tron cf12301077 fix: New Chinese Simplified translations from Crowdin [ci skip] 2020-12-12 22:40:31 -08:00
Translate-O-Tron 1eb7da8742 fix: New Russian translations from Crowdin [ci skip] 2020-12-12 22:40:29 -08:00
Translate-O-Tron b3c548382f fix: New Portuguese translations from Crowdin [ci skip] 2020-12-12 22:40:27 -08:00
Translate-O-Tron 7ebac53b43 fix: New Japanese translations from Crowdin [ci skip] 2020-12-12 22:40:25 -08:00
Translate-O-Tron 64428a6894 fix: New German translations from Crowdin [ci skip] 2020-12-12 22:40:23 -08:00
Translate-O-Tron d536af5269 fix: New Spanish translations from Crowdin [ci skip] 2020-12-12 22:40:22 -08:00
Translate-O-Tron 1726a88a60 fix: New French translations from Crowdin [ci skip] 2020-12-12 22:40:20 -08:00
Tom Moor 3fe807a10a fix: Object printed in UI 2020-12-12 22:29:20 -08:00
Tom Moor 72189e041b feat: attachments.delete (#1714)
* feat: Add endpoint for manually deleting attachments

* mock
2020-12-10 21:40:03 -08:00
Translate-O-Tron bc156f4cc8 New Crowdin updates (#1707)
* fix: New German translations from Crowdin [ci skip]

* fix: New German 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 French translations from Crowdin [ci skip]

* fix: New Portuguese, Brazilian translations from Crowdin [ci skip]
2020-12-10 19:03:01 -08:00
dependabot[bot] 26693c60df chore(deps): bump ini from 1.3.5 to 1.3.7 (#1713)
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-10 18:43:50 -08:00
Nan Yu 9e1f31e14c fix: dropzone error on image upload component (#1711) 2020-12-08 19:32:41 -08:00
Nan Yu 63d926e196 slightly nicer color definitions (#1705) 2020-12-07 08:56:07 -08:00
Reid Beels 3f9f1f0bed docs: Add note to .env.sample about Google OAuth URI (#1706) 2020-12-07 08:55:37 -08:00
Tom Moor b2bdc7f1d4 chore: Add user and auth context to server side error reports (#1693) 2020-12-06 17:59:44 -08:00
Translate-O-Tron 2e798c698d chore: New Crowdin updates (#1691) 2020-12-06 17:54:16 -08:00
Nan Yu aa59f5fe09 chore: React-Dropzone version bump (#1699)
* update dropzone to new version

* remove global styles import

* change bg on active item on drag as well

* add back background
2020-12-06 17:50:59 -08:00
Tom Moor ac2060b166 fix: Migrate attachment columns to incease available length (#1704)
closes #1703
2020-12-06 16:51:25 -08:00
Tom Moor 424c29536d chore: Bump RME (SQL language support) 2020-12-04 10:18:30 -08:00
Tom Moor 6c1ecde4e7 fix: Server error when attempting to update team with identical details to previous 2020-12-04 10:18:30 -08:00
Tom Moor aa6fc45097 Add localization status to README 2020-12-04 08:22:43 -08:00
Tom Moor 9478944718 fix: Account for non-recorded views, closes #1700 2020-12-02 20:50:54 -08:00
Tom Moor 9e1c5d1db3 fix: JS error in UserProfile introduced in refactoring to functional component 2020-12-02 20:48:24 -08:00
Nan Yu 474fbf07e6 chore: Flatten left nav in preparation to refactor drag to reorder (#1689)
* flatten hierarchy
* fix drop to import positioning on collections
2020-12-01 21:59:18 -08:00
Tom Moor fe62048890 fix: One source of transaction deadlock when invites > pg pool (#1696)
* fix: One source of transaction deadlock when invites > pg pool

* lint
2020-12-01 19:20:20 -08:00
Tom Moor 1851477290 fix: Disabling public sharing should disable all existing share links
Issue came through customer support
2020-11-30 23:39:23 -08:00
Tom Moor bde6f4b3c4 fix: Don't make request to record view for deleted document 2020-11-30 23:17:39 -08:00
Saumya Pandey 283b479689 chore: Change response of shares.info response for unshared document (#1666)
* Update server/api/share.js to send 204 status for unshared documents.

* Update shares.info endpoint to expect 204 in a few test.

* Update SharesStore and ApiClient to handle 204 status code
2020-11-30 22:49:15 -08:00
Tom Moor 183f06c2d1 fix: Policies not added to store from all fetch requests
closes #1688
2020-11-30 22:38:11 -08:00
Tom Moor 21fff8d172 fix: ui store spread onto DropToImport 2020-11-30 21:46:55 -08:00
Tom Moor 18e56aff65 fix: Editable title in sidebar impossible to see in dark mode 2020-11-30 21:45:48 -08:00
Tom Moor a97523a652 chore: Upgrade pg (performance improvements) 2020-11-30 21:31:13 -08:00
Tom Moor 2316512a19 Update crowdin.yml 2020-11-30 19:09:41 -08:00
Tom Moor 1285efc49a feat: I18n (#1653)
* feat: i18n

* Changing language single source of truth from TEAM to USER

* Changes according to @tommoor comments on PR

* Changed package.json for build:i18n and translation label

* Finished 1st MVP of i18n for outline

* new translation labels & Portuguese from Portugal translation

* Fixes from PR request

* Described language dropdown as an experimental feature

* Set keySeparator to false in order to cowork with html keys

* Added useTranslation to Breadcrumb

* Repositioned <strong> element

* Removed extra space from TemplatesMenu

* Fortified the test suite for i18n

* Fixed trans component problematic

* Check if selected language is available

* Update yarn.lock

* Removed unused Trans

* Removing debug variable from i18n init

* Removed debug variable

* test: update snapshots

* flow: Remove decorator usage to get proper flow typing
It's a shame, but hopefully we'll move to Typescript in the next 6 months and we can forget this whole Flow mistake ever happened

* translate: Drafts

* More translatable strings

* Mo translation strings

* translation: Search

* async translations loading

* cache translations in client

* Revert "cache translations in client"

This reverts commit 08fb61ce36.

* Revert localStorage cache for cache headers

* Update Crowdin configuration file

* Moved translation files to locales folder and fixed english text

* Added CONTRIBUTING File for CrowdIn

* chore: Move translations again to please CrowdIn

* fix: loading paths
chore: Add strings for editor

* fix: Improve validation on documents.import endpoint

* test: mock bull

* fix: Unknown mimetype should fallback to Markdown parsing if markdown extension (#1678)

* closes #1675

* Update CONTRIBUTING

* chore: Add link to translation portal from app UI

* refactor: Centralize language config

* fix: Ensure creation of i18n directory in build

* feat: Add language prompt

* chore: Improve contributing guidelines, add link from README

* chore: Normalize tab header casing

* chore: More string externalization

* fix: Language prompt in dark mode

Co-authored-by: André Glatzl <andreglatzl@gmail.com>
2020-11-29 20:04:58 -08:00
Tom Moor 63c73c9a51 Create auto_assign.yml 2020-11-27 09:51:52 -08:00
Tom Moor 1b7fe0f7da flow 2020-11-27 09:48:10 -08:00
Tom Moor 6eda1cc0d3 fix: Unknown mimetype should fallback to Markdown parsing if markdown extension (#1678)
closes #1675
2020-11-26 21:16:56 -08:00
Tom Moor ac349b40f5 test: mock bull 2020-11-26 21:11:35 -08:00
Tom Moor 8bddc1b338 fix: Improve validation on documents.import endpoint 2020-11-26 20:29:45 -08:00
Tom Moor 56d5f048f9 fix: Group membership count off after suspending users in groups (#1670)
* fix: Clear group memberships when suspending a user
Refactor to command

* test

* test
2020-11-22 11:21:47 -08:00
Tom Moor 273d9c4680 fix: Correctly map CMD+Shift+P to publish in title
fixes #1655
2020-11-21 22:20:59 -08:00
Tom Moor 44ca447185 fix: Scrollbar styling
closes #1665
2020-11-21 16:16:38 -08:00
Tom Moor 6b511e4251 Bump rich-markdown-editor, 2 minor fixes 2020-11-21 15:34:03 -08:00
Saumya Pandey de6ee91d96 fix: Prevent API request for views data for deleted documents (#1663)
* Prevent API request for views data for deleted documents

Added a conditional statement to check if the document.deletedAt is falsy before making a request to views.list.

* Update app/components/Collaborators.js to use isDeleted attribute.

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-11-18 19:09:08 -08:00
Tom Moor 18fac781a9 Update LICENSE 2020-11-14 23:10:16 -08:00
Tom Moor 1ce01fa936 0.50.0 2020-11-14 23:07:41 -08:00
Tom Moor 12a2e1c387 chore: Menu templates (#1644)
* chore: Menu template system

* NewTemplateMenu

* UserMenu

* MenuItemsTemplate -> DropdownMenuItems

* support nested menus

* DocumentMenu

* BreadcrumbMenu

* isInvited
2020-11-14 20:44:31 -08:00
Tom Moor 19ab32f551 chore: Add additional missing events (#1639)
* chore: Add additional missing events
signed in
profile updated
team setting updated

* Minor refactor to DRY existing code

* Add events

* lint

* flow: Add missing ip to event types
2020-11-14 20:44:18 -08:00
Tom Moor 7bdcba46b8 fix: Virtualize move document listbox (#1650)
* fix: Virtualize move document listbox
closes #1645
2020-11-12 22:02:56 -08:00
Tom Moor 32d3053002 fix: Heading anchor position changed _again_ 2020-11-12 22:02:19 -08:00
Tom Moor 85dd54db3d fix: Consistent spacing when first item in document is a header 2020-11-12 21:51:20 -08:00
Tom Moor 5d0dd9b734 chore: Bump RME (various editor fixes) 2020-11-12 21:47:44 -08:00
Tom Moor 735d5cbf26 fix: Ignore safely ignored loop error
closes #1646
2020-11-11 17:05:05 -08:00
Tom Moor a94012a03a chore: Drop and create test database automatically between runs
docs: Update README to specify using make to run tests
2020-11-11 16:58:45 -08:00
Tom Moor 80d74c9334 fix: Clicking the share link from a context menu propagates the click onto the container (#1643)
closes #1642
2020-11-11 09:02:02 -08:00
Tom Moor 26e6db1afd fix: Update document policy to disable sharing for read-only users (#1638)
* fix: Update document policy to disable sharing for read-only users

* test: Update test for new permission logic
2020-11-10 20:35:41 -08:00
Tom Moor 5e7bbdc111 feat: Sync sessions across browser tabs (#1641)
* feat: Sync sessions across browser tabs

If the user signs in or out in one tab, then make sure their session on the same subdomain is kept in sync on other tabs
2020-11-10 19:43:14 -08:00
Tom Moor 71e9860f88 flow: Correctly type Theme 2020-11-09 00:01:50 -08:00
Tom Moor 26f4901547 fix: 'Not found' page should obey theme
closes #1626
2020-11-08 23:52:00 -08:00
Tom Moor 4c56ed40f1 feat: Hide Outline branding on custom domain share links
closes #1629
2020-11-08 23:01:57 -08:00
Tom Moor 4e7a1cd121 feat: add filters to drafts (#1631)
* feat: add filters to drafts

Co-authored-by: Guilherme Diniz <guilhermedassumpcao@gmail.com>
2020-11-08 22:33:52 -08:00
Tom Moor 14e0ed8108 fix: Various React warnings 2020-11-08 20:28:27 -08:00
Tom Moor 0372ff2727 fix: Unneccessary scrollbar 2020-11-08 20:04:46 -08:00
Tom Moor 02e7e75cb9 fix: Remove non-standardized css (console warning) 2020-11-08 20:01:47 -08:00
Tom Moor af73de4128 feat: Show table of contents when useful on publicly shared docs
closes #1625
2020-11-08 19:50:00 -08:00
Tom Moor 0125a5361d fix: Document published notification potentially sent to users without permission to view document 2020-11-05 19:49:05 -08:00
Nonpawit Teerachetmongkol fdaa36c9fd fix: gist not support username contains numbers (#1622) 2020-11-05 09:03:16 -08:00
Tom Moor 1b6a986986 chore: Refactor authentication pass between subdomains (#1619)
* fix: Use get request instead of cookie to transfer token between domains

* Add domain to database
Add redirects to team domain when present

* 30s -> 1m

* fix: Avoid redirect loop if subdomain and domain set

* fix: Create a transfer specific token to prevent replay requests

* refactor: Move isCustomDomain out of shared as it won't work on the client
2020-11-04 19:54:04 -08:00
Tom Moor 3d09c8f655 chore: Refactor backlinks and revisions (#1611)
* Update backlinks service to not rely on revisions

* fix: Add missing index for finding backlinks

* Debounce revision creation (#1616)

* refactor debounce logic to service

* Debounce slack notification

* Revisions created by service

* fix: Revision sidebar latest

* test: Add tests for notifications
2020-11-01 10:26:39 -08:00
Tom Moor 7735aa12d7 GSuite -> Google Workspace 2020-10-27 22:14:51 -07:00
Tom Moor 7ac724909d fix: Cannot duplicate document with title close to max title length
closes #1610
2020-10-27 19:15:35 -07:00
Tom Moor abd3a1ee12 Update LICENSE 2020-10-26 23:26:43 -07:00
Tom Moor 9bfc0cacae 0.49.0 2020-10-26 23:25:50 -07:00
Tom Moor bd80e8384a chore: Remove events log from settings 2020-10-26 19:32:48 -07:00
Tom Moor bfdfa3ee4b feat: Debounce notification emails by 5 minutes to avoid duplicate notifications where possible (#1598) 2020-10-25 15:06:07 -07:00
Tom Moor dba5dd14e7 fix: Put public and private uploads in separate folders to allow for restrictive AWS policies
closes #1581
2020-10-21 21:00:40 -07:00
Tom Moor a9c05adc3c fix: Account for multiple images on the same line of text when converting images for public share
closes #1602
2020-10-21 20:22:23 -07:00
Tom Moor 34bdc88003 fix: Offset heading styles 2020-10-21 09:04:21 -07:00
Tom Moor df7b9f3e88 feat: Add support for "word" files exported from Confluence (#1600)
* Display error message to end user

* fix: Improve conversion of tables

* fix: Characters at ends of lines in tables lost
2020-10-21 08:53:59 -07:00
Tom Moor b78e2f1e05 fix: Match search requests from Slack using Integration for non-Slack teams (#1599)
* Match slack hook requests to integration
2020-10-21 08:53:38 -07:00
Tom Moor 15337b5bdf fix: Improve error handling when redis connection is lost 2020-10-20 07:41:17 -07:00
Tom Moor 4103f53f2a fix: Offset headers when scrolling from TOC to account for fixed header
closes #1578
2020-10-19 23:07:37 -07:00
Tom Moor 758fcc1759 feat: Show unique views rather than total views in document meta. (#1559)
* unique-views

* fix: 'only you' displays briefly when visiting a document previously only viewed by one other
2020-10-19 22:44:28 -07:00
Debajyoti Halder b3549637fe fix: Dark mode inline code styling fixed #1593 (#1597)
background changed to props.theme.codeBackground
2020-10-19 22:14:14 -07:00
Tom Moor 7bee60a337 fix: Clicking link with blank href should not open new tab 2020-10-19 08:00:52 -07:00
Tom Moor 38a005ed8a lint 2020-10-19 07:48:51 -07:00
Tom Moor 71b7ef1186 fix: Websockets cannot connect in Safari 2020-10-19 07:43:03 -07:00
Tom Moor 3af1a80615 fix: Incorrect cursor on headings 2020-10-19 07:40:12 -07:00
Tom Moor 4044818daa fix: Archived documents should not be returned from documents.list
closes #1575
2020-10-13 20:38:28 -07:00
Tom Moor 428171a1ec closes #1587 – remove global queue events when completed 2020-10-13 20:30:37 -07:00
Tom Moor 9c3195ef25 chore(deps): Bump RME
Fixes unable to upload the same image multiple times
2020-10-13 20:13:51 -07:00
Yohann Leon a6dc708fc0 fix: spotify widget wrong size (#1579) 2020-10-09 19:02:09 -07:00
Tom Moor 9c8f125668 chore: No need to build:server on CI 2020-09-30 20:29:54 -07:00
Tom Moor f348db048e chore: Specify babelrc for server specifically (#1585) 2020-09-30 20:02:33 -07:00
Tom Moor 0b8eb326ab chore(deps): Bump RME
closes #1566
2020-09-30 19:40:00 -07:00
Tom Moor 1da1f3d6e8 chore: Update Zapier integration (no longer invite-only)
fix: Remove link to Zapier integration from self-hosted as it doesnt make sense
2020-09-28 21:08:58 -07:00
Tom Moor 7def0dfab1 chore(deps): Upgrade socket.io-redis dependency for fix related to recent downtime
https://github.com/socketio/socket.io-redis/issues/210
2020-09-28 18:51:49 -07:00
Tom Moor 96987d2091 0.48.1 2020-09-27 10:32:15 -07:00
Tom Moor 6bb32c253b fix: Unable to run migrations in latest image. Added option to run non-SSL migration in production 2020-09-27 10:32:08 -07:00
Tom Moor 1d5f735032 Update LICENSE 2020-09-26 17:19:03 -07:00
Tom Moor f3e3651222 0.48.0 2020-09-26 17:18:34 -07:00
Tom Moor b3d9478486 Merge pull request #1563 from outline/release-0.48.0
release: v48.0.0
2020-09-26 17:09:40 -07:00
Tom Moor f26aeca46a chore(migrations): Add missing indexes 2020-09-26 14:01:04 -07:00
Tom Moor f1a95e5e79 feat: Improved search results when finding links in document editor (#1573)
* feat: Improved search results when finding links in document editor

* chore(deps): Bump RME for smoother link search
2020-09-26 11:07:49 -07:00
Tom Moor 6f1f855083 feat: Add tracking of search source in UI 2020-09-24 21:56:37 -07:00
Tom Moor 40d52e9a78 fix: Cannot press down arrow to navigate via keyboard to search results
(due to withRouter converting DocumentPreview to a functional component)
2020-09-24 21:36:31 -07:00
Tom Moor a2f2971fec fix: Reduce liklihood of false search queries
fix: Reduce possibility of dupe search queries
feat: Allow 'Enter' to trigger search before debounce
2020-09-24 21:29:00 -07:00
Tom Moor d89808ce9d fix: Home link on 'Not Found' page 2020-09-24 19:38:19 -07:00
Tom Moor a43cc9c5a9 chore(deps): Upgrade RME for improved doc search results 2020-09-24 19:35:28 -07:00
Tom Moor bb7fcd1b67 feat: Allow embedding /share/ routes in iframes 2020-09-23 19:26:18 -07:00
Tom Moor c1957025ec fix: Dont dupe record search queries when paging results
feat: Record queries via api tokens separately
2020-09-21 23:31:10 -07:00
Renan Filipe 98626ebbaf feat: Record search queries (#1554)
* Record search queries

* feat: add totalCount to the search response

* feat: add comments to explain why we use setTimeout
2020-09-21 23:05:42 -07:00
Tom Moor 0fa8a6ed2e feat: Add ctx.state.authType for tracking (#1567) 2020-09-21 22:02:37 -07:00
Tom Moor fa96891c8e fix(editor): Upgrade RME, improved link pasting 2020-09-21 20:33:58 -07:00
Tom Moor 9aa81dcf82 fix: Error deleting account as only admin not displayed to user 2020-09-21 20:31:06 -07:00
Tom Moor c04d5bdfb0 flow 2020-09-21 19:47:17 -07:00
Tom Moor ea69d09562 fix: Guard usage of localStorage 2020-09-21 19:43:51 -07:00
Tom Moor c8ff5cf221 fix: Styling of 'New' badge in dark mode
fix: less than a min ago -> just now
2020-09-21 19:35:51 -07:00
Tom Moor 5638f7a687 Merge develop 2020-09-21 19:18:34 -07:00
Tom Moor 1293f52552 lint 2020-09-21 19:18:09 -07:00
Tom Moor 86812cfe76 fix(editor): Upgrade RME, fixes cursor navigation around headings in FF 2020-09-21 19:11:54 -07:00
Tom Moor d9b7384853 fix: Improve handling of invalid file type passed to documents.import API endpoint 2020-09-21 00:34:13 -07:00
Tom Moor 292afd774d fix: CMD+Enter in title should leave editing mode 2020-09-21 00:21:35 -07:00
Tom Moor d3d286b1be tweak search highlight 2020-09-21 00:07:32 -07:00
Tom Moor 26b9566b96 fix: Various fixes for unread tracking 2020-09-20 23:37:09 -07:00
Guilherme DIniz d487da8f15 feat: Visually differentiate unread documents (#1507)
* feat: Visually differentiate unread documents

* feat: add document treatment in document preview

* fix requested changes

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-09-20 22:32:28 -07:00
Tom Moor 4ffc04bc5d fix: Allow selection of embeds (#1562)
* feat: Support importing .docx or .html files as new documents (#1551)

* Support importing .docx as new documents

* Add html file support, build types and interface for easily adding file types to importer

* fix: Upload embedded images in docx to storage

* refactor: Bulk of logic to command

* refactor: Do all importing on server, so we're not splitting logic for import into two places

* test: Add documentImporter tests


Co-authored-by: Lance Whatley <whatl3y@gmail.com>

* fix: Accessibility audit

* fix: Quick fix, non editable title
closes #1560

* fix: Embed selection

Co-authored-by: Lance Whatley <whatl3y@gmail.com>
2020-09-20 22:27:11 -07:00
Tom Moor 68148bd4d8 fix: Quick fix, non editable title
closes #1560
2020-09-18 08:36:57 -07:00
Tom Moor 881105992e fix: Accessibility audit 2020-09-16 22:31:14 -07:00
Tom Moor 2c1a111dee feat: Support importing .docx or .html files as new documents (#1551)
* Support importing .docx as new documents

* Add html file support, build types and interface for easily adding file types to importer

* fix: Upload embedded images in docx to storage

* refactor: Bulk of logic to command

* refactor: Do all importing on server, so we're not splitting logic for import into two places

* test: Add documentImporter tests


Co-authored-by: Lance Whatley <whatl3y@gmail.com>
2020-09-16 21:54:33 -07:00
Tom Moor e67d319e2b fix: Update DocumentMetaWithViews to hooks, correctly observe store changes
closes #1555
2020-09-16 21:15:21 -07:00
Tom Moor 85f7e03921 test: No hotreload in test env 2020-09-16 08:22:50 -07:00
Tom Moor e30adbaac2 fix: Flip production/development NODE_ENV logic
closes #1548
2020-09-16 00:13:12 -07:00
Tom Moor ac8f0ebaac feat: Allow Google Embeds from regular (non publish-to-web) links (#1533)
Improve styling to allow getting back to source document
2020-09-15 18:38:42 -07:00
Tom Moor b3b71d2dc7 feat: Editable titles in sidebar (#1544)
* feat/editable-titles

* feat: Double click to edit titles in the sidebar

* Take into account policies

* fix: Title update on another client

* Improved styling
2020-09-15 18:01:40 -07:00
Tom Moor ab3613af48 fix: Path to onboarding markdown files (changed with updated build process) 2020-09-15 12:20:27 -07:00
Tom Moor 3940f1a108 Update README.md 2020-09-14 19:29:55 -07:00
Tom Moor 142e7da6a5 fix: Placeholder style 2020-09-13 20:26:38 -07:00
Tom Moor 021de66f7a fix: Document titles look faded in Safari 2020-09-13 20:18:50 -07:00
Nan Yu 55858d5d7d fix: put guard around sentry init (#1547) 2020-09-13 19:54:08 -07:00
Tom Moor 93d3582ac7 fix: Dead pointer zone over links when hover card is showing 2020-09-13 19:49:25 -07:00
Tom Moor 0b2107c1ee Merge develop 2020-09-13 10:50:13 -07:00
Tom Moor f8a167fd4b Merge branch 'develop' of github.com:outline/outline into develop 2020-09-13 10:47:31 -07:00
Tom Moor 608be3deef refactor: Remove babel/register for instant production server startup (#1481)
* refactor: Remove babel/register for instant production server startup

* fix: Update procfile location

* fix: package.json must be copied, not linked for production build

* fix: Production file paths

* fix: Public assets path

* Remove unused scripts
2020-09-13 10:46:33 -07:00
Tom Moor 56551d1ab3 fix: Error in backlinks service when updating an old document (pre v1) 2020-09-13 01:03:39 -07:00
Tom Moor 450d6b7e42 fix: Focus accessibility (#1536)
* fix: Focus ring appearing on click
fix: Focus ring not appearing on sidebar links
add: focus-visible polyfill

* fix: More visible outlines on keyboard focus
fix: Header block should be a button semantically
2020-09-12 23:27:23 -07:00
Matheus Rocha Vieira fc98cf78e6 chore: Upgrade Sentry to Latest Version (#1541)
* Upgrade Sentry to Latest Version
2020-09-12 23:24:32 -07:00
Nan Yu d9aa53a094 feat: allow searching for urls of internal documents (#1529)
* core search logic

* bump version of rich markdown editor

* let shift and meta modifiers do their thing when clicking on a link in a doc

* version bump editor

* test: Add parseDocumentSlug test

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-09-12 23:23:40 -07:00
Nan Yu ffab4fbf76 remove -1 bottom from navigation links 2020-09-12 11:24:58 -07:00
Tom Moor 2161fba1dd Update LICENSE 2020-09-11 12:28:10 -07:00
Tom Moor cd2cdd025c 0.47.1 2020-09-11 12:26:13 -07:00
Tom Moor d5f5319f80 fix: History sidebar header shrinking when lots of history 2020-09-11 12:10:40 -07:00
Tom Moor c298c73240 fix: Revision skipped after identical previous autosave 2020-09-11 12:06:57 -07:00
Tom Moor 38d1831259 fix: Send events for draft documents down user channel always 2020-09-11 11:19:30 -07:00
Tom Moor 9c9b95741c fix: Unable to edit collection description
closes #1523
2020-09-09 23:23:01 -07:00
Tom Moor cc8db7e991 fix: Save team logo automatically
closes #1521
2020-09-08 21:12:37 -07:00
Tom Moor c5b7d9be13 fix: Flash of sidebar when navigating between documents 2020-09-08 20:48:52 -07:00
Tom Moor be2e46b5d2 References -> Referenced by
Less ambiguous as to the backlink direction
2020-09-08 18:44:19 -07:00
Tom Moor 4b2a766357 fix: Missing toast message when successfully copying code 2020-09-08 07:31:03 -07:00
Tom Moor f264d67862 fix: Two API endpoints where requesting a permenantly deleted document results in server error 2020-09-08 07:29:06 -07:00
Tom Moor b1648ac2aa Update LICENSE 2020-09-07 20:25:16 -07:00
Tom Moor 25423d8c85 0.47.0 2020-09-07 20:24:40 -07:00
Nan Yu e7ab2939d4 fix: Improved handling of delete events from collection and document sockets (#1517)
* handle delete events fron collection and document sockets

* handle collection deletes to documents

* rework semantics to always reload after a delete

Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-09-07 19:05:10 -07:00
Tom Moor ceeac9b982 fix: Deeply nested document titles not updated in collection documentStructure cache
closes #1508
2020-09-07 13:41:17 -07:00
Tom Moor 5de2f969e3 fix: Preload membership 2020-09-07 12:17:04 -07:00
Tom Moor b54901d50c fix: CMD+Eneter in title should still publish 2020-09-07 12:06:03 -07:00
Tom Moor 4de3f69474 fix: Documents in deleted collection should appear in trash (#1362)
* fix: Documents from deleted collection should show in trash

* improve messaging

* test: Add documents.move tests
feat: Add ability to restore trashed documents from deleted collection

* update store

* fix

* ui

* lint

* fix: Improve breadcrumb
2020-09-07 11:51:09 -07:00
Tom Moor c5de2da115 Merge branch 'develop' of github.com:outline/outline into develop 2020-09-07 10:43:36 -07:00
Tom Moor 709c3e78bd fix: Occasional render loop in editor toolbar (#1518)
* fix: CMD+S should save when editor title is focused

* fix: Bump RME, fixes various small editor issues
2020-09-07 10:42:51 -07:00
Tom Moor acb04fdf1a fix: CMD+S should save when editor title is focused 2020-09-06 10:33:39 -07:00
Tom Moor f13696dd2a Update yarn.lock 2020-09-05 19:58:17 -07:00
Tom Moor d6f245d67e Bump RME: Fixes inline styles in table cells with newlines 2020-09-05 19:51:12 -07:00
Tom Moor f2abf38fe4 perf: Remove source once compiled 2020-09-05 12:57:27 -07:00
Tom Moor f0712e22d8 perf: Improving dockerfile 2020-09-05 12:44:40 -07:00
Tom Moor e7e289d9fa end 2020-09-04 23:28:29 -07:00
Tom Moor 713187cfb4 fix 2020-09-04 15:39:36 -07:00
Tom Moor 11d3a5c9b9 fix: Enter in document title should create a newline at the top of editor and focus
closes #1511
2020-09-04 13:23:33 -07:00
Matheus Rocha Vieira cf1e506009 feat: Add ClickUp Embed Service (#1465)
* Add Clickup Embed Service

* Transparency Icon


Co-authored-by: Tom Moor <tom.moor@gmail.com>
2020-09-04 13:21:27 -07:00
Tom Moor 6b6d67beb6 fix: Allow disabling SSL for Postgres connection with standard PGSSLMODE env
closes #1501
2020-09-04 12:51:48 -07:00
Tom Moor a98e8ad8df fix: Breadcrumb overflow color is inaccessible
closes #1505
2020-09-04 12:49:20 -07:00
Tom Moor 9049785d98 fix: e shortcut to edit doesn't work when title is selected
closes #1510
2020-09-04 12:42:41 -07:00
Tom Moor e8648d4611 fix: Error in shares.info endpoint when requesting share record for deleted document 2020-09-03 23:22:41 -07:00
Tom Moor dd7436f78c fix: async error in backlinks service when dealing with a deleted document 2020-09-03 22:44:42 -07:00
Tom Moor b93a397ab3 feat: Bump RME 2020-09-03 22:27:30 -07:00
Tom Moor 206160582e chore: Tweak ordering of unpublish menu item 2020-09-02 20:19:36 -07:00
Tom Moor 4bf5926ee3 Bump RME 2020-08-31 21:57:26 -07:00
Tom Moor 82433e02a0 feat: Add custom error state for chunk loading failed 2020-08-31 21:09:23 -07:00
Tom Moor 637a9b5cf9 refactor: Remove unused event handlers 2020-08-31 20:44:19 -07:00
Tom Moor 95b91c466a fix: Disallow creating nested document within document in trash 2020-08-31 20:32:08 -07:00
Tom Moor 4edf90a184 fix: Development warning, missing key on event list items 2020-08-31 20:29:55 -07:00
Tom Moor 31522b0d6f fix: Local shares state not cleared when document is deleted 2020-08-31 20:28:41 -07:00
Tom Moor 759d4a5ac2 fix: Handle error revoking share link on frontend 2020-08-31 20:24:05 -07:00
Tom Moor dd0d51dd9d test 2020-08-31 20:23:51 -07:00
Tom Moor 8550116c6b fix: shares.list should not return shares for deleted documents
fix: shares.info should not return info for revoked shares
closes #1492
2020-08-31 20:15:10 -07:00
Tom Moor 3c7dc93982 Merge branch 'develop' of github.com:outline/outline into develop 2020-08-31 20:06:44 -07:00
Guilherme DIniz 0aa338cccc feat: Allow unpublishing documents (#1467)
* Allow unpublishing documents

* add block unpublish files that has children

* add api tests to new route
2020-08-31 20:03:05 -07:00
Tom Moor 8f41895e66 Merge develop 2020-08-31 19:40:41 -07:00
Tom Moor de8ac4acf5 fix: Configure mobx-react-lite observer batching
Removes development warning
2020-08-31 18:42:12 -07:00
Tom Moor de59147418 chore: Upgrade Sentry to 5.22.3
closes #1498
2020-08-31 18:36:30 -07:00
Tom Moor cf522cc85f fix: Regression with TOC not showing when navigating directly to document (#1500)
fix: Editing document too wide when TOC visible in read only
2020-08-31 18:31:13 -07:00
Tom Moor 8c7200fa87 chore: yarn deduplicate 2020-08-30 19:44:30 -07:00
Tom Moor f2310be173 Updated Yarn lockfile 2020-08-29 12:11:12 -07:00
Tom Moor 29f4dc9331 Bump RME
Fixes #1107 - It's now possible to use line breaks in table cells with Shift+Enter
Fixes #1253 - Selected content can now be dragged to reorder
2020-08-29 12:00:55 -07:00
Tom Moor 03b6dd62a8 fix: Missing click action to change permissions on a collection
fix: Modals no longer stacking correctly since upgrading react-portal
2020-08-25 21:00:50 -07:00
Tom Moor 7f0c608dbb Merge branch 'guilherme-diniz-feature/document-history-header' into develop 2020-08-25 20:04:02 -07:00
Tom Moor c52fbb944e Styling tidy up 2020-08-25 20:03:52 -07:00
Tom Moor e22e952606 Merge branch 'feature/document-history-header' of git://github.com/guilherme-diniz/outline into guilherme-diniz-feature/document-history-header 2020-08-25 19:44:56 -07:00
Guilherme Diniz 197cdff6c3 fix layout issues 2020-08-25 17:22:13 -03:00
Tom Moor 85d09b2351 fix: Deleting a document should correctly show who deleted (#1488) 2020-08-25 08:51:12 -07:00
Tom Moor 69611638b9 fix: Redirect to parent document when deleting a child document if possible (#1489) 2020-08-25 08:45:04 -07:00
Tom Moor e117d5f103 fix: Unable to view all possible locations when moving document (#1490)
* fix: Remove limit of displayed results on Move dialog

* fix: Filter templates from results

* Show final document location on hover/active, reduces visual noise
2020-08-25 08:44:46 -07:00
Tom Moor 03db975217 Merge branch 'feature/document-history-header' of git://github.com/guilherme-diniz/outline into guilherme-diniz-feature/document-history-header 2020-08-24 23:46:16 -07:00
Tom Moor 76279902f9 chore: Introduce AWS_S3_FORCE_PATH_STYLE option to maintain compatability with Minio et al (#1443)
- Make AWS_S3_UPLOAD_BUCKET_NAME optional
2020-08-24 23:27:10 -07:00
Tom Moor a304e91ffc Merge branch 'develop' into perf/issue-1464 2020-08-24 20:58:56 -07:00
Tom Moor 9b5573c5e2 0.46.1 2020-08-24 20:22:08 -07:00
Tom Moor ec61efa12b Remove unused scripts 2020-08-23 21:10:32 -07:00
Tom Moor b01778a39f fix: Public assets path 2020-08-23 20:44:44 -07:00
Tom Moor 5aa092853b fix: Production file paths 2020-08-23 20:35:59 -07:00
Tom Moor 1fa3db4bdc fix: package.json must be copied, not linked for production build 2020-08-23 20:29:17 -07:00
Tom Moor 6a9f74e6cc fix: Update procfile location 2020-08-23 19:21:43 -07:00
Tom Moor e8719340d1 refactor: Remove babel/register for instant production server startup 2020-08-23 19:10:16 -07:00
Tom Moor 70838918c3 fix: Collections not collapsing 2020-08-23 12:51:35 -07:00
Tom Moor ec38f5d79c refactor: Remove old react lifecycle methods (#1480)
* refactor: Remove deprecated APIs

* bump mobx-react for hooks support

* inject -> useStores
https://mobx-react.js.org/recipes-migration\#hooks-to-the-rescue

* chore: React rules of hooks lint
2020-08-23 11:51:56 -07:00
Jonathan Killian 179176c312 fix: Update package.json build script to use yarn instead of npm. (#1476)
* fix: Update package.json build script to yarn.

Update package.json build script to use yarn instead of npm to maintain consistency with the rest of scripts. I was running into an issue with the Dockerfile when using nvm with yarn and this fixed the issue.
2020-08-22 19:56:52 -07:00
Tom Moor c446a91f7d fix: Restore Postgres SSL support on Heroku
https://github.com/brianc/node-postgres/issues/2009
2020-08-22 08:27:42 -07:00
Guilherme Diniz 05f48f054b feat: Add Header to Document History Sidebar 2020-08-21 20:58:57 -03:00
Tom Moor ec55299c8b fix: Improve websocket reliability (#1470)
* check connection on page visibility change

* fix: SocketPresence account for socket changing
2020-08-20 20:37:54 -07:00
Tom Moor 26c574ab58 chore: Upgrade pg and sequelize to support node 14+ (#1462)
* Upgrade pg and sequelize to support node 14+

When Node 14 came out the app was incompatible, we should always have a maximum version defined here until the server code has been tested to prove compatibility

Co-authored-by: Lance Whatley <whatl3y@gmail.com>
2020-08-20 20:19:44 -07:00
Tom Moor 6dd6768f07 feat: Allow moving templates between collections (#1454)
- Allow template move in document policy
- fix: Ensure that document is not added to collection structure in documentMover command
- fix: Moving a template should now show nested documents as options
- fix: Hitting 'm' should not allow moving a draft
- fix: Styling of seperators on move screen
2020-08-20 19:46:29 -07:00
Tom Moor 0555fd2caa pref: JS bundling improvements (#1461)
* perf: Split only initial vendors
2020-08-17 22:09:12 -07:00
Tom Moor d885252fb0 fix: Mobile style fixes and improvements (#1459)
* fixes #1457 – check for matchMedia function before using it

* fixes: Depth issues
closes #1458

* fixes: Long breadcrumbs cause horizontal overflow

* fix: Improve tabs and overflow on mobile
2020-08-17 00:08:22 -07:00
Tom Moor df9b0bcf91 fix: Websocket reconnect when navigating from settings -> home 2020-08-14 17:47:12 -07:00
Tom Moor 31910f1628 Remove auto reconnect, increase reconnectionDelayMax 2020-08-14 17:25:55 -07:00
Tom Moor 14cb3a36c1 perf: Reduce initial bundle size / async bundle loading (#1456)
* feat: Move to React.lazy

* perf: Remove duplicate babel/runtime

* fix: Run yarn-deduplicate

* Further attempts to remove rich-markdown-editor from initial chunk

* perf: Lazy loading of authenticated routes

* perf: Move color picker to async loading
fix: Display placeholder when loading rich editor

* fix: Cache bust on auto reload
2020-08-14 17:23:58 -07:00
Tom Moor d3350c20b6 perf: Attempt websocket connection before polling 2020-08-14 13:37:11 -07:00
Tom Moor 174acfac32 fix: Unnecessary shares.info request when loading public share (#1453)
closes #1450
2020-08-13 16:48:03 -07:00
1823 changed files with 123470 additions and 79298 deletions
+24 -4
View File
@@ -1,15 +1,15 @@
{
"presets": [
"@babel/preset-react",
"@babel/preset-flow",
"@babel/preset-typescript",
[
"@babel/preset-env",
{
"corejs": {
"version": "2",
"version": "3",
"proposals": true
},
"useBuiltIns": "usage",
"useBuiltIns": "usage"
}
]
],
@@ -25,5 +25,25 @@
"@babel/plugin-transform-destructuring",
"@babel/plugin-transform-regenerator",
"transform-class-properties"
]
],
"env": {
"production": {
"plugins": [
[
"styled-components",
{
"displayName": false
}
]
],
"ignore": [
"**/*.test.ts"
]
},
"development": {
"ignore": [
"**/*.test.ts"
]
}
}
}
+156 -25
View File
@@ -1,43 +1,174 @@
version: 2
version: 2.1
defaults: &defaults
working_directory: ~/outline
docker:
- image: cimg/node:14.19
- image: cimg/redis:5.0
- image: cimg/postgres:14.2
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: circle_test
resource_class: large
environment:
NODE_ENV: test
SECRET_KEY: F0E5AD933D7F6FD8F4DBB3E038C501C052DC0593C686D21ACB30AE205D2F634B
DATABASE_URL_TEST: postgres://postgres:password@localhost:5432/circle_test
DATABASE_URL: postgres://postgres:password@localhost:5432/circle_test
URL: http://localhost:3000
SMTP_FROM_EMAIL: hello@example.com
AWS_S3_UPLOAD_BUCKET_URL: https://s3.amazonaws.com
AWS_S3_UPLOAD_BUCKET_NAME: outline-circle
executors:
docker-publisher:
environment:
IMAGE_NAME: outlinewiki/outline
BASE_IMAGE_NAME: outlinewiki/outline-base
docker:
- image: circleci/buildpack-deps:stretch
jobs:
build:
working_directory: ~/outline
docker:
- image: circleci/node:12
- image: circleci/redis:latest
- image: circleci/postgres:9.6.5-alpine-ram
environment:
NODE_ENV: test
SECRET_KEY: F0E5AD933D7F6FD8F4DBB3E038C501C052DC0593C686D21ACB30AE205D2F634B
DATABASE_URL_TEST: postgres://root@localhost:5432/circle_test
DATABASE_URL: postgres://root@localhost:5432/circle_test
URL: http://localhost:3000
SMTP_FROM_EMAIL: hello@example.com
AWS_S3_UPLOAD_BUCKET_URL: https://s3.amazonaws.com
AWS_S3_UPLOAD_BUCKET_NAME: outline-circle
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: install-deps
command: yarn install --pure-lockfile
command: yarn install --frozen-lockfile
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}
paths:
- ./node_modules
lint:
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: lint
command: yarn lint
types:
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: typescript
command: yarn tsc
test-app:
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: test
command: yarn test:app
test-shared:
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: test
command: yarn test:shared
test-server:
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: migrate
command: ./node_modules/.bin/sequelize db:migrate --url $DATABASE_URL_TEST
- run:
name: lint
command: yarn lint
- run:
name: flow
command: yarn flow check --max-workers 4
- run:
name: test
command: yarn test
command: yarn test:server --forceExit
bundle-size:
<<: *defaults
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: build
command: yarn build
name: build-webpack
command: yarn build:webpack
build-image:
executor: docker-publisher
steps:
- checkout
- setup_remote_docker:
version: 20.10.6
- run:
name: Install Docker buildx
command: |
mkdir -p ~/.docker/cli-plugins
url="https://github.com/docker/buildx/releases/download/v0.8.0/buildx-v0.8.0.linux-amd64"
curl -sSL -o ~/.docker/cli-plugins/docker-buildx $url
chmod a+x ~/.docker/cli-plugins/docker-buildx
- run:
name: Enable Docker buildx
command: export DOCKER_CLI_EXPERIMENTAL=enabled
- run:
name: Initialize Docker buildx
command: |
docker buildx install
docker context create docker-multiarch
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker buildx create --name docker-multiarch --platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x docker-multiarch
docker buildx inspect --builder docker-multiarch --bootstrap
docker buildx use docker-multiarch
- run:
name: Build base image
command: docker build -f Dockerfile.base -t $BASE_IMAGE_NAME:latest --load .
- run:
name: Login to Docker Hub
command: echo "$DOCKERHUB_PASS" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
- run:
name: Publish base Docker Image to Docker Hub
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 .
workflows:
version: 2
all:
jobs:
- build
- lint:
requires:
- build
- test-server:
requires:
- build
- test-shared:
requires:
- build
- test-app:
requires:
- build
- types:
requires:
- build
- bundle-size:
requires:
- test-app
- test-shared
- test-server
build-docker:
jobs:
- build-image:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
+17
View File
@@ -0,0 +1,17 @@
__mocks__
.git
.vscode
.github
.circleci
.DS_Store
.env*
.eslint*
.log
Makefile
Procfile
app.json
crowdin.yml
build
docker-compose.yml
fakes3
node_modules
+153 -35
View File
@@ -1,61 +1,179 @@
# Copy this file to .env, remove this comment and change the keys. For development
# with docker this should mostly work out of the box other than setting the Slack
# keys (for auth) and the SECRET_KEY.
#
# Please use `openssl rand -hex 32` to create SECRET_KEY
# –––––––––––––––– REQUIRED ––––––––––––––––
NODE_ENV=production
# Generate a hex-encoded 32-byte random key. You should use `openssl rand -hex 32`
# in your terminal to generate a random value.
SECRET_KEY=generate_a_new_key
# Generate a unique random key. The format is not important but you could still use
# `openssl rand -hex 32` in your terminal to produce this.
UTILS_SECRET=generate_a_new_key
DATABASE_URL=postgres://user:pass@localhost:5532/outline
DATABASE_URL_TEST=postgres://user:pass@localhost:5532/outline-test
REDIS_URL=redis://localhost:6479
# For production point these at your databases, in development the default
# should work out of the box.
DATABASE_URL=postgres://user:pass@localhost:5432/outline
DATABASE_URL_TEST=postgres://user:pass@localhost:5432/outline-test
DATABASE_CONNECTION_POOL_MIN=
DATABASE_CONNECTION_POOL_MAX=
# Uncomment this to disable SSL for connecting to Postgres
# PGSSLMODE=disable
# For redis you can either specify an ioredis compatible url like this
REDIS_URL=redis://localhost:6379
# or alternatively, if you would like to provide addtional connection options,
# use a base64 encoded JSON connection option object. Refer to the ioredis documentation
# for a list of available options.
# Example: Use Redis Sentinel for high availability
# {"sentinels":[{"host":"sentinel-0","port":26379},{"host":"sentinel-1","port":26379}],"name":"mymaster"}
# REDIS_URL=ioredis://eyJzZW50aW5lbHMiOlt7Imhvc3QiOiJzZW50aW5lbC0wIiwicG9ydCI6MjYzNzl9LHsiaG9zdCI6InNlbnRpbmVsLTEiLCJwb3J0IjoyNjM3OX1dLCJuYW1lIjoibXltYXN0ZXIifQ==
# 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
PORT=3000
# enforce (auto redirect to) https in production, (optional) default is true.
# set to false if your SSL is terminated at a loadbalancer, for example
FORCE_HTTPS=true
# See [documentation](docs/SERVICES.md) on running a separate collaboration
# server, for normal operation this does not need to be set.
COLLABORATION_URL=
ENABLE_UPDATES=true
DEBUG=cache,presenters,events
# To support uploading of images for avatars and document attachments an
# s3-compatible storage must be provided. AWS S3 is recommended for redundency
# however if you want to keep all file storage local an alternative such as
# minio (https://github.com/minio/minio) can be used.
# Third party signin credentials (at least one is required)
SLACK_KEY=get_a_key_from_slack
SLACK_SECRET=get_the_secret_of_above_key
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Comma separated list of domains to be allowed (optional)
# If not set, all Google apps domains are allowed by default
GOOGLE_ALLOWED_DOMAINS=
# Third party credentials (optional)
SLACK_VERIFICATION_TOKEN=PLxk6OlXXXXXVj3YYYY
SLACK_APP_ID=A0XXXXXXX
SLACK_MESSAGE_ACTIONS=true
GOOGLE_ANALYTICS_ID=
SENTRY_DSN=
# AWS credentials (optional in development)
# A more detailed guide on setting up S3 is available here:
# => https://wiki.generaloutline.com/share/125de1cc-9ff6-424b-8415-0d58c809a40f
#
AWS_ACCESS_KEY_ID=get_a_key_from_aws
AWS_SECRET_ACCESS_KEY=get_the_secret_of_above_key
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
# uploaded s3 objects permission level, default is private
# set to "public-read" to allow public access
AWS_S3_FORCE_PATH_STYLE=true
AWS_S3_ACL=private
# Emails configuration (optional)
# –––––––––––––– AUTHENTICATION ––––––––––––––
# Third party signin credentials, at least ONE OF EITHER Google, Slack,
# or Microsoft is required for a working installation or you'll have no sign-in
# options.
# To configure Slack auth, you'll need to create an Application at
# => https://api.slack.com/apps
#
# When configuring the Client ID, add a redirect URL under "OAuth & Permissions":
# https://<URL>/auth/slack.callback
SLACK_CLIENT_ID=get_a_key_from_slack
SLACK_CLIENT_SECRET=get_the_secret_of_above_key
# To configure Google auth, you'll need to create an OAuth Client ID at
# => https://console.cloud.google.com/apis/credentials
#
# When configuring the Client ID, add an Authorized redirect URI:
# https://<URL>/auth/google.callback
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# To configure Microsoft/Azure auth, you'll need to create an OAuth Client. See
# the guide for details on setting up your Azure App:
# => https://wiki.generaloutline.com/share/dfa77e56-d4d2-4b51-8ff8-84ea6608faa4
AZURE_CLIENT_ID=
AZURE_CLIENT_SECRET=
AZURE_RESOURCE_APP_ID=
# To configure generic OIDC auth, you'll need some kind of identity provider.
# See documentation for whichever IdP you use to acquire the following info:
# Redirect URI is https://<URL>/auth/oidc.callback
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_AUTH_URI=
OIDC_TOKEN_URI=
OIDC_USERINFO_URI=
# Specify which claims to derive user information from
# Supports any valid JSON path with the JWT payload
OIDC_USERNAME_CLAIM=preferred_username
# Display name for OIDC authentication
OIDC_DISPLAY_NAME=OpenID
# Space separated auth scopes.
OIDC_SCOPES=openid profile email
# –––––––––––––––– OPTIONAL ––––––––––––––––
# Base64 encoded private key and certificate for HTTPS termination. This is only
# required if you do not use an external reverse proxy. See documentation:
# https://wiki.generaloutline.com/share/1c922644-40d8-41fe-98f9-df2b67239d45
SSL_KEY=
SSL_CERT=
# If using a Cloudfront/Cloudflare distribution or similar it can be set below.
# This will cause paths to javascript, stylesheets, and images to be updated to
# the hostname defined in CDN_URL. In your CDN configuration the origin server
# should be set to the same as URL.
CDN_URL=
# Auto-redirect to https in production. The default is true but you may set to
# false if you can be sure that SSL is terminated at an external loadbalancer.
FORCE_HTTPS=true
# Have the installation check for updates by sending anonymized statistics to
# the maintainers
ENABLE_UPDATES=true
# How many processes should be spawned. As a reasonable rule divide your servers
# available memory by 512 for a rough estimate
WEB_CONCURRENCY=1
# Override the maxium size of document imports, could be required if you have
# especially large Word documents with embedded imagery
MAXIMUM_IMPORT_SIZE=5120000
# You can remove this line if your reverse proxy already logs incoming http
# requests and this ends up being duplicative
DEBUG=http
# 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
#
SLACK_VERIFICATION_TOKEN=your_token
SLACK_APP_ID=A0XXXXXXX
SLACK_MESSAGE_ACTIONS=true
# Optionally enable google analytics to track pageviews in the knowledge base
GOOGLE_ANALYTICS_ID=
# Optionally enable Sentry (sentry.io) to track errors and performance
SENTRY_DSN=
# To support sending outgoing transactional emails such as "document updated" or
# "you've been invited" you'll need to provide authentication for an SMTP server
SMTP_HOST=
SMTP_PORT=
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_FROM_EMAIL=
SMTP_REPLY_EMAIL=
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
# Optionally enable rate limiter at application web server
RATE_LIMITER_ENABLED=true
# Configure default throttling parameters for rate limiter
RATE_LIMITER_REQUESTS=1000
RATE_LIMITER_DURATION_WINDOW=60
+56 -41
View File
@@ -1,19 +1,47 @@
{
"parser": "babel-eslint",
"parser": "@typescript-eslint/parser",
"parserOptions": {
"sourceType": "module",
"extraFileExtensions": [".json"],
"ecmaFeatures": {
"jsx": true
}
},
"extends": [
"react-app",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:flowtype/recommended"
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"plugin:prettier/recommended"
],
"plugins": [
"prettier",
"flowtype"
"es",
"@typescript-eslint",
"eslint-plugin-import",
"eslint-plugin-node",
"eslint-plugin-react",
"import"
],
"rules": {
"eqeqeq": 2,
"no-unused-vars": 2,
"curly": 2,
"object-shorthand": "error",
"no-mixed-operators": "off",
"no-useless-escape": "off",
"es/no-regexp-lookbehind-assertions": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"args": "after-used",
"ignoreRestSiblings": true
}
],
"padding-line-between-statements": ["error", { "blankLine": "always", "prev": "*", "next": "export" }],
"lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }],
"import/no-named-as-default": "off",
"import/no-named-as-default-member": "off",
"import/newline-after-import": 2,
"import/order": [
"error",
{
@@ -22,53 +50,48 @@
},
"pathGroups": [
{
"pattern": "shared/**",
"pattern": "@shared/**",
"group": "external",
"position": "after"
},
{
"pattern": "stores",
"pattern": "@server/**",
"group": "external",
"position": "after"
},
{
"pattern": "stores/**",
"pattern": "~/stores",
"group": "external",
"position": "after"
},
{
"pattern": "models/**",
"pattern": "~/stores/**",
"group": "external",
"position": "after"
},
{
"pattern": "scenes/**",
"pattern": "~/models/**",
"group": "external",
"position": "after"
},
{
"pattern": "components/**",
"pattern": "~/scenes/**",
"group": "external",
"position": "after"
},
{
"pattern": "~/components/**",
"group": "external",
"position": "after"
},
{
"pattern": "~/**",
"group": "external",
"position": "after"
}
]
}
],
"flowtype/require-valid-file-annotation": [
2,
"always",
{
"annotationStyle": "line"
}
],
"flowtype/space-after-type-colon": [
2,
"always"
],
"flowtype/space-before-type-colon": [
2,
"never"
],
"prettier/prettier": [
"error",
{
@@ -83,19 +106,11 @@
"pragma": "React",
"version": "detect"
},
"import/resolver": {
"node": {
"paths": [
"app",
"."
]
}
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"]
},
"flowtype": {
"onlyFilesWithFlowAnnotation": false
"import/resolver": {
"typescript": {}
}
},
"env": {
"jest": true
}
}
-37
View File
@@ -1,37 +0,0 @@
[include]
.*/app/.*
.*/server/.*
.*/shared/.*
[ignore]
.*/node_modules/tiny-cookie/flow/.*
.*/node_modules/styled-components/.*
.*/node_modules/polished/.*
.*/node_modules/mobx/.*.flow
.*/node_modules/react-side-effect/.*
.*/node_modules/fbjs/.*
.*/node_modules/config-chain/.*
.*/server/scripts/.*
*.test.js
[libs]
[options]
emoji=true
module.system.node.resolve_dirname=node_modules
module.system.node.resolve_dirname=app
module.name_mapper='^\(.*\)\.md$' -> 'empty/object'
module.name_mapper='^shared\/\(.*\)$' -> '<PROJECT_ROOT>/shared/\1'
module.file_ext=.js
module.file_ext=.md
module.file_ext=.json
esproposal.decorators=ignore
esproposal.class_static_fields=enable
esproposal.class_instance_fields=enable
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [outline]
+10
View File
@@ -0,0 +1,10 @@
# Set to true to add reviewers to pull requests
addReviewers: true
# A list of reviewers to be added to pull requests (GitHub user name)
reviewers:
- tommoor
# A list of keywords to be skipped the process that add reviewers if pull requests include it
skipKeywords:
- wip
+11
View File
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
-21
View File
@@ -1,21 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- security
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
Hey! The issue has been automatically marked as stale because it has not had
recent activity. It will be closed soon if no further activity occurs. Please
reply here if you wish for the issue to be kept open.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
@@ -0,0 +1,56 @@
# Image Actions will run in the following scenarios:
# - on Pull Requests containing images (not including forks)
# - on pushing of images to `main` (for forks)
# - on demand (https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/)
# - at 11 PM every Sunday in anything gets missed with any of the above scenarios
# For Pull Requests, the images are added to the PR.
# For other scenarios, a new PR will be opened if any images are compressed.
name: Compress images
on:
pull_request:
paths:
- "**.jpg"
- "**.jpeg"
- "**.png"
- "**.webp"
push:
branches:
- main
paths:
- "**.jpg"
- "**.jpeg"
- "**.png"
- "**.webp"
workflow_dispatch:
schedule:
- cron: "00 20 * * 0"
jobs:
build:
name: calibreapp/image-actions
runs-on: ubuntu-latest
# Only run on main repo on and PRs that match the main repo.
if: |
github.repository == 'outline/outline' &&
(github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository)
steps:
- name: Checkout Branch
uses: actions/checkout@v2
- name: Compress Images
id: calibre
uses: calibreapp/image-actions@main
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
# For non-Pull Requests, run in compressOnly mode and we'll PR after.
compressOnly: ${{ github.event_name != 'pull_request' }}
- name: Create Pull Request
# If it's not a Pull Request then commit any changes as a new PR.
if: |
github.event_name != 'pull_request' &&
steps.calibre.outputs.markdown != ''
uses: peter-evans/create-pull-request@v3
with:
title: "chore: Auto Compress Images"
branch-suffix: timestamp
commit-message: "chore: Compressed inefficient images automatically"
body: ${{ steps.calibre.outputs.markdown }}
+70
View File
@@ -0,0 +1,70 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '28 15 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
+29
View File
@@ -0,0 +1,29 @@
name: "Close Stale PRs"
on:
workflow_dispatch:
schedule:
- cron: "30 1 * * *"
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v5
with:
stale-pr-message: "This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 5 days"
stale-issue-message: "This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 5 days"
close-pr-message: "Automatically closed due to inactivity"
close-issue-message: "Automatically closed due to inactivity"
days-before-issue-stale: 120
days-before-pr-stale: 60
days-before-close: 5
operations-per-run: 60
stale-issue-label: stale
stale-pr-label: stale
exempt-issue-labels: "security,pinned"
- name: Print outputs
run: echo ${{ join(steps.stale.outputs.*, ',') }}
+6 -1
View File
@@ -1,9 +1,14 @@
dist
build
node_modules/*
server/scripts
.env
.log
.vscode/*
npm-debug.log
stats.json
.DS_Store
fakes3/*
.idea
*.pem
*.key
*.cert
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
+88
View File
@@ -0,0 +1,88 @@
{
"projects": [
{
"displayName": "server",
"verbose": false,
"roots": [
"<rootDir>/server"
],
"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"
},
{
"displayName": "app",
"verbose": false,
"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"
],
"testEnvironment": "jsdom",
"testEnvironmentOptions": {
"url": "http://localhost"
}
},
{
"displayName": "shared-node",
"verbose": false,
"roots": [
"<rootDir>/shared"
],
"moduleNameMapper": {
"^@server/(.*)$": "<rootDir>/server/$1",
"^@shared/(.*)$": "<rootDir>/shared/$1"
},
"setupFiles": [
"<rootDir>/__mocks__/console.js"
],
"setupFilesAfterEnv": [
"<rootDir>/shared/test/setup.ts"
],
"testEnvironment": "node"
},
{
"displayName": "shared-jsdom",
"verbose": false,
"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"
],
"testEnvironment": "jsdom",
"testEnvironmentOptions": {
"url": "http://localhost"
}
}
]
}
+4 -3
View File
@@ -1,6 +1,7 @@
{
"javascript.validate.enable": false,
"typescript.validate.enable": false,
"javascript.validate.enable": true,
"javascript.format.enable": true,
"typescript.validate.enable": true,
"typescript.format.enable": true,
"editor.formatOnSave": true,
"typescript.format.enable": false
}
+22 -11
View File
@@ -1,17 +1,28 @@
FROM node:12-alpine
ENV PATH /opt/outline/node_modules/.bin:/opt/node_modules/.bin:$PATH
ENV NODE_PATH /opt/outline/node_modules:/opt/node_modules
ENV APP_PATH /opt/outline
RUN mkdir -p $APP_PATH
ARG APP_PATH=/opt/outline
FROM outlinewiki/outline-base as base
ARG APP_PATH
WORKDIR $APP_PATH
COPY . $APP_PATH
RUN yarn install --pure-lockfile
RUN yarn build
RUN cp -r /opt/outline/node_modules /opt/node_modules
# ---
FROM node:16.14.2-alpine3.15 AS runner
CMD yarn start
ARG APP_PATH
WORKDIR $APP_PATH
ENV NODE_ENV production
COPY --from=base $APP_PATH/build ./build
COPY --from=base $APP_PATH/server ./server
COPY --from=base $APP_PATH/public ./public
COPY --from=base $APP_PATH/.sequelizerc ./.sequelizerc
COPY --from=base $APP_PATH/node_modules ./node_modules
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
USER nodejs
EXPOSE 3000
CMD ["yarn", "start"]
+18
View File
@@ -0,0 +1,18 @@
ARG APP_PATH=/opt/outline
FROM node:16.14.2-alpine3.15 AS deps
ARG APP_PATH
WORKDIR $APP_PATH
COPY ./package.json ./yarn.lock ./
RUN yarn install --no-optional --frozen-lockfile --network-timeout 1000000 && \
yarn cache clean
COPY . .
ARG CDN_URL
RUN yarn build
RUN rm -rf node_modules
RUN yarn install --production=true --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.46.0
Licensed Work: Outline 0.64.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: 2023-08-12
Change Date: 2026-05-23
Change License: Apache License, Version 2.0
+7 -1
View File
@@ -2,17 +2,23 @@ up:
docker-compose up -d redis postgres s3
yarn install --pure-lockfile
yarn sequelize db:migrate
yarn dev
yarn dev:watch
build:
docker-compose build --pull outline
test:
docker-compose up -d redis postgres s3
yarn sequelize db:drop --env=test
yarn sequelize db:create --env=test
yarn sequelize db:migrate --env=test
yarn test
watch:
docker-compose up -d redis postgres s3
yarn sequelize db:drop --env=test
yarn sequelize db:create --env=test
yarn sequelize db:migrate --env=test
yarn test:watch
destroy:
+2 -1
View File
@@ -1 +1,2 @@
web: node index.js
web: yarn start --services=web,websockets,collaboration
worker: yarn start --services=worker
+49 -115
View File
@@ -1,136 +1,57 @@
<p align="center">
<img src="https://user-images.githubusercontent.com/31465/34380645-bd67f474-eb0b-11e7-8d03-0151c1730654.png" height="29" />
</p>
<p align="center">
<i>An open, extensible, wiki for your team built using React and Node.js.<br/>Try out Outline using our hosted version at <a href="https://www.getoutline.com">www.getoutline.com</a>.</i>
<i>A fast, collaborative, knowledge base for your team built using React and Node.js.<br/>Try out Outline using our hosted version at <a href="https://www.getoutline.com">www.getoutline.com</a>.</i>
<br/>
<img src="https://user-images.githubusercontent.com/380914/78513257-153ae080-775f-11ea-9b49-1e1939451a3e.png" alt="Outline" width="800" />
<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://github.com/prettier/prettier"><img src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat"></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"></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).
If you'd like to run your own copy of Outline or contribute to development then this is the place for you.
## Installation
# Installation
Outline requires the following dependencies:
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.
- Node.js >= 12
- Postgres >=9.5
- Redis >= 4
- AWS S3 storage bucket for media and other attachments
- Slack or Google developer application for authentication
If you have questions or improvements for the docs please create a thread in [GitHub discussions](https://github.com/outline/outline/discussions).
# Development
### 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.
In development you can quickly get an environment running using Docker by following these steps:
## Contributing
1. Install these dependencies if you don't already have them
1. [Docker for Desktop](https://www.docker.com)
1. [Node.js](https://nodejs.org/) (v12 LTS preferred)
1. [Yarn](https://yarnpkg.com)
1. Clone this repo
1. Register a Slack app at https://api.slack.com/apps
1. Copy the file `.env.sample` to `.env`
1. Fill out the following fields:
1. `SECRET_KEY` (follow instructions in the comments at the top of `.env`)
1. `SLACK_KEY` (this is called "Client ID" in Slack admin)
1. `SLACK_SECRET` (this is called "Client Secret" in Slack admin)
1. Configure your Slack app's Oauth & Permissions settings
1. Add `http://localhost:3000/auth/slack.callback` as an Oauth redirect URL
1. Ensure that the bot token scope contains at least `users:read`
1. Run `make up`. This will download dependencies, build and launch a development version of Outline
Outline is built and maintained by a small team we'd love your help to fix bugs and add features!
Before submitting a pull request _please_ discuss with the core team by creating or commenting in an issue on [GitHub](https://www.github.com/outline/outline/issues) we'd also love to hear from you in the [discussions](https://www.github.com/outline/outline/discussions). This way we can ensure that an approach is agreed on before code is written. This will result in a much higher liklihood of your code being accepted.
### Production
If youre looking for ways to get started, here's a list of ways to help us improve Outline:
For a self-hosted production installation there is more flexibility, but these are the suggested steps:
- [Translation](docs/TRANSLATION.md) into other languages
- Issues with [`good first issue`](https://github.com/outline/outline/labels/good%20first%20issue) label
- Performance improvements, both on server and frontend
- Developer happiness and documentation
- Bugs and other issues listed on GitHub
1. Clone this repo and install dependencies with `yarn` or `npm install`
## Architecture
> Requires [Node.js](https://nodejs.org/) and [yarn](https://yarnpkg.com) installed
If you're interested in contributing or learning more about the Outline codebase
please refer to the [architecture document](docs/ARCHITECTURE.md) first for a high level overview of how the application is put together.
1. Build the web app with `yarn build:webpack` or `npm run build:webpack`
1. Using the `.env.sample` as a reference, set the required variables in your production environment. The following are required as a minimum:
1. `SECRET_KEY` (follow instructions in the comments at the top of `.env`)
1. `SLACK_KEY` (this is called "Client ID" in Slack admin)
1. `SLACK_SECRET` (this is called "Client Secret" in Slack admin)
1. `DATABASE_URL` (run your own local copy of Postgres, or use a cloud service)
1. `REDIS_URL` (run your own local copy of Redis, or use a cloud service)
1. `URL` (the public facing URL of your installation)
1. `AWS_` (all of the keys beginning with AWS)
1. Migrate database schema with `yarn sequelize:migrate` or `npm run sequelize:migrate `
1. Start the service with any daemon tools you prefer. Take PM2 for example, `NODE_ENV=production pm2 start index.js --name outline `
1. Visit http://you_server_ip:3000 and you should be able to see Outline page
## Debugging
> Port number can be changed in the `.env` file
In development Outline outputs simple logging to the console, prefixed by categories. In production it outputs JSON logs, these can be easily parsed by your preferred log ingestion pipeline.
1. (Optional) You can add an `nginx` reverse proxy to serve your instance of Outline for a clean URL without the port number, support SSL, etc.
## Development
### Server
Outline uses [debug](https://www.npmjs.com/package/debug). To enable debugging output, the following categories are available:
```
DEBUG=sql,cache,presenters,events,logistics,emails,mailer
```
## Migrations
Sequelize is used to create and run migrations, for example:
```
yarn sequelize migration:generate --name my-migration
yarn sequelize db:migrate
```
Or to run migrations on test database:
```
yarn sequelize db:migrate --env test
```
## Structure
Outline is composed of separate backend and frontend application which are both driven by the same Node process. As both are written in Javascript, they share some code but are mostly separate. We utilize the latest language features, including `async`/`await`, and [Flow](https://flow.org/) typing. Prettier and ESLint are enforced by CI.
### Frontend
Outline's frontend is a React application compiled with [Webpack](https://webpack.js.org/). It uses [Mobx](https://mobx.js.org/) for state management and [Styled Components](https://www.styled-components.com/) for component styles. Unless global, state logic and styles are always co-located with React components together with their subcomponents to make the component tree easier to manage.
The editor itself is built on [Prosemirror](https://github.com/prosemirror) and hosted in a separate repository to encourage reuse: [rich-markdown-editor](https://github.com/outline/rich-markdown-editor)
- `app/` - Frontend React application
- `app/scenes` - Full page views
- `app/components` - Reusable React components
- `app/stores` - Global state stores
- `app/models` - State models
- `app/types` - Flow types for non-models
### Backend
Backend is driven by [Koa](http://koajs.com/) (API, web server), [Sequelize](http://docs.sequelizejs.com/) (database) and React for public pages and emails.
- `server/api` - API endpoints
- `server/commands` - Domain logic, currently being refactored from /models
- `server/emails` - React rendered email templates
- `server/models` - Database models
- `server/policies` - Authorization logic
- `server/presenters` - API responses for database models
- `server/test` - Test helps and support
- `server/utils` - Utility methods
- `shared` - Code shared between frontend and backend applications
HTTP logging is disabled by default, but can be enabled by setting the `DEBUG=http` environment variable.
## Tests
@@ -140,28 +61,41 @@ To add new tests, write your tests with [Jest](https://facebook.github.io/jest/)
```shell
# To run all tests
yarn test
make test
# To run backend tests in watch mode
make watch
```
Once the test database is created with `make test` you may individually run
frontend and backend tests directly.
```shell
# To run backend tests
yarn test:server
# To run a specific backend test
yarn test:server myTestFile
# To run frontend tests
yarn test:app
```
## Contributing
## Migrations
Outline is built and maintained by a small team we'd love your help to fix bugs and add features!
Sequelize is used to create and run migrations, for example:
However, before working on a pull request please let the core team know by creating or commenting in an issue on [GitHub](https://www.github.com/outline/outline/issues), and we'd also love to hear from you in the [Discussions](https://www.github.com/outline/outline/discussions). This way we can ensure that an approach is agreed on before code is written and will hopefully help to get your contributions integrated faster!
```shell
yarn sequelize migration:generate --name my-migration
yarn sequelize db:migrate
```
If youre looking for ways to get started, here's a list of ways to help us improve Outline:
Or to run migrations on test database:
* Issues with [`good first issue`](https://github.com/outline/outline/labels/good%20first%20issue) label
* Performance improvements, both on server and frontend
* Developer happiness and documentation
* Bugs and other issues listed on GitHub
```shell
yarn sequelize db:migrate --env test
```
## License
Outline is [BSL 1.1 licensed](https://github.com/outline/outline/blob/master/LICENSE).
Outline is [BSL 1.1 licensed](LICENSE).
-1
View File
@@ -1,2 +1 @@
// Mock for node-uuid
global.console.warn = () => {};
+2 -1
View File
@@ -1 +1,2 @@
window.matchMedia = data => data;
window.matchMedia = (data) => data;
window.env = {};
+73 -7
View File
@@ -30,8 +30,12 @@
"postdeploy": "yarn sequelize db:migrate"
},
"env": {
"NODE_ENV": {
"value": "production",
"required": true
},
"SECRET_KEY": {
"description": "A secret key",
"description": "A 32-character secret key, generate with openssl rand -hex 32",
"generator": "secret",
"required": true
},
@@ -40,7 +44,7 @@
"required": true
},
"URL": {
"description": "https://{your app name}.herokuapp.com",
"description": "https://{your app name}.herokuapp.com, or the domain you are binding to",
"required": true
},
"GOOGLE_CLIENT_ID": {
@@ -51,15 +55,58 @@
"description": "",
"required": false
},
"GOOGLE_ALLOWED_DOMAINS": {
"description": "Comma separated list of domains to be allowed (optional). If not set, all Google apps domains are allowed by default",
"AZURE_CLIENT_ID": {
"description": "To configure Microsoft/Azure auth, you'll need to create an OAuth Client. See the guide for details on setting up your Azure App: https://wiki.generaloutline.com/share/dfa77e56-d4d2-4b51-8ff8-84ea6608faa4",
"required": false
},
"SLACK_KEY": {
"AZURE_CLIENT_SECRET": {
"description": "",
"required": false
},
"AZURE_RESOURCE_APP_ID": {
"description": "",
"required": false
},
"OIDC_CLIENT_ID": {
"description": "To configure generic OIDC auth, you'll need some kind of identity provider. See documentation for whichever IdP you use to acquire the following info; Redirect URI is https://<URL>/auth/oidc.callback",
"required": false
},
"OIDC_CLIENT_SECRET": {
"description": "",
"required": false
},
"OIDC_AUTH_URI": {
"description": "",
"required": false
},
"OIDC_TOKEN_URI": {
"description": "",
"required": false
},
"OIDC_USERINFO_URI": {
"description": "",
"required": false
},
"OIDC_USERNAME_CLAIM": {
"description": "Specify which claims to derive user information from. Supports any valid JSON path with the JWT payload",
"value": "preferred_username",
"required": false
},
"OIDC_DISPLAY_NAME": {
"description": "Display name for OIDC authentication",
"value": "OpenID",
"required": false
},
"OIDC_SCOPES": {
"description": "Space separated auth scopes.",
"value": "openid profile email",
"required": false
},
"SLACK_CLIENT_ID": {
"description": "See https://api.slack.com/apps to create a new Slack app. You must configure at least one of Slack or Google to control login.",
"required": false
},
"SLACK_SECRET": {
"SLACK_CLIENT_SECRET": {
"description": "Your Slack client secret - d2dc414f9953226bad0a356cXXXXYYYY",
"required": false
},
@@ -92,6 +139,11 @@
"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",
"required": false
},
"AWS_REGION": {
"value": "us-east-1",
"description": "Region in which the above S3 bucket exists",
@@ -126,6 +178,15 @@
"description": "wikireply@example.com (optional)",
"required": false
},
"SMTP_SECURE": {
"value": "true",
"description": "Use a secure SMTP connection (optional)",
"required": false
},
"SMTP_TLS_CIPHERS": {
"description": "Override SMTP cipher configuration (optional)",
"required": false
},
"GOOGLE_ANALYTICS_ID": {
"description": "UA-xxxx (optional)",
"required": false
@@ -137,6 +198,11 @@
"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.",
"required": false
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"extends": [
"../.eslintrc",
"plugin:react-hooks/recommended",
],
"plugins": [
"eslint-plugin-react-hooks",
],
"env": {
"jest": true,
"browser": true
}
}
+137
View File
@@ -0,0 +1,137 @@
import {
CollectionIcon,
EditIcon,
PlusIcon,
StarredIcon,
UnstarredIcon,
} from "outline-icons";
import * as React from "react";
import stores from "~/stores";
import Collection from "~/models/Collection";
import CollectionEdit from "~/scenes/CollectionEdit";
import CollectionNew from "~/scenes/CollectionNew";
import DynamicCollectionIcon from "~/components/CollectionIcon";
import { createAction } from "~/actions";
import { CollectionSection } from "~/actions/sections";
import history from "~/utils/history";
const ColorCollectionIcon = ({ collection }: { collection: Collection }) => {
return <DynamicCollectionIcon collection={collection} />;
};
export const openCollection = createAction({
name: ({ t }) => t("Open collection"),
section: CollectionSection,
shortcut: ["o", "c"],
icon: <CollectionIcon />,
children: ({ stores }) => {
const collections = stores.collections.orderedData;
return collections.map((collection) => ({
// Note: using url which includes the slug rather than id here to bust
// cache if the collection is renamed
id: collection.url,
name: collection.name,
icon: <ColorCollectionIcon collection={collection} />,
section: CollectionSection,
perform: () => history.push(collection.url),
}));
},
});
export const createCollection = createAction({
name: ({ t }) => t("New collection"),
section: CollectionSection,
icon: <PlusIcon />,
keywords: "create",
visible: ({ stores }) =>
stores.policies.abilities(stores.auth.team?.id || "").createCollection,
perform: ({ t, event }) => {
event?.preventDefault();
event?.stopPropagation();
stores.dialogs.openModal({
title: t("Create a collection"),
content: <CollectionNew onSubmit={stores.dialogs.closeAllModals} />,
});
},
});
export const editCollection = createAction({
name: ({ t }) => t("Edit collection"),
section: CollectionSection,
icon: <EditIcon />,
visible: ({ stores, activeCollectionId }) =>
!!activeCollectionId &&
stores.policies.abilities(activeCollectionId).update,
perform: ({ t, activeCollectionId }) => {
if (!activeCollectionId) {
return;
}
stores.dialogs.openModal({
title: t("Edit collection"),
content: (
<CollectionEdit
onSubmit={stores.dialogs.closeAllModals}
collectionId={activeCollectionId}
/>
),
});
},
});
export const starCollection = createAction({
name: ({ t }) => t("Star"),
section: CollectionSection,
icon: <StarredIcon />,
keywords: "favorite bookmark",
visible: ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return false;
}
const collection = stores.collections.get(activeCollectionId);
return (
!collection?.isStarred &&
stores.policies.abilities(activeCollectionId).star
);
},
perform: ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return;
}
const collection = stores.collections.get(activeCollectionId);
collection?.star();
},
});
export const unstarCollection = createAction({
name: ({ t }) => t("Unstar"),
section: CollectionSection,
icon: <UnstarredIcon />,
keywords: "unfavorite unbookmark",
visible: ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return false;
}
const collection = stores.collections.get(activeCollectionId);
return (
!!collection?.isStarred &&
stores.policies.abilities(activeCollectionId).unstar
);
},
perform: ({ activeCollectionId, stores }) => {
if (!activeCollectionId) {
return;
}
const collection = stores.collections.get(activeCollectionId);
collection?.unstar();
},
});
export const rootCollectionActions = [
openCollection,
createCollection,
starCollection,
unstarCollection,
];
+50
View File
@@ -0,0 +1,50 @@
import { ToolsIcon, TrashIcon, UserIcon } from "outline-icons";
import * as React from "react";
import stores from "~/stores";
import { createAction } from "~/actions";
import { DeveloperSection } from "~/actions/sections";
import env from "~/env";
import { client } from "~/utils/ApiClient";
import { deleteAllDatabases } from "~/utils/developer";
export const clearIndexedDB = createAction({
name: ({ t }) => t("Delete IndexedDB cache"),
icon: <TrashIcon />,
keywords: "cache clear database",
section: DeveloperSection,
perform: async ({ t }) => {
await deleteAllDatabases();
stores.toasts.showToast(t("IndexedDB cache deleted"));
},
});
export const createTestUsers = createAction({
name: "Create test users",
icon: <UserIcon />,
section: DeveloperSection,
visible: () => env.ENVIRONMENT === "development",
perform: async () => {
const count = 10;
try {
await client.post("/developer.create_test_users", { count });
stores.toasts.showToast(`${count} test users created`);
} catch (err) {
stores.toasts.showToast(err.message, { type: "error" });
}
},
});
export const developer = createAction({
name: ({ t }) => t("Developer"),
keywords: "debug",
icon: <ToolsIcon />,
iconInContextMenu: false,
section: DeveloperSection,
visible: ({ event }) =>
env.ENVIRONMENT === "development" ||
(event instanceof KeyboardEvent && event.altKey),
children: [clearIndexedDB, createTestUsers],
});
export const rootDeveloperActions = [developer];
+573
View File
@@ -0,0 +1,573 @@
import invariant from "invariant";
import {
DownloadIcon,
DuplicateIcon,
StarredIcon,
PrintIcon,
UnstarredIcon,
DocumentIcon,
NewDocumentIcon,
ShapesIcon,
ImportIcon,
PinIcon,
SearchIcon,
UnsubscribeIcon,
SubscribeIcon,
MoveIcon,
TrashIcon,
CrossIcon,
ArchiveIcon,
} from "outline-icons";
import * as React from "react";
import { getEventFiles } from "@shared/utils/files";
import DocumentDelete from "~/scenes/DocumentDelete";
import DocumentMove from "~/scenes/DocumentMove";
import DocumentPermanentDelete from "~/scenes/DocumentPermanentDelete";
import DocumentTemplatizeDialog from "~/components/DocumentTemplatizeDialog";
import { createAction } from "~/actions";
import { DocumentSection } from "~/actions/sections";
import history from "~/utils/history";
import { homePath, newDocumentPath, searchPath } from "~/utils/routeHelpers";
export const openDocument = createAction({
name: ({ t }) => t("Open document"),
section: DocumentSection,
shortcut: ["o", "d"],
keywords: "go to",
icon: <DocumentIcon />,
children: ({ stores }) => {
const paths = stores.collections.pathsToDocuments;
return paths
.filter((path) => path.type === "document")
.map((path) => ({
// Note: using url which includes the slug rather than id here to bust
// cache if the document is renamed
id: path.url,
name: path.title,
icon: () =>
stores.documents.get(path.id)?.isStarred ? <StarredIcon /> : null,
section: DocumentSection,
perform: () => history.push(path.url),
}));
},
});
export const createDocument = createAction({
name: ({ t }) => t("New document"),
section: DocumentSection,
icon: <NewDocumentIcon />,
keywords: "create",
visible: ({ activeCollectionId, stores }) =>
!!activeCollectionId &&
stores.policies.abilities(activeCollectionId).update,
perform: ({ activeCollectionId, inStarredSection }) =>
activeCollectionId &&
history.push(newDocumentPath(activeCollectionId), {
starred: inStarredSection,
}),
});
export const starDocument = createAction({
name: ({ t }) => t("Star"),
section: DocumentSection,
icon: <StarredIcon />,
keywords: "favorite bookmark",
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!document?.isStarred && stores.policies.abilities(activeDocumentId).star
);
},
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.star();
},
});
export const unstarDocument = createAction({
name: ({ t }) => t("Unstar"),
section: DocumentSection,
icon: <UnstarredIcon />,
keywords: "unfavorite unbookmark",
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!!document?.isStarred &&
stores.policies.abilities(activeDocumentId).unstar
);
},
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.unstar();
},
});
export const subscribeDocument = createAction({
name: ({ t }) => t("Subscribe"),
section: DocumentSection,
icon: <SubscribeIcon />,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!document?.isSubscribed &&
stores.policies.abilities(activeDocumentId).subscribe
);
},
perform: ({ activeDocumentId, stores, t }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.subscribe();
stores.toasts.showToast(t("Subscribed to document notifications"), {
type: "success",
});
},
});
export const unsubscribeDocument = createAction({
name: ({ t }) => t("Unsubscribe"),
section: DocumentSection,
icon: <UnsubscribeIcon />,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!!document?.isSubscribed &&
stores.policies.abilities(activeDocumentId).unsubscribe
);
},
perform: ({ activeDocumentId, stores, currentUserId, t }) => {
if (!activeDocumentId || !currentUserId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.unsubscribe(currentUserId);
stores.toasts.showToast(t("Unsubscribed from document notifications"), {
type: "success",
});
},
});
export const downloadDocumentAsHTML = createAction({
name: ({ t }) => t("HTML"),
section: DocumentSection,
keywords: "html export",
icon: <DownloadIcon />,
iconInContextMenu: false,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).download,
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.download("text/html");
},
});
export const downloadDocumentAsMarkdown = createAction({
name: ({ t }) => t("Markdown"),
section: DocumentSection,
keywords: "md markdown export",
icon: <DownloadIcon />,
iconInContextMenu: false,
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).download,
perform: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
document?.download("text/markdown");
},
});
export const downloadDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Download") : t("Download document"),
section: DocumentSection,
icon: <DownloadIcon />,
keywords: "export",
children: [downloadDocumentAsHTML, downloadDocumentAsMarkdown],
});
export const duplicateDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Duplicate") : t("Duplicate document"),
section: DocumentSection,
icon: <DuplicateIcon />,
keywords: "copy",
visible: ({ activeDocumentId, stores }) =>
!!activeDocumentId && stores.policies.abilities(activeDocumentId).update,
perform: async ({ activeDocumentId, t, stores }) => {
if (!activeDocumentId) {
return;
}
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",
});
},
});
/**
* Pin a document to a collection. Pinned documents will be displayed at the top
* of the collection for all collection members to see.
*/
export const pinDocumentToCollection = createAction({
name: ({ t }) => t("Pin to collection"),
section: DocumentSection,
icon: <PinIcon />,
iconInContextMenu: false,
visible: ({ activeCollectionId, activeDocumentId, stores }) => {
if (!activeDocumentId || !activeCollectionId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!!stores.policies.abilities(activeDocumentId).pin && !document?.pinned
);
},
perform: async ({ activeDocumentId, activeCollectionId, t, stores }) => {
if (!activeDocumentId || !activeCollectionId) {
return;
}
const document = stores.documents.get(activeDocumentId);
await document?.pin(document.collectionId);
const collection = stores.collections.get(activeCollectionId);
if (!collection || !location.pathname.startsWith(collection?.url)) {
stores.toasts.showToast(t("Pinned to collection"));
}
},
});
/**
* Pin a document to team home. Pinned documents will be displayed at the top
* of the home screen for all team members to see.
*/
export const pinDocumentToHome = createAction({
name: ({ t }) => t("Pin to home"),
section: DocumentSection,
icon: <PinIcon />,
iconInContextMenu: false,
visible: ({ activeDocumentId, currentTeamId, stores }) => {
if (!currentTeamId || !activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return (
!!stores.policies.abilities(activeDocumentId).pinToHome &&
!document?.pinnedToHome
);
},
perform: async ({ activeDocumentId, location, t, stores }) => {
if (!activeDocumentId) {
return;
}
const document = stores.documents.get(activeDocumentId);
await document?.pin();
if (location.pathname !== homePath()) {
stores.toasts.showToast(t("Pinned to team home"));
}
},
});
export const pinDocument = createAction({
name: ({ t }) => t("Pin"),
section: DocumentSection,
icon: <PinIcon />,
children: [pinDocumentToCollection, pinDocumentToHome],
});
export const printDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Print") : t("Print document"),
section: DocumentSection,
icon: <PrintIcon />,
visible: ({ activeDocumentId }) => !!activeDocumentId,
perform: async () => {
window.print();
},
});
export const importDocument = createAction({
name: ({ t }) => t("Import document"),
section: DocumentSection,
icon: <ImportIcon />,
keywords: "upload",
visible: ({ activeCollectionId, activeDocumentId, stores }) => {
if (activeDocumentId) {
return !!stores.policies.abilities(activeDocumentId).createChildDocument;
}
if (activeCollectionId) {
return !!stores.policies.abilities(activeCollectionId).update;
}
return false;
},
perform: ({ activeCollectionId, activeDocumentId, stores }) => {
const { documents, toasts } = stores;
const input = document.createElement("input");
input.type = "file";
input.accept = documents.importFileTypes.join(", ");
input.onchange = async (ev) => {
const files = getEventFiles(ev);
try {
const file = files[0];
const document = await documents.import(
file,
activeDocumentId,
activeCollectionId,
{
publish: true,
}
);
history.push(document.url);
} catch (err) {
toasts.showToast(err.message, {
type: "error",
});
throw err;
}
};
input.click();
},
});
export const createTemplate = createAction({
name: ({ t }) => t("Templatize"),
section: DocumentSection,
icon: <ShapesIcon />,
keywords: "new create template",
visible: ({ activeCollectionId, activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
const document = stores.documents.get(activeDocumentId);
return !!(
!!activeCollectionId &&
stores.policies.abilities(activeCollectionId).update &&
!document?.isTemplate &&
!document?.isDeleted
);
},
perform: ({ activeDocumentId, stores, t, event }) => {
if (!activeDocumentId) {
return;
}
event?.preventDefault();
event?.stopPropagation();
stores.dialogs.openModal({
title: t("Create template"),
isCentered: true,
content: <DocumentTemplatizeDialog documentId={activeDocumentId} />,
});
},
});
export const searchDocumentsForQuery = (searchQuery: string) =>
createAction({
id: "search",
section: DocumentSection,
name: ({ t }) =>
t(`Search documents for "{{searchQuery}}"`, { searchQuery }),
icon: <SearchIcon />,
perform: () => history.push(searchPath(searchQuery)),
visible: ({ location }) => location.pathname !== searchPath(),
});
export const moveDocument = createAction({
name: ({ t }) => t("Move"),
section: DocumentSection,
icon: <MoveIcon />,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
return !!stores.policies.abilities(activeDocumentId).move;
},
perform: ({ activeDocumentId, stores, t }) => {
if (activeDocumentId) {
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
stores.dialogs.openModal({
title: t("Move {{ documentName }}", {
documentName: document.noun,
}),
content: (
<DocumentMove
document={document}
onRequestClose={stores.dialogs.closeAllModals}
/>
),
});
}
},
});
export const archiveDocument = createAction({
name: ({ t }) => t("Archive"),
section: DocumentSection,
icon: <ArchiveIcon />,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
return !!stores.policies.abilities(activeDocumentId).archive;
},
perform: async ({ activeDocumentId, stores, t }) => {
if (activeDocumentId) {
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
await document.archive();
stores.toasts.showToast(t("Document archived"), {
type: "success",
});
}
},
});
export const deleteDocument = createAction({
name: ({ t }) => t("Delete"),
section: DocumentSection,
icon: <TrashIcon />,
dangerous: true,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
return !!stores.policies.abilities(activeDocumentId).delete;
},
perform: ({ activeDocumentId, stores, t }) => {
if (activeDocumentId) {
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
stores.dialogs.openModal({
title: t("Delete {{ documentName }}", {
documentName: document.noun,
}),
isCentered: true,
content: (
<DocumentDelete
document={document}
onSubmit={stores.dialogs.closeAllModals}
/>
),
});
}
},
});
export const permanentlyDeleteDocument = createAction({
name: ({ t }) => t("Permanently delete"),
section: DocumentSection,
icon: <CrossIcon />,
dangerous: true,
visible: ({ activeDocumentId, stores }) => {
if (!activeDocumentId) {
return false;
}
return !!stores.policies.abilities(activeDocumentId).permanentDelete;
},
perform: ({ activeDocumentId, stores, t }) => {
if (activeDocumentId) {
const document = stores.documents.get(activeDocumentId);
if (!document) {
return;
}
stores.dialogs.openModal({
title: t("Permanently delete {{ documentName }}", {
documentName: document.noun,
}),
isCentered: true,
content: (
<DocumentPermanentDelete
document={document}
onSubmit={stores.dialogs.closeAllModals}
/>
),
});
}
},
});
export const rootDocumentActions = [
openDocument,
archiveDocument,
createDocument,
createTemplate,
deleteDocument,
importDocument,
downloadDocument,
starDocument,
unstarDocument,
subscribeDocument,
unsubscribeDocument,
duplicateDocument,
moveDocument,
permanentlyDeleteDocument,
printDocument,
pinDocumentToCollection,
pinDocumentToHome,
];
+170
View File
@@ -0,0 +1,170 @@
import {
HomeIcon,
SearchIcon,
ArchiveIcon,
TrashIcon,
EditIcon,
OpenIcon,
SettingsIcon,
ShapesIcon,
KeyboardIcon,
EmailIcon,
LogoutIcon,
ProfileIcon,
} from "outline-icons";
import * as React from "react";
import {
developersUrl,
changelogUrl,
feedbackUrl,
githubIssuesUrl,
} from "@shared/utils/urlHelpers";
import stores from "~/stores";
import SearchQuery from "~/models/SearchQuery";
import KeyboardShortcuts from "~/scenes/KeyboardShortcuts";
import { createAction } from "~/actions";
import { NavigationSection, RecentSearchesSection } from "~/actions/sections";
import history from "~/utils/history";
import {
organizationSettingsPath,
profileSettingsPath,
homePath,
searchPath,
draftsPath,
templatesPath,
archivePath,
trashPath,
} from "~/utils/routeHelpers";
export const navigateToHome = createAction({
name: ({ t }) => t("Home"),
section: NavigationSection,
shortcut: ["d"],
icon: <HomeIcon />,
perform: () => history.push(homePath()),
visible: ({ location }) => location.pathname !== homePath(),
});
export const navigateToRecentSearchQuery = (searchQuery: SearchQuery) =>
createAction({
section: RecentSearchesSection,
name: searchQuery.query,
icon: <SearchIcon />,
perform: () => history.push(searchPath(searchQuery.query)),
});
export const navigateToDrafts = createAction({
name: ({ t }) => t("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"),
section: NavigationSection,
shortcut: ["g", "a"],
icon: <ArchiveIcon />,
perform: () => history.push(archivePath()),
visible: ({ location }) => location.pathname !== archivePath(),
});
export const navigateToTrash = createAction({
name: ({ t }) => t("Trash"),
section: NavigationSection,
icon: <TrashIcon />,
perform: () => history.push(trashPath()),
visible: ({ location }) => location.pathname !== trashPath(),
});
export const navigateToSettings = createAction({
name: ({ t }) => t("Settings"),
section: NavigationSection,
shortcut: ["g", "s"],
icon: <SettingsIcon />,
visible: ({ stores }) =>
stores.policies.abilities(stores.auth.team?.id || "").update,
perform: () => history.push(organizationSettingsPath()),
});
export const navigateToProfileSettings = createAction({
name: ({ t }) => t("Profile"),
section: NavigationSection,
iconInContextMenu: false,
icon: <ProfileIcon />,
perform: () => history.push(profileSettingsPath()),
});
export const openAPIDocumentation = createAction({
name: ({ t }) => t("API documentation"),
section: NavigationSection,
iconInContextMenu: false,
icon: <OpenIcon />,
perform: () => window.open(developersUrl()),
});
export const openFeedbackUrl = createAction({
name: ({ t }) => t("Send us feedback"),
section: NavigationSection,
iconInContextMenu: false,
icon: <EmailIcon />,
perform: () => window.open(feedbackUrl()),
});
export const openBugReportUrl = createAction({
name: ({ t }) => t("Report a bug"),
section: NavigationSection,
perform: () => window.open(githubIssuesUrl()),
});
export const openChangelog = createAction({
name: ({ t }) => t("Changelog"),
section: NavigationSection,
iconInContextMenu: false,
icon: <OpenIcon />,
perform: () => window.open(changelogUrl()),
});
export const openKeyboardShortcuts = createAction({
name: ({ t }) => t("Keyboard shortcuts"),
section: NavigationSection,
shortcut: ["?"],
iconInContextMenu: false,
icon: <KeyboardIcon />,
perform: ({ t }) => {
stores.dialogs.openGuide({
title: t("Keyboard shortcuts"),
content: <KeyboardShortcuts />,
});
},
});
export const logout = createAction({
name: ({ t }) => t("Log out"),
section: NavigationSection,
icon: <LogoutIcon />,
perform: () => stores.auth.logout(),
});
export const rootNavigationActions = [
navigateToHome,
navigateToDrafts,
navigateToTemplates,
navigateToArchive,
navigateToTrash,
openAPIDocumentation,
openFeedbackUrl,
openBugReportUrl,
openChangelog,
openKeyboardShortcuts,
logout,
];
+49
View File
@@ -0,0 +1,49 @@
import { SunIcon, MoonIcon, BrowserIcon } from "outline-icons";
import * as React from "react";
import stores from "~/stores";
import { Theme } from "~/stores/UiStore";
import { createAction } from "~/actions";
import { SettingsSection } from "~/actions/sections";
export const changeToDarkTheme = createAction({
name: ({ t }) => t("Dark"),
icon: <MoonIcon />,
iconInContextMenu: false,
keywords: "theme dark night",
section: SettingsSection,
selected: () => stores.ui.theme === "dark",
perform: () => stores.ui.setTheme(Theme.Dark),
});
export const changeToLightTheme = createAction({
name: ({ t }) => t("Light"),
icon: <SunIcon />,
iconInContextMenu: false,
keywords: "theme light day",
section: SettingsSection,
selected: () => stores.ui.theme === "light",
perform: () => stores.ui.setTheme(Theme.Light),
});
export const changeToSystemTheme = createAction({
name: ({ t }) => t("System"),
icon: <BrowserIcon />,
iconInContextMenu: false,
keywords: "theme system default",
section: SettingsSection,
selected: () => stores.ui.theme === "system",
perform: () => stores.ui.setTheme(Theme.System),
});
export const changeTheme = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Appearance") : t("Change theme"),
placeholder: ({ t }) => t("Change theme to"),
icon: () =>
stores.ui.resolvedTheme === "light" ? <SunIcon /> : <MoonIcon />,
keywords: "appearance display",
section: SettingsSection,
children: [changeToLightTheme, changeToDarkTheme, changeToSystemTheme],
});
export const rootSettingsActions = [changeTheme];
+40
View File
@@ -0,0 +1,40 @@
import * as React from "react";
import styled from "styled-components";
import { createAction } from "~/actions";
import { loadSessionsFromCookie } from "~/hooks/useSessions";
export const changeTeam = createAction({
name: ({ t }) => t("Switch team"),
placeholder: ({ t }) => t("Select a team"),
keywords: "change workspace organization",
section: "Account",
visible: ({ currentTeamId }) => {
const sessions = loadSessionsFromCookie();
const otherSessions = sessions.filter(
(session) => session.teamId !== currentTeamId
);
return otherSessions.length > 0;
},
children: ({ currentTeamId }) => {
const sessions = loadSessionsFromCookie();
const otherSessions = sessions.filter(
(session) => session.teamId !== currentTeamId
);
return otherSessions.map((session) => ({
id: session.url,
name: session.name,
section: "Account",
icon: <Logo alt={session.name} src={session.logoUrl} />,
perform: () => (window.location.href = session.url),
}));
},
});
const Logo = styled("img")`
border-radius: 2px;
width: 24px;
height: 24px;
`;
export const rootTeamActions = [changeTeam];
+23
View File
@@ -0,0 +1,23 @@
import { PlusIcon } from "outline-icons";
import * as React from "react";
import stores from "~/stores";
import Invite from "~/scenes/Invite";
import { createAction } from "~/actions";
import { UserSection } from "~/actions/sections";
export const inviteUser = createAction({
name: ({ t }) => `${t("Invite people")}`,
icon: <PlusIcon />,
keywords: "team member user",
section: UserSection,
visible: ({ stores }) =>
stores.policies.abilities(stores.auth.team?.id || "").inviteUser,
perform: ({ t }) => {
stores.dialogs.openModal({
title: t("Invite people"),
content: <Invite onSubmit={stores.dialogs.closeAllModals} />,
});
},
});
export const rootUserActions = [inviteUser];
+97
View File
@@ -0,0 +1,97 @@
import { flattenDeep } from "lodash";
import * as React from "react";
import { Optional } from "utility-types";
import { v4 as uuidv4 } from "uuid";
import {
Action,
ActionContext,
CommandBarAction,
MenuItemButton,
MenuItemWithChildren,
} from "~/types";
function resolve<T>(value: any, context: ActionContext): T {
return typeof value === "function" ? value(context) : value;
}
export function createAction(definition: Optional<Action, "id">): Action {
return {
...definition,
id: uuidv4(),
};
}
export function actionToMenuItem(
action: Action,
context: ActionContext
): MenuItemButton | MenuItemWithChildren {
const resolvedIcon = resolve<React.ReactElement<any>>(action.icon, context);
const resolvedChildren = resolve<Action[]>(action.children, context);
const visible = action.visible ? action.visible(context) : true;
const title = resolve<string>(action.name, context);
const icon =
resolvedIcon && action.iconInContextMenu !== false
? React.cloneElement(resolvedIcon, {
color: "currentColor",
})
: undefined;
if (resolvedChildren) {
const items = resolvedChildren
.map((a) => actionToMenuItem(a, context))
.filter(Boolean)
.filter((a) => a.visible);
return {
type: "submenu",
title,
icon,
items,
visible: visible && items.length > 0,
};
}
return {
type: "button",
title,
icon,
visible,
dangerous: action.dangerous,
onClick: () => action.perform && action.perform(context),
selected: action.selected ? action.selected(context) : undefined,
};
}
export function actionToKBar(
action: Action,
context: ActionContext
): CommandBarAction[] {
if (typeof action.visible === "function" && !action.visible(context)) {
return [];
}
const resolvedIcon = resolve<React.ReactElement<any>>(action.icon, context);
const resolvedChildren = resolve<Action[]>(action.children, context);
const resolvedSection = resolve<string>(action.section, context);
const resolvedName = resolve<string>(action.name, context);
const resolvedPlaceholder = resolve<string>(action.placeholder, context);
const children = resolvedChildren
? flattenDeep(resolvedChildren.map((a) => actionToKBar(a, context))).filter(
(a) => !!a
)
: [];
return [
{
id: action.id,
name: resolvedName,
section: resolvedSection,
placeholder: resolvedPlaceholder,
keywords: action.keywords ?? "",
shortcut: action.shortcut || [],
icon: resolvedIcon,
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 })));
}
+17
View File
@@ -0,0 +1,17 @@
import { rootCollectionActions } from "./definitions/collections";
import { rootDeveloperActions } from "./definitions/developer";
import { rootDocumentActions } from "./definitions/documents";
import { rootNavigationActions } from "./definitions/navigation";
import { rootSettingsActions } from "./definitions/settings";
import { rootTeamActions } from "./definitions/teams";
import { rootUserActions } from "./definitions/users";
export default [
...rootCollectionActions,
...rootDocumentActions,
...rootUserActions,
...rootNavigationActions,
...rootSettingsActions,
...rootDeveloperActions,
...rootTeamActions,
];
+16
View File
@@ -0,0 +1,16 @@
import { ActionContext } from "~/types";
export const CollectionSection = ({ t }: ActionContext) => t("Collection");
export const DeveloperSection = ({ t }: ActionContext) => t("Debug");
export const DocumentSection = ({ t }: ActionContext) => t("Document");
export const SettingsSection = ({ t }: ActionContext) => t("Settings");
export const NavigationSection = ({ t }: ActionContext) => t("Navigation");
export const UserSection = ({ t }: ActionContext) => t("People");
export const RecentSearchesSection = ({ t }: ActionContext) =>
t("Recent searches");
+73
View File
@@ -0,0 +1,73 @@
import * as React from "react";
import Tooltip, { Props as TooltipProps } from "~/components/Tooltip";
import { Action, ActionContext } from "~/types";
export type Props = {
/** Show the button in a disabled state */
disabled?: boolean;
/** Hide the button entirely if action is not applicable */
hideOnActionDisabled?: boolean;
/** Action to use on button */
action?: Action;
/** Context of action, must be provided with action */
context?: ActionContext;
/** If tooltip props are provided the button will be wrapped in a tooltip */
tooltip?: Omit<TooltipProps, "children">;
};
/**
* Button that can be used to trigger an action definition.
*/
const ActionButton = React.forwardRef(
(
{
action,
context,
tooltip,
hideOnActionDisabled,
...rest
}: Props & React.HTMLAttributes<HTMLButtonElement>,
ref: React.Ref<HTMLButtonElement>
) => {
const disabled = rest.disabled;
if (!context || !action) {
return <button {...rest} ref={ref} />;
}
if (action?.visible && !action.visible(context) && hideOnActionDisabled) {
return null;
}
const label =
typeof action.name === "function" ? action.name(context) : action.name;
const button = (
<button
{...rest}
aria-label={label}
disabled={disabled}
ref={ref}
onClick={
action?.perform && context
? (ev) => {
ev.preventDefault();
ev.stopPropagation();
action.perform?.(context);
}
: rest.onClick
}
>
{rest.children ?? label}
</button>
);
if (tooltip) {
return <Tooltip {...tooltip}>{button}</Tooltip>;
}
return button;
}
);
export default ActionButton;
@@ -1,7 +1,6 @@
// @flow
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import Flex from "components/Flex";
import Flex from "~/components/Flex";
export const Action = styled(Flex)`
justify-content: center;
@@ -11,11 +10,6 @@ export const Action = styled(Flex)`
font-size: 15px;
flex-shrink: 0;
a {
color: ${(props) => props.theme.text};
height: 24px;
}
&:empty {
display: none;
}
@@ -38,7 +32,7 @@ const Actions = styled(Flex)`
background: ${(props) => props.theme.background};
transition: ${(props) => props.theme.backgroundTransition};
padding: 12px;
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
@media print {
display: none;
@@ -1,34 +1,35 @@
// @flow
/* global ga */
import * as React from "react";
import env from "env";
import env from "~/env";
type Props = {
children?: React.Node,
};
export default class Analytics extends React.Component<Props> {
export default class Analytics extends React.Component {
componentDidMount() {
if (!env.GOOGLE_ANALYTICS_ID) return;
if (!env.GOOGLE_ANALYTICS_ID) {
return;
}
// standard Google Analytics script
window.ga =
window.ga ||
function () {
// $FlowIssue
(ga.q = ga.q || []).push(arguments);
function (...args) {
(ga.q = ga.q || []).push(args);
};
// $FlowIssue
ga.l = +new Date();
ga("create", env.GOOGLE_ANALYTICS_ID, "auto");
ga("set", { dimension1: "true" });
ga("set", {
dimension1: "true",
});
ga("send", "pageview");
const script = document.createElement("script");
script.src = "https://www.google-analytics.com/analytics.js";
script.async = true;
// Track PWA install event
window.addEventListener("appinstalled", () => {
ga("send", "event", "pwa", "install");
});
if (document.body) {
document.body.appendChild(script);
}
+22
View File
@@ -0,0 +1,22 @@
import * as React from "react";
export default function Arrow() {
return (
<svg
width="13"
height="30"
viewBox="0 0 13 30"
fill="none"
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"
/>
</svg>
);
}
+51
View File
@@ -0,0 +1,51 @@
import { observer } from "mobx-react";
import * as React from "react";
import {
useCompositeState,
Composite,
CompositeStateReturn,
} from "reakit/Composite";
type Props = {
children: (composite: CompositeStateReturn) => React.ReactNode;
onEscape?: (ev: React.KeyboardEvent<HTMLDivElement>) => void;
};
function ArrowKeyNavigation(
{ children, onEscape, ...rest }: Props,
ref: React.RefObject<HTMLDivElement>
) {
const composite = useCompositeState();
const handleKeyDown = React.useCallback(
(ev) => {
if (onEscape) {
if (ev.key === "Escape") {
onEscape(ev);
}
if (
ev.key === "ArrowUp" &&
composite.currentId === composite.items[0].id
) {
onEscape(ev);
}
}
},
[composite.currentId, composite.items, onEscape]
);
return (
<Composite
{...rest}
{...composite}
onKeyDown={handleKeyDown}
role="menu"
ref={ref}
>
{children(composite)}
</Composite>
);
}
export default observer(React.forwardRef(ArrowKeyNavigation));
@@ -1,10 +1,9 @@
// @flow
import * as React from "react";
type Props = {
size?: number,
fill?: string,
className?: string,
size?: number;
fill?: string;
className?: string;
};
function GoogleLogo({ size = 34, fill = "#FFF", className }: Props) {
+43
View File
@@ -0,0 +1,43 @@
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;
@@ -1,10 +1,9 @@
// @flow
import * as React from "react";
type Props = {
size?: number,
fill?: string,
className?: string,
size?: number;
fill?: string;
className?: string;
};
function SlackLogo({ size = 34, fill = "#FFF", className }: Props) {
+48
View File
@@ -0,0 +1,48 @@
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;
-43
View File
@@ -1,43 +0,0 @@
// @flow
import { observer, inject } from "mobx-react";
import * as React from "react";
import { Redirect } from "react-router-dom";
import { isCustomSubdomain } from "shared/utils/domains";
import AuthStore from "stores/AuthStore";
import LoadingIndicator from "components/LoadingIndicator";
import env from "env";
type Props = {
auth: AuthStore,
children?: React.Node,
};
const Authenticated = observer(({ auth, children }: Props) => {
if (auth.authenticated) {
const { user, team } = auth;
const { hostname } = window.location;
if (!team || !user) {
return <LoadingIndicator />;
}
// If we're authenticated but viewing a subdomain that doesn't match the
// currently authenticated team then kick the user to the teams subdomain.
if (
env.SUBDOMAINS_ENABLED &&
team.subdomain &&
isCustomSubdomain(hostname) &&
!hostname.startsWith(`${team.subdomain}.`)
) {
window.location.href = `${team.url}${window.location.pathname}`;
return <LoadingIndicator />;
}
return children;
}
auth.logout(true);
return <Redirect to="/" />;
});
export default inject("auth")(Authenticated);
+38
View File
@@ -0,0 +1,38 @@
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 useStores from "~/hooks/useStores";
import { changeLanguage } from "~/utils/language";
type Props = {
children: JSX.Element;
};
const Authenticated = ({ children }: Props) => {
const { auth } = useStores();
const { i18n } = useTranslation();
const language = auth.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
React.useEffect(() => {
changeLanguage(language, i18n);
}, [i18n, language]);
if (auth.authenticated) {
const { user, team } = auth;
if (!team || !user) {
return <LoadingIndicator />;
}
return children;
}
auth.logout(true);
return <Redirect to="/" />;
};
export default observer(Authenticated);
+110
View File
@@ -0,0 +1,110 @@
import { observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { withTranslation, WithTranslation } from "react-i18next";
import { Switch, Route } from "react-router-dom";
import RootStore from "~/stores/RootStore";
import ErrorSuspended from "~/scenes/ErrorSuspended";
import Layout from "~/components/Layout";
import RegisterKeyDown from "~/components/RegisterKeyDown";
import Sidebar from "~/components/Sidebar";
import SettingsSidebar from "~/components/Sidebar/Settings";
import history from "~/utils/history";
import {
searchPath,
matchDocumentSlug as slug,
newDocumentPath,
settingsPath,
} from "~/utils/routeHelpers";
import Fade from "./Fade";
import withStores from "./withStores";
const DocumentHistory = React.lazy(
() =>
import(
/* webpackChunkName: "document-history" */
"~/components/DocumentHistory"
)
);
const CommandBar = React.lazy(
() =>
import(
/* webpackChunkName: "command-bar" */
"~/components/CommandBar"
)
);
type Props = WithTranslation & RootStore;
@observer
class AuthenticatedLayout extends React.Component<Props> {
scrollable: HTMLDivElement | null | undefined;
@observable
keyboardShortcutsOpen = false;
goToSearch = (ev: KeyboardEvent) => {
if (!ev.metaKey && !ev.ctrlKey) {
ev.preventDefault();
ev.stopPropagation();
history.push(searchPath());
}
};
goToNewDocument = (event: KeyboardEvent) => {
if (event.metaKey || event.altKey) {
return;
}
const { activeCollectionId } = this.props.ui;
if (!activeCollectionId) {
return;
}
const can = this.props.policies.abilities(activeCollectionId);
if (!can.update) {
return;
}
history.push(newDocumentPath(activeCollectionId));
};
render() {
const { auth } = this.props;
const { user, team } = auth;
const showSidebar = auth.authenticated && user && team;
if (auth.isSuspended) {
return <ErrorSuspended />;
}
const sidebar = showSidebar ? (
<Fade>
<Switch>
<Route path={settingsPath()} component={SettingsSidebar} />
<Route component={Sidebar} />
</Switch>
</Fade>
) : undefined;
const rightRail = (
<React.Suspense fallback={null}>
<Switch>
<Route
path={`/doc/${slug}/history/:revisionId?`}
component={DocumentHistory}
/>
</Switch>
</React.Suspense>
);
return (
<Layout title={team?.name} sidebar={sidebar} rightRail={rightRail}>
<RegisterKeyDown trigger="n" handler={this.goToNewDocument} />
<RegisterKeyDown trigger="t" handler={this.goToSearch} />
<RegisterKeyDown trigger="/" handler={this.goToSearch} />
{this.props.children}
<CommandBar />
</Layout>
);
}
}
export default withTranslation()(withStores(AuthenticatedLayout));
@@ -1,19 +1,25 @@
// @flow
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";
type Props = {
src: string,
size: number,
icon?: React.Node,
src: string;
size: number;
icon?: React.ReactNode;
user?: User;
alt?: string;
showBorder?: boolean;
onClick?: React.MouseEventHandler<HTMLImageElement>;
className?: string;
};
@observer
class Avatar extends React.Component<Props> {
@observable error: boolean;
@observable
error: boolean;
static defaultProps = {
size: 24,
@@ -24,13 +30,13 @@ class Avatar extends React.Component<Props> {
};
render() {
const { src, icon, ...rest } = this.props;
const { src, icon, showBorder, ...rest } = this.props;
return (
<AvatarWrapper>
<CircleImg
onError={this.handleError}
src={this.error ? placeholder : src}
$showBorder={showBorder}
{...rest}
/>
{icon && <IconWrapper>{icon}</IconWrapper>}
@@ -55,12 +61,14 @@ const IconWrapper = styled.div`
height: 20px;
`;
const CircleImg = styled.img`
const CircleImg = styled.img<{ size: number; $showBorder?: boolean }>`
display: block;
width: ${(props) => props.size}px;
height: ${(props) => props.size}px;
border-radius: 50%;
border: 2px solid ${(props) => props.theme.background};
border: 2px solid
${(props) =>
props.$showBorder === false ? "transparent" : props.theme.background};
flex-shrink: 0;
`;
@@ -1,86 +0,0 @@
// @flow
import distanceInWordsToNow from "date-fns/distance_in_words_to_now";
import { observable } from "mobx";
import { observer } from "mobx-react";
import { EditIcon } from "outline-icons";
import * as React from "react";
import styled from "styled-components";
import User from "models/User";
import UserProfile from "scenes/UserProfile";
import Avatar from "components/Avatar";
import Tooltip from "components/Tooltip";
type Props = {
user: User,
isPresent: boolean,
isEditing: boolean,
isCurrentUser: boolean,
lastViewedAt: string,
};
@observer
class AvatarWithPresence extends React.Component<Props> {
@observable isOpen: boolean = false;
handleOpenProfile = () => {
this.isOpen = true;
};
handleCloseProfile = () => {
this.isOpen = false;
};
render() {
const {
user,
lastViewedAt,
isPresent,
isEditing,
isCurrentUser,
} = this.props;
return (
<>
<Tooltip
tooltip={
<Centered>
<strong>{user.name}</strong> {isCurrentUser && "(You)"}
<br />
{isPresent
? isEditing
? "currently editing"
: "currently viewing"
: `viewed ${distanceInWordsToNow(new Date(lastViewedAt))} ago`}
</Centered>
}
placement="bottom"
>
<AvatarWrapper isPresent={isPresent}>
<Avatar
src={user.avatarUrl}
onClick={this.handleOpenProfile}
size={32}
icon={isEditing ? <EditIcon size={16} color="#FFF" /> : undefined}
/>
</AvatarWrapper>
</Tooltip>
<UserProfile
user={user}
isOpen={this.isOpen}
onRequestClose={this.handleCloseProfile}
/>
</>
);
}
}
const Centered = styled.div`
text-align: center;
`;
const AvatarWrapper = styled.div`
opacity: ${(props) => (props.isPresent ? 1 : 0.5)};
transition: opacity 250ms ease-in-out;
`;
export default AvatarWithPresence;
@@ -0,0 +1,141 @@
import { observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { WithTranslation, withTranslation } from "react-i18next";
import styled, { css } from "styled-components";
import User from "~/models/User";
import UserProfile from "~/scenes/UserProfile";
import Avatar from "~/components/Avatar";
import Tooltip from "~/components/Tooltip";
type Props = WithTranslation & {
user: User;
isPresent: boolean;
isEditing: boolean;
isObserving: boolean;
isCurrentUser: boolean;
profileOnClick: boolean;
onClick?: React.MouseEventHandler<HTMLImageElement>;
};
@observer
class AvatarWithPresence extends React.Component<Props> {
@observable
isOpen = false;
handleOpenProfile = () => {
this.isOpen = true;
};
handleCloseProfile = () => {
this.isOpen = false;
};
render() {
const {
onClick,
user,
isPresent,
isEditing,
isObserving,
isCurrentUser,
t,
} = this.props;
const status = isPresent
? isEditing
? t("currently editing")
: t("currently viewing")
: t("previously edited");
return (
<>
<Tooltip
tooltip={
<Centered>
<strong>{user.name}</strong> {isCurrentUser && `(${t("You")})`}
{status && (
<>
<br />
{status}
</>
)}
</Centered>
}
placement="bottom"
>
<AvatarWrapper
$isPresent={isPresent}
$isObserving={isObserving}
$color={user.color}
>
<Avatar
src={user.avatarUrl}
onClick={
this.props.profileOnClick === false
? onClick
: this.handleOpenProfile
}
size={32}
/>
</AvatarWrapper>
</Tooltip>
{this.props.profileOnClick && (
<UserProfile
user={user}
isOpen={this.isOpen}
onRequestClose={this.handleCloseProfile}
/>
)}
</>
);
}
}
const Centered = styled.div`
text-align: center;
`;
const AvatarWrapper = styled.div<{
$isPresent: boolean;
$isObserving: boolean;
$color: string;
}>`
opacity: ${(props) => (props.$isPresent ? 1 : 0.5)};
transition: opacity 250ms ease-in-out;
border-radius: 50%;
position: relative;
&:after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 50%;
transition: border-color 100ms ease-in-out;
border: 2px solid transparent;
pointer-events: none;
${(props) =>
props.$isObserving &&
css`
border: 2px solid ${props.$color};
box-shadow: inset 0 0 0 2px ${props.theme.background};
&:hover {
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
}
`}
}
&:hover:after {
border: 2px solid ${(props) => props.$color};
box-shadow: inset 0 0 0 2px ${(props) => props.theme.background};
}
`;
export default withTranslation()(AvatarWithPresence);
@@ -1,6 +1,6 @@
// @flow
import Avatar from "./Avatar";
import AvatarWithPresence from "./AvatarWithPresence";
export { AvatarWithPresence };
export default Avatar;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 976 B

After

Width:  |  Height:  |  Size: 564 B

-17
View File
@@ -1,17 +0,0 @@
// @flow
import styled from "styled-components";
const Badge = styled.span`
margin-left: 10px;
padding: 2px 6px 3px;
background-color: ${({ primary, theme }) =>
primary ? theme.primary : theme.textTertiary};
color: ${({ primary, theme }) => (primary ? theme.white : theme.background)};
border-radius: 4px;
font-size: 11px;
font-weight: 500;
text-transform: uppercase;
user-select: none;
`;
export default Badge;
+22
View File
@@ -0,0 +1,22 @@
import { transparentize } from "polished";
import styled from "styled-components";
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"};
color: ${({ primary, yellow, theme }) =>
primary ? theme.white : yellow ? theme.almostBlack : theme.textTertiary};
border: 1px solid
${({ primary, yellow, theme }) =>
primary || yellow
? "transparent"
: transparentize(0.4, theme.textTertiary)};
border-radius: 10px;
font-size: 12px;
font-weight: 500;
user-select: none;
`;
export default Badge;
@@ -1,11 +1,12 @@
// @flow
import * as React from "react";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { depths } from "@shared/styles";
import env from "~/env";
import OutlineLogo from "./OutlineLogo";
import env from "env";
type Props = {
href?: string,
href?: string;
};
function Branding({ href = env.URL }: Props) {
@@ -18,9 +19,8 @@ function Branding({ href = env.URL }: Props) {
}
const Link = styled.a`
position: fixed;
bottom: 0;
left: 0;
justify-content: center;
padding-bottom: 16px;
font-weight: 600;
font-size: 14px;
@@ -29,7 +29,6 @@ const Link = styled.a`
color: ${(props) => props.theme.text};
display: flex;
align-items: center;
padding: 16px;
svg {
fill: ${(props) => props.theme.text};
@@ -38,6 +37,14 @@ const Link = styled.a`
&:hover {
background: ${(props) => props.theme.sidebarBackground};
}
${breakpoint("tablet")`
z-index: ${depths.sidebar + 1};
position: fixed;
bottom: 0;
left: 0;
padding: 16px;
`};
`;
export default Branding;
-162
View File
@@ -1,162 +0,0 @@
// @flow
import { observer, inject } from "mobx-react";
import {
PadlockIcon,
GoToIcon,
MoreIcon,
ShapesIcon,
EditIcon,
} from "outline-icons";
import * as React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
import CollectionsStore from "stores/CollectionsStore";
import Document from "models/Document";
import CollectionIcon from "components/CollectionIcon";
import Flex from "components/Flex";
import BreadcrumbMenu from "./BreadcrumbMenu";
import { collectionUrl } from "utils/routeHelpers";
type Props = {
document: Document,
collections: CollectionsStore,
onlyText: boolean,
};
const Breadcrumb = observer(({ document, collections, onlyText }: Props) => {
const collection = collections.get(document.collectionId);
if (!collection) return <div />;
const path = collection.pathToDocument(document).slice(0, -1);
if (onlyText === true) {
return (
<>
{collection.private && (
<>
<SmallPadlockIcon color="currentColor" size={16} />{" "}
</>
)}
{collection.name}
{path.map((n) => (
<React.Fragment key={n.id}>
<SmallSlash />
{n.title}
</React.Fragment>
))}
</>
);
}
const isTemplate = document.isTemplate;
const isDraft = !document.publishedAt && !isTemplate;
const isNestedDocument = path.length > 1;
const lastPath = path.length ? path[path.length - 1] : undefined;
const menuPath = isNestedDocument ? path.slice(0, -1) : [];
return (
<Wrapper justify="flex-start" align="center">
{isTemplate && (
<>
<CollectionName to="/templates">
<ShapesIcon color="currentColor" />
&nbsp;
<span>Templates</span>
</CollectionName>
<Slash />
</>
)}
{isDraft && (
<>
<CollectionName to="/drafts">
<EditIcon color="currentColor" />
&nbsp;
<span>Drafts</span>
</CollectionName>
<Slash />
</>
)}
<CollectionName to={collectionUrl(collection.id)}>
<CollectionIcon collection={collection} expanded />
&nbsp;
<span>{collection.name}</span>
</CollectionName>
{isNestedDocument && (
<>
<Slash /> <BreadcrumbMenu label={<Overflow />} path={menuPath} />
</>
)}
{lastPath && (
<>
<Slash />{" "}
<Crumb to={lastPath.url} title={lastPath.title}>
{lastPath.title}
</Crumb>
</>
)}
</Wrapper>
);
});
const Wrapper = styled(Flex)`
display: none;
${breakpoint("tablet")`
display: flex;
`};
`;
const SmallPadlockIcon = styled(PadlockIcon)`
display: inline-block;
vertical-align: sub;
`;
const SmallSlash = styled(GoToIcon)`
width: 15px;
height: 10px;
flex-shrink: 0;
opacity: 0.25;
`;
export const Slash = styled(GoToIcon)`
flex-shrink: 0;
fill: ${(props) => props.theme.divider};
`;
const Overflow = styled(MoreIcon)`
flex-shrink: 0;
opacity: 0.25;
transition: opacity 100ms ease-in-out;
&:hover,
&:active {
opacity: 1;
}
`;
const Crumb = styled(Link)`
color: ${(props) => props.theme.text};
font-size: 15px;
height: 24px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
&:hover {
text-decoration: underline;
}
`;
const CollectionName = styled(Link)`
display: flex;
flex-shrink: 0;
color: ${(props) => props.theme.text};
font-size: 15px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
`;
export default inject("collections")(Breadcrumb);
+88
View File
@@ -0,0 +1,88 @@
import { GoToIcon } from "outline-icons";
import * as React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
import Flex from "~/components/Flex";
import BreadcrumbMenu from "~/menus/BreadcrumbMenu";
import { MenuInternalLink } from "~/types";
type Props = {
items: MenuInternalLink[];
max?: number;
highlightFirstItem?: boolean;
};
function Breadcrumb({
items,
highlightFirstItem,
children,
max = 2,
}: React.PropsWithChildren<Props>) {
const totalItems = items.length;
const topLevelItems: MenuInternalLink[] = [...items];
let overflowItems;
// chop middle breadcrumbs and present a "..." menu instead
if (totalItems > max) {
const halfMax = Math.floor(max / 2);
overflowItems = topLevelItems.splice(halfMax, totalItems - max);
topLevelItems.splice(halfMax, 0, {
to: "",
type: "route",
title: <BreadcrumbMenu items={overflowItems as MenuInternalLink[]} />,
});
}
return (
<Flex justify="flex-start" align="center">
{topLevelItems.map((item, index) => (
<React.Fragment key={String(item.to) || index}>
{item.icon}
{item.to ? (
<Item
to={item.to}
$withIcon={!!item.icon}
$highlight={!!highlightFirstItem && index === 0}
>
{item.title}
</Item>
) : (
item.title
)}
{index !== topLevelItems.length - 1 || !!children ? <Slash /> : null}
</React.Fragment>
))}
{children}
</Flex>
);
}
const Slash = styled(GoToIcon)`
flex-shrink: 0;
fill: ${(props) => props.theme.divider};
`;
const Item = styled(Link)<{ $highlight: boolean; $withIcon: boolean }>`
display: flex;
flex-shrink: 1;
min-width: 0;
color: ${(props) => props.theme.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")};
svg {
flex-shrink: 0;
}
&:hover {
text-decoration: underline;
}
`;
export default Breadcrumb;
-25
View File
@@ -1,25 +0,0 @@
// @flow
import * as React from "react";
import { Link } from "react-router-dom";
import { DropdownMenu, DropdownMenuItem } from "components/DropdownMenu";
type Props = {
label: React.Node,
path: Array<any>,
};
export default class BreadcrumbMenu extends React.Component<Props> {
render() {
const { path } = this.props;
return (
<DropdownMenu label={this.props.label} position="center">
{path.map((item) => (
<DropdownMenuItem as={Link} to={item.url} key={item.id}>
{item.title}
</DropdownMenuItem>
))}
</DropdownMenu>
);
}
}
-160
View File
@@ -1,160 +0,0 @@
// @flow
import { ExpandedIcon } from "outline-icons";
import { darken, lighten } from "polished";
import * as React from "react";
import styled from "styled-components";
const RealButton = styled.button`
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};
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
height: 32px;
text-decoration: none;
flex-shrink: 0;
outline: none;
cursor: pointer;
user-select: none;
svg {
fill: ${(props) => props.iconColor || props.theme.buttonText};
}
&::-moz-focus-inner {
padding: 0;
border: 0;
}
&:hover {
background: ${(props) => darken(0.05, props.theme.buttonBackground)};
}
&:focus {
transition-duration: 0.05s;
box-shadow: ${(props) => lighten(0.4, props.theme.buttonBackground)} 0px 0px
0px 3px;
outline: none;
}
&:disabled {
cursor: default;
pointer-events: none;
color: ${(props) => props.theme.white50};
}
${(props) =>
props.neutral &&
`
background: ${props.theme.buttonNeutralBackground};
color: ${props.theme.buttonNeutralText};
box-shadow: ${
props.borderOnHover ? "none" : "rgba(0, 0, 0, 0.07) 0px 1px 2px"
};
border: 1px solid ${
props.borderOnHover ? "transparent" : props.theme.buttonNeutralBorder
};
svg {
fill: ${props.iconColor || props.theme.buttonNeutralText};
}
&:hover {
background: ${darken(0.05, props.theme.buttonNeutralBackground)};
border: 1px solid ${props.theme.buttonNeutralBorder};
}
&:focus {
transition-duration: 0.05s;
border: 1px solid ${lighten(0.4, props.theme.buttonBackground)};
box-shadow: ${lighten(0.4, props.theme.buttonBackground)} 0px 0px
0px 2px;
}
&:disabled {
color: ${props.theme.textTertiary};
}
`} ${(props) =>
props.danger &&
`
background: ${props.theme.danger};
color: ${props.theme.white};
&:hover {
background: ${darken(0.05, props.theme.danger)};
}
&:focus {
transition-duration: 0.05s;
box-shadow: ${lighten(0.4, props.theme.danger)} 0px 0px
0px 3px;
}
`};
`;
const Label = styled.span`
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
${(props) => props.hasIcon && "padding-left: 4px;"};
`;
export const Inner = styled.span`
display: flex;
padding: 0 8px;
padding-right: ${(props) => (props.disclosure ? 2 : 8)}px;
line-height: ${(props) => (props.hasIcon ? 24 : 32)}px;
justify-content: center;
align-items: center;
min-height: 30px;
${(props) => props.hasIcon && props.hasText && "padding-left: 4px;"};
${(props) => props.hasIcon && !props.hasText && "padding: 0 4px;"};
`;
export type Props = {
type?: string,
value?: string,
icon?: React.Node,
iconColor?: string,
className?: string,
children?: React.Node,
innerRef?: React.ElementRef<any>,
disclosure?: boolean,
fullwidth?: boolean,
borderOnHover?: boolean,
};
function Button({
type = "text",
icon,
children,
value,
disclosure,
innerRef,
...rest
}: Props) {
const hasText = children !== undefined || value !== undefined;
const hasIcon = icon !== undefined;
return (
<RealButton type={type} ref={innerRef} {...rest}>
<Inner hasIcon={hasIcon} hasText={hasText} disclosure={disclosure}>
{hasIcon && icon}
{hasText && <Label hasIcon={hasIcon}>{children || value}</Label>}
{disclosure && <ExpandedIcon />}
</Inner>
</RealButton>
);
}
export default React.forwardRef<Props, typeof Button>((props, ref) => (
<Button {...props} innerRef={ref} />
));
+186
View File
@@ -0,0 +1,186 @@
import { LocationDescriptor } from "history";
import { ExpandedIcon } from "outline-icons";
import { darken, lighten } from "polished";
import * as React from "react";
import styled from "styled-components";
const RealButton = styled.button<{
fullwidth?: boolean;
borderOnHover?: boolean;
$neutral?: boolean;
danger?: boolean;
iconColor?: string;
}>`
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};
box-shadow: rgba(0, 0, 0, 0.2) 0px 1px 2px;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
height: 32px;
text-decoration: none;
flex-shrink: 0;
cursor: pointer;
user-select: none;
appearance: none !important;
${(props) =>
!props.borderOnHover &&
`
svg {
fill: ${props.iconColor || "currentColor"};
}
`}
&::-moz-focus-inner {
padding: 0;
border: 0;
}
&:hover:not(:disabled),
&[aria-expanded="true"] {
background: ${(props) => darken(0.05, props.theme.buttonBackground)};
}
&:disabled {
cursor: default;
pointer-events: none;
color: ${(props) => props.theme.white50};
background: ${(props) => lighten(0.2, props.theme.buttonBackground)};
svg {
fill: ${(props) => props.theme.white50};
}
}
${(props) =>
props.$neutral &&
`
background: ${props.theme.buttonNeutralBackground};
color: ${props.theme.buttonNeutralText};
box-shadow: ${
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.theme.buttonNeutralBackground
: darken(0.05, props.theme.buttonNeutralBackground)
};
box-shadow: rgba(0, 0, 0, 0.07) 0px 1px 2px, ${
props.theme.buttonNeutralBorder
} 0 0 0 1px inset;
}
&:disabled {
color: ${props.theme.textTertiary};
background: none;
svg {
fill: currentColor;
}
}
`}
${(props) =>
props.danger &&
`
background: ${props.theme.danger};
color: ${props.theme.white};
&:hover:not(:disabled),
&[aria-expanded="true"] {
background: ${darken(0.05, props.theme.danger)};
}
&:disabled {
background: ${lighten(0.05, props.theme.danger)};
}
&.focus-visible {
outline-color: ${darken(0.2, props.theme.danger)} !important;
}
`};
`;
const Label = styled.span<{ hasIcon?: boolean }>`
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
${(props) => props.hasIcon && "padding-left: 4px;"};
`;
export const Inner = styled.span<{
disclosure?: boolean;
hasIcon?: boolean;
hasText?: boolean;
}>`
display: flex;
padding: 0 8px;
padding-right: ${(props) => (props.disclosure ? 2 : 8)}px;
line-height: ${(props) => (props.hasIcon ? 24 : 32)}px;
justify-content: center;
align-items: center;
min-height: 32px;
${(props) => props.hasIcon && props.hasText && "padding-left: 4px;"};
${(props) => props.hasIcon && !props.hasText && "padding: 0 4px;"};
`;
export type Props<T> = {
icon?: React.ReactNode;
iconColor?: string;
children?: React.ReactNode;
disclosure?: boolean;
neutral?: boolean;
danger?: boolean;
primary?: boolean;
fullwidth?: boolean;
as?: T;
to?: LocationDescriptor;
borderOnHover?: boolean;
href?: string;
"data-on"?: string;
"data-event-category"?: string;
"data-event-action"?: string;
};
const Button = <T extends React.ElementType = "button">(
props: Props<T> & React.ComponentPropsWithoutRef<T>,
ref: React.Ref<HTMLButtonElement>
) => {
const { type, icon, children, value, disclosure, neutral, ...rest } = props;
const hasText = children !== undefined || value !== undefined;
const hasIcon = icon !== undefined;
return (
<RealButton type={type || "button"} ref={ref} $neutral={neutral} {...rest}>
<Inner hasIcon={hasIcon} hasText={hasText} disclosure={disclosure}>
{hasIcon && icon}
{hasText && <Label hasIcon={hasIcon}>{children || value}</Label>}
{disclosure && <ExpandedIcon color="currentColor" />}
</Inner>
</RealButton>
);
};
export default React.forwardRef(Button);
@@ -1,4 +1,3 @@
// @flow
import styled from "styled-components";
import Button, { Inner } from "./Button";
+14
View File
@@ -0,0 +1,14 @@
import styled from "styled-components";
const ButtonLink = styled.button`
margin: 0;
padding: 0;
border: 0;
color: ${(props) => props.theme.link};
line-height: inherit;
background: none;
text-decoration: none;
cursor: pointer;
`;
export default ButtonLink;
@@ -1,27 +1,32 @@
// @flow
import * as React from "react";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
type Props = {
children?: React.Node,
withStickyHeader?: boolean;
};
const Container = styled.div`
const Container = styled.div<Props>`
width: 100%;
padding: 60px 20px;
max-width: 100vw;
padding: ${(props) => (props.withStickyHeader ? "4px 12px" : "60px 12px")};
${breakpoint("tablet")`
padding: 60px;
padding: ${(props: Props) =>
props.withStickyHeader ? "4px 44px 60px" : "60px 44px"};
`};
`;
const Content = styled.div`
max-width: 46em;
margin: 0 auto;
${breakpoint("desktopLarge")`
max-width: 52em;
`};
`;
const CenteredContent = ({ children, ...rest }: Props) => {
const CenteredContent: React.FC<Props> = ({ children, ...rest }) => {
return (
<Container {...rest}>
<Content>{children}</Content>
-61
View File
@@ -1,61 +0,0 @@
// @flow
import * as React from "react";
import styled from "styled-components";
import HelpText from "components/HelpText";
import VisuallyHidden from "components/VisuallyHidden";
export type Props = {
checked?: boolean,
label?: string,
labelHidden?: boolean,
className?: string,
note?: string,
short?: boolean,
small?: boolean,
};
const LabelText = styled.span`
font-weight: 500;
margin-left: ${(props) => (props.small ? "6px" : "10px")};
${(props) => (props.small ? `color: ${props.theme.textSecondary}` : "")};
`;
const Wrapper = styled.div`
padding-bottom: 8px;
${(props) => (props.small ? "font-size: 14px" : "")};
`;
const Label = styled.label`
display: flex;
align-items: center;
user-select: none;
`;
export default function Checkbox({
label,
labelHidden,
note,
className,
small,
short,
...rest
}: Props) {
const wrappedLabel = <LabelText small={small}>{label}</LabelText>;
return (
<>
<Wrapper small={small}>
<Label>
<input type="checkbox" {...rest} />
{label &&
(labelHidden ? (
<VisuallyHidden>{wrappedLabel}</VisuallyHidden>
) : (
wrappedLabel
))}
</Label>
{note && <HelpText small>{note}</HelpText>}
</Wrapper>
</>
);
}
+80
View File
@@ -0,0 +1,80 @@
import React from "react";
import styled, { useTheme } from "styled-components";
const cleanPercentage = (percentage: number) => {
const tooLow = !Number.isFinite(+percentage) || percentage < 0;
const tooHigh = percentage > 100;
return tooLow ? 0 : tooHigh ? 100 : +percentage;
};
const Circle = ({
color,
percentage,
offset,
}: {
color: string;
percentage?: number;
offset: number;
}) => {
const radius = offset * 0.7;
const circumference = 2 * Math.PI * radius;
let strokePercentage;
if (percentage) {
// because the circle is so small, anything greater than 85% appears like 100%
percentage = percentage > 85 && percentage < 100 ? 85 : percentage;
strokePercentage = percentage
? ((100 - percentage) * circumference) / 100
: 0;
}
return (
<circle
r={radius}
cx={offset}
cy={offset}
fill="none"
stroke={strokePercentage !== circumference ? color : ""}
strokeWidth={2.5}
strokeDasharray={circumference}
strokeDashoffset={percentage ? strokePercentage : 0}
strokeLinecap="round"
style={{
transition: "stroke-dashoffset 0.6s ease 0s",
}}
></circle>
);
};
const CircularProgressBar = ({
percentage,
size = 16,
}: {
percentage: number;
size?: number;
}) => {
const theme = useTheme();
percentage = cleanPercentage(percentage);
const offset = Math.floor(size / 2);
return (
<SVG width={size} height={size}>
<g transform={`rotate(-90 ${offset} ${offset})`}>
<Circle color={theme.progressBarBackground} offset={offset} />
{percentage > 0 && (
<Circle
color={theme.primary}
percentage={percentage}
offset={offset}
/>
)}
</g>
</SVG>
);
};
const SVG = styled.svg`
flex-shrink: 0;
`;
export default CircularProgressBar;
@@ -1,7 +1,6 @@
// @flow
import styled from "styled-components";
const ClickablePadding = styled.div`
const ClickablePadding = styled.div<{ grow?: boolean }>`
min-height: 10em;
cursor: ${({ onClick }) => (onClick ? "text" : "default")};
${({ grow }) => grow && `flex-grow: 100;`};
-76
View File
@@ -1,76 +0,0 @@
// @flow
import { sortBy, keyBy } from "lodash";
import { observer, inject } from "mobx-react";
import * as React from "react";
import { MAX_AVATAR_DISPLAY } from "shared/constants";
import DocumentPresenceStore from "stores/DocumentPresenceStore";
import ViewsStore from "stores/ViewsStore";
import Document from "models/Document";
import { AvatarWithPresence } from "components/Avatar";
import Facepile from "components/Facepile";
type Props = {
views: ViewsStore,
presence: DocumentPresenceStore,
document: Document,
currentUserId: string,
};
@observer
class Collaborators extends React.Component<Props> {
componentDidMount() {
this.props.views.fetchPage({ documentId: this.props.document.id });
}
render() {
const { document, presence, views, currentUserId } = this.props;
let documentPresence = presence.get(document.id);
documentPresence = documentPresence
? Array.from(documentPresence.values())
: [];
const documentViews = views.inDocument(document.id);
const presentIds = documentPresence.map((p) => p.userId);
const editingIds = documentPresence
.filter((p) => p.isEditing)
.map((p) => p.userId);
// ensure currently present via websocket are always ordered first
const mostRecentViewers = sortBy(
documentViews.slice(0, MAX_AVATAR_DISPLAY),
(view) => {
return presentIds.includes(view.user.id);
}
);
const viewersKeyedByUserId = keyBy(mostRecentViewers, (v) => v.user.id);
const overflow = documentViews.length - mostRecentViewers.length;
return (
<Facepile
users={mostRecentViewers.map((v) => v.user)}
overflow={overflow}
renderAvatar={(user) => {
const isPresent = presentIds.includes(user.id);
const isEditing = editingIds.includes(user.id);
const { lastViewedAt } = viewersKeyedByUserId[user.id];
return (
<AvatarWithPresence
key={user.id}
user={user}
lastViewedAt={lastViewedAt}
isPresent={isPresent}
isEditing={isEditing}
isCurrentUser={currentUserId === user.id}
/>
);
}}
/>
);
}
}
export default inject("views", "presence")(Collaborators);
+121
View File
@@ -0,0 +1,121 @@
import { sortBy, filter, uniq, isEqual } from "lodash";
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 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";
type Props = {
document: Document;
};
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();
const { document } = props;
const documentPresence = presence.get(document.id);
const documentPresenceArray = documentPresence
? Array.from(documentPresence.values())
: [];
const presentIds = documentPresenceArray.map((p) => p.userId);
const editingIds = documentPresenceArray
.filter((p) => p.isEditing)
.map((p) => p.userId);
// ensure currently present via websocket are always ordered first
const collaborators = React.useMemo(
() =>
sortBy(
filter(
users.orderedData,
(user) =>
(presentIds.includes(user.id) ||
document.collaboratorIds.includes(user.id)) &&
!user.isSuspended
),
(user) => presentIds.includes(user.id)
),
[document.collaboratorIds, users.orderedData, presentIds]
);
// load any users we don't yet have in memory
React.useEffect(() => {
const ids = uniq([...document.collaboratorIds, ...presentIds])
.filter((userId) => !users.get(userId))
.sort();
if (!isEqual(requestedUserIds, ids) && ids.length > 0) {
setRequestedUserIds(ids);
users.fetchPage({ ids, limit: 100 });
}
}, [document, users, presentIds, document.collaboratorIds, requestedUserIds]);
const popover = usePopoverState({
gutter: 0,
placement: "bottom-end",
});
return (
<>
<PopoverDisclosure {...popover}>
{(props) => (
<NudeButton width={collaborators.length * 32} height={32} {...props}>
<Facepile
users={collaborators}
renderAvatar={(collaborator) => {
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;
return (
<AvatarWithPresence
key={collaborator.id}
user={collaborator}
isPresent={isPresent}
isEditing={isEditing}
isObserving={isObserving}
isCurrentUser={currentUserId === collaborator.id}
profileOnClick={false}
onClick={
isObservable
? (ev) => {
if (isPresent) {
ev.preventDefault();
ev.stopPropagation();
ui.setObservingUser(
isObserving ? undefined : collaborator.id
);
}
}
: undefined
}
/>
);
}}
/>
</NudeButton>
)}
</PopoverDisclosure>
<Popover {...popover} width={300} aria-label={t("Viewers")} tabIndex={0}>
<DocumentViews document={document} isOpen={popover.visible} />
</Popover>
</>
);
}
export default observer(Collaborators);
+69
View File
@@ -0,0 +1,69 @@
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import { useHistory } from "react-router-dom";
import Collection from "~/models/Collection";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import Text from "~/components/Text";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import useStores from "~/hooks/useStores";
import { homePath } from "~/utils/routeHelpers";
type Props = {
collection: Collection;
onSubmit: () => void;
};
function CollectionDeleteDialog({ collection, onSubmit }: Props) {
const team = useCurrentTeam();
const { ui } = useStores();
const history = useHistory();
const { t } = useTranslation();
const handleSubmit = async () => {
const redirect = collection.id === ui.activeCollectionId;
await collection.delete();
onSubmit();
if (redirect) {
history.push(homePath());
}
};
return (
<ConfirmationDialog
onSubmit={handleSubmit}
submitText={t("Im sure Delete")}
savingText={`${t("Deleting")}`}
danger
>
<>
<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."
values={{
collectionName: collection.name,
}}
components={{
em: <strong />,
}}
/>
</Text>
{team.defaultCollectionId === collection.id ? (
<Text type="secondary">
<Trans
defaults="Also, <em>{{collectionName}}</em> is being used as the start view deleting it will reset the start view to the Home page."
values={{
collectionName: collection.name,
}}
components={{
em: <strong />,
}}
/>
</Text>
) : null}
</>
</ConfirmationDialog>
);
}
export default observer(CollectionDeleteDialog);
+230
View File
@@ -0,0 +1,230 @@
import debounce from "lodash/debounce";
import { observer } from "mobx-react";
import { transparentize } from "polished";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
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 usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts";
type Props = {
collection: Collection;
};
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);
const [isDirty, setDirty] = React.useState(false);
const can = usePolicy(collection);
const handleStartEditing = React.useCallback(() => {
setEditing(true);
}, []);
const handleStopEditing = React.useCallback(() => {
setEditing(false);
}, []);
const handleClickDisclosure = React.useCallback(
(event) => {
event.preventDefault();
if (isExpanded && document.activeElement) {
// @ts-expect-error ts-migrate(2339) FIXME: Property 'blur' does not exist on type 'Element'.
document.activeElement.blur();
}
setExpanded(!isExpanded);
},
[isExpanded]
);
const handleSave = React.useMemo(
() =>
debounce(async (getValue) => {
try {
await collection.save({
description: getValue(),
});
setDirty(false);
} catch (err) {
showToast(
t("Sorry, an error occurred saving the collection", {
type: "error",
})
);
throw err;
}
}, 1000),
[collection, showToast, t]
);
const handleChange = React.useCallback(
(getValue) => {
setDirty(true);
handleSave(getValue);
},
[handleSave]
);
React.useEffect(() => {
setEditing(false);
}, [collection.id]);
const placeholder = `${t("Add a description")}`;
const key = isEditing || isDirty ? "draft" : collection.updatedAt;
return (
<MaxHeight data-editing={isEditing} data-expanded={isExpanded}>
<Input data-editing={isEditing} data-expanded={isExpanded}>
<span onClick={can.update ? handleStartEditing : undefined}>
{collections.isSaving && <LoadingIndicator />}
{collection.hasDescription || isEditing || isDirty ? (
<React.Suspense
fallback={
<Placeholder
onClick={() => {
//
}}
>
Loading
</Placeholder>
}
>
<Editor
key={key}
defaultValue={collection.description || ""}
onChange={handleChange}
placeholder={placeholder}
readOnly={!isEditing}
autoFocus={isEditing}
onBlur={handleStopEditing}
maxLength={1000}
embedsDisabled
readOnlyWriteCheckboxes
/>
</React.Suspense>
) : (
can.update && (
<Placeholder
onClick={() => {
//
}}
>
{placeholder}
</Placeholder>
)
)}
</span>
</Input>
{!isEditing && (
<Disclosure
onClick={handleClickDisclosure}
aria-label={isExpanded ? t("Collapse") : t("Expand")}
size={30}
>
<Arrow />
</Disclosure>
)}
</MaxHeight>
);
}
const Disclosure = styled(NudeButton)`
opacity: 0;
color: ${(props) => props.theme.divider};
position: absolute;
top: calc(25vh - 50px);
left: 50%;
z-index: 1;
transform: rotate(-90deg) translateX(-50%);
transition: opacity 100ms ease-in-out;
&:focus,
&:hover {
opacity: 1;
}
&:active {
color: ${(props) => props.theme.sidebarText};
}
`;
const Placeholder = styled(ButtonLink)`
color: ${(props) => props.theme.placeholder};
cursor: text;
min-height: 27px;
`;
const MaxHeight = styled.div`
position: relative;
max-height: 25vh;
overflow: hidden;
margin: -12px -8px -8px;
padding: 8px;
&[data-editing="true"],
&[data-expanded="true"] {
max-height: initial;
overflow: initial;
${Disclosure} {
top: initial;
bottom: 0;
transform: rotate(90deg) translateX(-50%);
}
}
&:hover ${Disclosure} {
opacity: 1;
}
`;
const Input = styled.div`
margin: -8px;
padding: 8px;
border-radius: 8px;
transition: ${(props) => props.theme.backgroundTransition};
&:after {
content: "";
position: absolute;
top: calc(25vh - 50px);
left: 0;
right: 0;
height: 50px;
pointer-events: none;
background: linear-gradient(
180deg,
${(props) => transparentize(1, props.theme.background)} 0%,
${(props) => props.theme.background} 100%
);
}
&[data-editing="true"],
&[data-expanded="true"] {
&:after {
background: transparent;
}
}
&[data-editing="true"] {
background: ${(props) => props.theme.secondaryBackground};
}
.block-menu-trigger,
.heading-anchor {
display: none !important;
}
`;
export default observer(CollectionDescription);
-45
View File
@@ -1,45 +0,0 @@
// @flow
import { inject, observer } from "mobx-react";
import { PrivateCollectionIcon, CollectionIcon } from "outline-icons";
import { getLuminance } from "polished";
import * as React from "react";
import UiStore from "stores/UiStore";
import Collection from "models/Collection";
import { icons } from "components/IconPicker";
type Props = {
collection: Collection,
expanded?: boolean,
size?: number,
ui: UiStore,
};
function ResolvedCollectionIcon({ collection, expanded, size, ui }: Props) {
// If the chosen icon color is very dark then we invert it in dark mode
// otherwise it will be impossible to see against the dark background.
const color =
ui.resolvedTheme === "dark"
? getLuminance(collection.color) > 0.12
? collection.color
: "currentColor"
: collection.color;
if (collection.icon && collection.icon !== "collection") {
try {
const Component = icons[collection.icon].component;
return <Component color={color} size={size} />;
} catch (error) {
console.warn("Failed to render custom icon " + collection.icon);
}
}
if (collection.private) {
return (
<PrivateCollectionIcon color={color} expanded={expanded} size={size} />
);
}
return <CollectionIcon color={color} expanded={expanded} size={size} />;
}
export default inject("ui")(observer(ResolvedCollectionIcon));
+49
View File
@@ -0,0 +1,49 @@
import { observer } from "mobx-react";
import { CollectionIcon } from "outline-icons";
import { getLuminance } from "polished";
import * as React from "react";
import Collection from "~/models/Collection";
import { icons } from "~/components/IconPicker";
import useStores from "~/hooks/useStores";
import Logger from "~/utils/Logger";
type Props = {
collection: Collection;
expanded?: boolean;
size?: number;
color?: string;
};
function ResolvedCollectionIcon({
collection,
color: inputColor,
expanded,
size,
}: Props) {
const { ui } = useStores();
// If the chosen icon color is very dark then we invert it in dark mode
// otherwise it will be impossible to see against the dark background.
const color =
inputColor ||
(ui.resolvedTheme === "dark" && collection.color !== "currentColor"
? getLuminance(collection.color) > 0.09
? collection.color
: "currentColor"
: collection.color);
if (collection.icon && collection.icon !== "collection") {
try {
const Component = icons[collection.icon].component;
return <Component color={color} size={size} />;
} catch (error) {
Logger.warn("Failed to render custom icon", {
icon: collection.icon,
});
}
}
return <CollectionIcon color={color} expanded={expanded} size={size} />;
}
export default observer(ResolvedCollectionIcon);
+131
View File
@@ -0,0 +1,131 @@
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 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";
function CommandBar() {
const { t } = useTranslation();
const { ui } = useStores();
const settingsActions = useSettingsActions();
const commandBarActions = React.useMemo(
() => [...rootActions, settingsActions],
[settingsActions]
);
useCommandBarActions(commandBarActions);
const { rootAction } = useKBar((state) => ({
rootAction: state.currentRootActionId
? ((state.actions[
state.currentRootActionId
] as unknown) as CommandBarAction)
: undefined,
}));
return (
<>
<SearchActions />
<KBarPortal>
<Positioner>
<Animator>
<SearchInput
placeholder={`${
rootAction?.placeholder ||
rootAction?.name ||
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>
</>
);
}
const KBarPortal: React.FC = ({ children }) => {
const { showing } = useKBar((state) => ({
showing: state.visualState !== "hidden",
}));
if (!showing) {
return null;
}
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};
`;
const SearchInput = styled(KBarSearch)`
padding: 16px 20px;
width: 100%;
outline: none;
border: none;
background: ${(props) => props.theme.menuBackground};
color: ${(props) => props.theme.text};
&:disabled,
&::placeholder {
color: ${(props) => props.theme.placeholder};
}
`;
const Animator = styled(KBarAnimator)`
max-width: 600px;
max-height: 75vh;
width: 90vw;
background: ${(props) => props.theme.menuBackground};
color: ${(props) => props.theme.text};
border-radius: 8px;
overflow: hidden;
box-shadow: rgb(0 0 0 / 40%) 0px 16px 60px;
transition: max-width 0.2s ease-in-out;
${breakpoint("desktopLarge")`
max-width: 740px;
`};
@media print {
display: none;
}
`;
export default observer(CommandBar);
+122
View File
@@ -0,0 +1,122 @@
import { ActionImpl } from "kbar";
import { ArrowIcon, BackIcon } from "outline-icons";
import * as React from "react";
import styled, { css, useTheme } from "styled-components";
import Flex from "~/components/Flex";
import Key from "~/components/Key";
type Props = {
action: ActionImpl;
active: boolean;
currentRootActionId: string | null | undefined;
};
function CommandBarItem(
{ action, active, currentRootActionId }: Props,
ref: React.RefObject<HTMLDivElement>
) {
const theme = useTheme();
const ancestors = React.useMemo(() => {
if (!currentRootActionId) {
return action.ancestors;
}
const index = action.ancestors.findIndex(
(ancestor) => ancestor.id === currentRootActionId
);
// +1 removes the currentRootAction; e.g. if we are on the "Set theme"
// parent action, the UI should not display "Set theme… > Dark" but rather
// just "Dark"
return action.ancestors.slice(index + 1);
}, [action.ancestors, currentRootActionId]);
return (
<Item active={active} ref={ref}>
<Content align="center" gap={8}>
<Icon>
{action.icon ? (
// @ts-expect-error no icon on ActionImpl
React.cloneElement(action.icon, {
size: 22,
color: "currentColor",
})
) : (
<ArrowIcon color="currentColor" />
)}
</Icon>
{ancestors.map((ancestor) => (
<React.Fragment key={ancestor.id}>
<Ancestor>{ancestor.name}</Ancestor>
<ForwardIcon color={theme.textSecondary} size={22} />
</React.Fragment>
))}
{action.name}
{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>
))}
</div>
) : null}
</Item>
);
}
const Icon = styled(Flex)`
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
color: ${(props) => props.theme.textSecondary};
flex-shrink: 0;
`;
const Ancestor = styled.span`
color: ${(props) => props.theme.textSecondary};
`;
const Content = styled(Flex)`
overflow: hidden;
text-overflow: ellipsis;
flex-shrink: 1;
`;
const Item = styled.div<{ active?: boolean }>`
font-size: 15px;
padding: 10px 16px;
background: ${(props) =>
props.active ? props.theme.menuItemSelected : "none"};
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
min-width: 0;
${(props) =>
props.active &&
css`
${Icon} {
color: ${props.theme.text};
}
`}
`;
const ForwardIcon = styled(BackIcon)`
transform: rotate(180deg);
flex-shrink: 0;
`;
export default React.forwardRef<HTMLDivElement, Props>(CommandBarItem);
+35
View File
@@ -0,0 +1,35 @@
import { useMatches, KBarResults } from "kbar";
import * as React from "react";
import styled from "styled-components";
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}
/>
)
}
/>
);
}
const Header = styled.h3`
font-size: 13px;
letter-spacing: 0.04em;
margin: 0;
padding: 16px 0 4px 20px;
color: ${(props) => props.theme.textTertiary};
height: 36px;
`;
+61
View File
@@ -0,0 +1,61 @@
import { observer } from "mobx-react";
import * as React from "react";
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 */
onSubmit: () => Promise<void> | void;
/** Text to display on the submit button */
submitText?: string;
/** Text to display while the form is saving */
savingText?: string;
/** If true, the submit button will be a dangerous red */
danger?: boolean;
};
const ConfirmationDialog: React.FC<Props> = ({
onSubmit,
children,
submitText,
savingText,
danger,
}) => {
const [isSaving, setIsSaving] = React.useState(false);
const { dialogs } = useStores();
const { showToast } = useToasts();
const handleSubmit = React.useCallback(
async (ev: React.SyntheticEvent) => {
ev.preventDefault();
setIsSaving(true);
try {
await onSubmit();
dialogs.closeAllModals();
} catch (err) {
showToast(err.message, {
type: "error",
});
} finally {
setIsSaving(false);
}
},
[onSubmit, dialogs, showToast]
);
return (
<Flex column>
<form onSubmit={handleSubmit}>
<Text type="secondary">{children}</Text>
<Button type="submit" disabled={isSaving} danger={danger} autoFocus>
{isSaving ? savingText : submitText}
</Button>
</form>
</Flex>
);
};
export default observer(ConfirmationDialog);
+58
View File
@@ -0,0 +1,58 @@
import { observer } from "mobx-react";
import { DisconnectedIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled, { useTheme } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import Fade from "~/components/Fade";
import NudeButton from "~/components/NudeButton";
import Tooltip from "~/components/Tooltip";
import useStores from "~/hooks/useStores";
function ConnectionStatus() {
const { ui } = useStores();
const theme = useTheme();
const { t } = useTranslation();
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>
}
placement="bottom"
>
<Button>
<Fade>
<DisconnectedIcon color={theme.sidebarText} />
</Fade>
</Button>
</Tooltip>
) : null;
}
const Button = styled(NudeButton)`
display: none;
position: fixed;
bottom: 0;
right: 32px;
margin: 24px;
${breakpoint("tablet")`
display: block;
`};
@media print {
display: none;
}
`;
const Centered = styled.div`
text-align: center;
`;
export default observer(ConnectionStatus);
+191
View File
@@ -0,0 +1,191 @@
import isPrintableKeyEvent from "is-printable-key-event";
import * as React from "react";
import styled from "styled-components";
import useOnScreen from "~/hooks/useOnScreen";
type Props = Omit<React.HTMLAttributes<HTMLSpanElement>, "ref" | "onChange"> & {
disabled?: boolean;
readOnly?: boolean;
onClick?: React.MouseEventHandler<HTMLDivElement>;
onChange?: (text: string) => void;
onBlur?: React.FocusEventHandler<HTMLSpanElement> | undefined;
onInput?: React.FormEventHandler<HTMLSpanElement> | undefined;
onKeyDown?: React.KeyboardEventHandler<HTMLSpanElement> | undefined;
placeholder?: string;
maxLength?: number;
autoFocus?: boolean;
children?: React.ReactNode;
value: string;
};
export type RefHandle = {
focus: () => void;
focusAtStart: () => void;
focusAtEnd: () => void;
getComputedDirection: () => string;
};
/**
* 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("");
React.useImperativeHandle(ref, () => ({
focus: () => {
contentRef.current?.focus();
},
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 = (
callback:
| React.FocusEventHandler<HTMLSpanElement>
| React.FormEventHandler<HTMLSpanElement>
| React.KeyboardEventHandler<HTMLSpanElement>
| undefined
) => (event: any) => {
const text = contentRef.current?.innerText || "";
if (maxLength && isPrintableKeyEvent(event) && text.length >= maxLength) {
event?.preventDefault();
return;
}
if (text !== lastValue.current) {
lastValue.current = text;
onChange && 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);
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]);
// 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);
},
[]
);
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>
);
}
);
function placeCaret(element: HTMLElement, atStart: boolean) {
if (
typeof window.getSelection !== "undefined" &&
typeof document.createRange !== "undefined"
) {
const range = document.createRange();
range.selectNodeContents(element);
range.collapse(atStart);
const sel = window.getSelection();
sel?.removeAllRanges();
sel?.addRange(range);
}
}
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};
outline: none;
resize: none;
cursor: text;
&:empty {
display: inline-block;
}
&:empty::before {
display: inline-block;
color: ${(props) => props.theme.placeholder};
-webkit-text-fill-color: ${(props) => props.theme.placeholder};
content: attr(data-placeholder);
pointer-events: none;
height: 0;
}
`;
export default ContentEditable;
@@ -1,14 +1,12 @@
// @flow
import styled from "styled-components";
import Flex from "components/Flex";
const Header = styled(Flex)`
const Header = styled.h3`
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
color: ${(props) => props.theme.sidebarText};
letter-spacing: 0.04em;
margin: 4px 16px;
margin: 1em 12px 0.5em;
`;
export default Header;
+163
View File
@@ -0,0 +1,163 @@
import { LocationDescriptor } from "history";
import { CheckmarkIcon } from "outline-icons";
import * as React from "react";
import { MenuItem as BaseMenuItem } from "reakit/Menu";
import styled, { css } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import MenuIconWrapper from "../MenuIconWrapper";
type Props = {
onClick?: (event: React.SyntheticEvent) => void | Promise<void>;
selected?: boolean;
disabled?: boolean;
dangerous?: boolean;
to?: LocationDescriptor;
href?: string;
target?: "_blank";
as?: string | React.ComponentType<any>;
hide?: () => void;
level?: number;
icon?: React.ReactElement;
};
const MenuItem: React.FC<Props> = ({
onClick,
children,
selected,
disabled,
as,
hide,
icon,
...rest
}) => {
const handleClick = React.useCallback(
(ev) => {
if (onClick) {
ev.preventDefault();
ev.stopPropagation();
onClick(ev);
}
if (hide) {
hide();
}
},
[onClick, hide]
);
// 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}
disabled={disabled}
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>
)}
</BaseMenuItem>
);
};
const Spacer = styled.svg`
width: 24px;
height: 24px;
flex-shrink: 0;
`;
type MenuAnchorProps = {
level?: number;
disabled?: boolean;
dangerous?: boolean;
disclosure?: boolean;
};
export const MenuAnchorCSS = css<MenuAnchorProps>`
display: flex;
margin: 0;
border: 0;
padding: 12px;
padding-left: ${(props) => 12 + (props.level || 0) * 10}px;
width: 100%;
min-height: 32px;
background: none;
color: ${(props) =>
props.disabled ? props.theme.textTertiary : props.theme.textSecondary};
justify-content: left;
align-items: center;
font-size: 16px;
cursor: default;
user-select: none;
white-space: nowrap;
position: relative;
svg:not(:last-child) {
margin-right: 4px;
}
svg {
flex-shrink: 0;
opacity: ${(props) => (props.disabled ? ".5" : 1)};
}
${(props) =>
props.disabled
? "pointer-events: none;"
: `
@media (hover: hover) {
&:hover,
&:focus,
&.focus-visible {
color: ${props.theme.white};
background: ${props.dangerous ? props.theme.danger : props.theme.primary};
box-shadow: none;
cursor: pointer;
svg {
fill: ${props.theme.white};
}
}
}
`};
${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;
@@ -0,0 +1,66 @@
import * as React from "react";
import { useMousePosition } from "~/hooks/useMousePosition";
type Positions = {
/* Sub-menu x */
x: number;
/* Sub-menu y */
y: number;
/* Sub-menu height */
h: number;
/* Sub-menu width */
w: number;
/* Mouse x */
mouseX: number;
/* Mouse y */
mouseY: number;
};
/**
* Component to cover the area between the mouse cursor and the sub-menu, to
* allow moving cursor to lower parts of sub-menu without the sub-menu
* disappearing.
*/
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 [mouseX, mouseY] = useMousePosition();
const positions = { x, y, h, w, mouseX, mouseY };
return (
<div
style={{
position: "absolute",
top: 0,
// backgroundColor: "rgba(255,0,0,0.1)", // Uncomment to debug
right: getRight(positions),
left: getLeft(positions),
height: h,
width: getWidth(positions),
clipPath: getClipPath(positions),
}}
/>
);
}
const getLeft = ({ x, mouseX }: Positions) =>
mouseX > x ? undefined : -Math.max(x - mouseX, 10) + "px";
const getRight = ({ x, w, mouseX }: Positions) =>
mouseX > x ? -Math.max(mouseX - (x + w), 10) + "px" : undefined;
const getWidth = ({ x, w, mouseX }: Positions) =>
mouseX > x
? Math.max(mouseX - (x + w), 10) + "px"
: Math.max(x - mouseX, 10) + "px";
const getClipPath = ({ x, y, h, mouseX, mouseY }: Positions) =>
mouseX > x
? `polygon(0% 0%, 0% 100%, 100% ${(100 * (mouseY - y)) / h - 10}%, 100% ${
(100 * (mouseY - y)) / h + 5
}%)`
: `polygon(100% 0%, 0% ${(100 * (mouseY - y)) / h - 10}%, 0% ${
(100 * (mouseY - y)) / h + 5
}%, 100% 100%)`;
@@ -0,0 +1,25 @@
import { MoreIcon } from "outline-icons";
import * as React from "react";
import { MenuButton } from "reakit/Menu";
import NudeButton from "~/components/NudeButton";
type Props = React.ComponentProps<typeof MenuButton> & {
className?: string;
iconColor?: string;
};
export default function OverflowMenuButton({
iconColor,
className,
...rest
}: Props) {
return (
<MenuButton {...rest}>
{(props) => (
<NudeButton className={className} {...props}>
<MoreIcon color={iconColor} />
</NudeButton>
)}
</MenuButton>
);
}
+15
View File
@@ -0,0 +1,15 @@
import * as React from "react";
import { MenuSeparator } from "reakit/Menu";
import styled from "styled-components";
export default function Separator(rest: React.HTMLAttributes<HTMLHRElement>) {
return (
<MenuSeparator {...rest}>
{(props) => <HorizontalRule {...props} />}
</MenuSeparator>
);
}
const HorizontalRule = styled.hr`
margin: 0.5em 12px;
`;
+218
View File
@@ -0,0 +1,218 @@
import { ExpandedIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import {
useMenuState,
MenuButton,
MenuItem as BaseMenuItem,
} from "reakit/Menu";
import styled, { useTheme } from "styled-components";
import Flex from "~/components/Flex";
import MenuIconWrapper from "~/components/MenuIconWrapper";
import { actionToMenuItem } from "~/actions";
import useActionContext from "~/hooks/useActionContext";
import {
Action,
ActionContext,
MenuSeparator,
MenuHeading,
MenuItem as TMenuItem,
} from "~/types";
import Header from "./Header";
import MenuItem, { MenuAnchor } from "./MenuItem";
import MouseSafeArea from "./MouseSafeArea";
import Separator from "./Separator";
import ContextMenu from ".";
type Props = {
actions?: (Action | MenuSeparator | MenuHeading)[];
context?: Partial<ActionContext>;
items?: TMenuItem[];
};
const Disclosure = styled(ExpandedIcon)`
transform: rotate(270deg);
position: absolute;
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();
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>
</>
);
}
);
export function filterTemplateItems(items: TMenuItem[]): TMenuItem[] {
return items
.filter((item) => item.visible !== false)
.reduce((acc, item) => {
// trim separator if the previous item was a separator
if (
item.type === "separator" &&
acc[acc.length - 1]?.type === "separator"
) {
return acc;
}
return [...acc, item];
}, [] as TMenuItem[])
.filter((item, index, arr) => {
if (
item.type === "separator" &&
(index === 0 || index === arr.length - 1)
) {
return false;
}
return true;
});
}
function Template({ items, actions, context, ...menu }: Props) {
const ctx = useActionContext({
isContextMenu: true,
});
const templateItems = actions
? actions.map((item) =>
item.type === "separator" || item.type === "heading"
? item
: actionToMenuItem(item, ctx)
)
: items || [];
const filteredTemplates = filterTemplateItems(templateItems);
const iconIsPresentInAnyMenuItem = filteredTemplates.find(
(item) =>
item.type !== "separator" && item.type !== "heading" && !!item.icon
);
return (
<>
{filteredTemplates.map((item, index) => {
if (
iconIsPresentInAnyMenuItem &&
item.type !== "separator" &&
item.type !== "heading"
) {
item.icon = item.icon || <MenuIconWrapper />;
}
if (item.type === "route") {
return (
<MenuItem
as={Link}
to={item.to}
key={index}
disabled={item.disabled}
selected={item.selected}
icon={item.icon}
{...menu}
>
{item.title}
</MenuItem>
);
}
if (item.type === "link") {
return (
<MenuItem
href={item.href}
key={index}
disabled={item.disabled}
selected={item.selected}
level={item.level}
target={item.href.startsWith("#") ? undefined : "_blank"}
icon={item.icon}
{...menu}
>
{item.title}
</MenuItem>
);
}
if (item.type === "button") {
return (
<MenuItem
as="button"
onClick={item.onClick}
disabled={item.disabled}
selected={item.selected}
dangerous={item.dangerous}
key={index}
icon={item.icon}
{...menu}
>
{item.title}
</MenuItem>
);
}
if (item.type === "submenu") {
return (
<BaseMenuItem
key={index}
as={Submenu}
templateItems={item.items}
title={<Title title={item.title} icon={item.icon} />}
{...menu}
/>
);
}
if (item.type === "separator") {
return <Separator key={index} />;
}
if (item.type === "heading") {
return <Header>{item.title}</Header>;
}
const _exhaustiveCheck: never = item;
return _exhaustiveCheck;
})}
</>
);
}
function Title({
title,
icon,
}: {
title: React.ReactNode;
icon?: React.ReactNode;
}) {
return (
<Flex align="center">
{icon && <MenuIconWrapper>{icon}</MenuIconWrapper>}
{title}
</Flex>
);
}
export default React.memo<Props>(Template);
+225
View File
@@ -0,0 +1,225 @@
import { disableBodyScroll, enableBodyScroll } from "body-scroll-lock";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Portal } from "react-portal";
import { Menu } from "reakit/Menu";
import styled, { DefaultTheme } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { depths } from "@shared/styles";
import Scrollable from "~/components/Scrollable";
import useMenuContext from "~/hooks/useMenuContext";
import useMenuHeight from "~/hooks/useMenuHeight";
import usePrevious from "~/hooks/usePrevious";
import useStores from "~/hooks/useStores";
import useUnmount from "~/hooks/useUnmount";
import {
fadeIn,
fadeAndSlideUp,
fadeAndSlideDown,
mobileContextMenu,
} from "~/styles/animations";
export type Placement =
| "auto-start"
| "auto"
| "auto-end"
| "top-start"
| "top"
| "top-end"
| "right-start"
| "right"
| "right-end"
| "bottom-end"
| "bottom"
| "bottom-start"
| "left-end"
| "left"
| "left-start";
type Props = {
"aria-label": string;
visible?: boolean;
placement?: Placement;
animating?: boolean;
unstable_disclosureRef?: React.RefObject<HTMLElement | null>;
onOpen?: () => void;
onClose?: () => void;
hide?: () => void;
};
const ContextMenu: React.FC<Props> = ({
children,
onOpen,
onClose,
...rest
}) => {
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();
useUnmount(() => {
setIsMenuOpen(false);
});
React.useEffect(() => {
if (rest.visible && !previousVisible) {
if (onOpen) {
onOpen();
}
if (rest["aria-label"] !== t("Submenu")) {
setIsMenuOpen(true);
}
}
if (!rest.visible && previousVisible) {
if (onClose) {
onClose();
}
if (rest["aria-label"] !== t("Submenu")) {
setIsMenuOpen(false);
}
}
}, [
onOpen,
onClose,
previousVisible,
rest.visible,
ui.sidebarCollapsed,
setIsMenuOpen,
rest,
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;
}
// sets the menu height based on the available space between the disclosure/
// trigger and the bottom of the window
return (
<>
<Menu hideOnClickOutside 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 (
<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>
);
}}
</Menu>
{(rest.visible || rest.animating) && (
<Portal>
<Backdrop onClick={rest.hide} />
</Portal>
)}
</>
);
};
export default ContextMenu;
export const Backdrop = styled.div`
animation: ${fadeIn} 200ms ease-in-out;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: ${(props) => props.theme.backdrop};
z-index: ${depths.menu - 1};
${breakpoint("tablet")`
display: none;
`};
`;
export const Position = styled.div`
position: absolute;
z-index: ${depths.menu};
/*
* overrides make mobile-first coding style challenging
* so we explicitly define mobile breakpoint here
*/
${breakpoint("mobile", "tablet")`
position: fixed !important;
transform: none !important;
top: auto !important;
right: 8px !important;
bottom: 16px !important;
left: 8px !important;
`};
`;
type BackgroundProps = {
topAnchor?: boolean;
rightAnchor?: boolean;
theme: DefaultTheme;
};
export const Background = styled(Scrollable)<BackgroundProps>`
animation: ${mobileContextMenu} 200ms ease;
transform-origin: 50% 100%;
max-width: 100%;
background: ${(props) => props.theme.menuBackground};
border-radius: 6px;
padding: 6px 0;
min-width: 180px;
min-height: 44px;
max-height: 75vh;
pointer-events: all;
font-weight: normal;
@media print {
display: none;
}
${breakpoint("tablet")`
animation: ${(props: BackgroundProps) =>
props.topAnchor ? fadeAndSlideDown : fadeAndSlideUp} 200ms ease;
transform-origin: ${(props: BackgroundProps) =>
props.rightAnchor ? "75%" : "25%"} 0;
max-width: 276px;
background: ${(props: BackgroundProps) => props.theme.menuBackground};
box-shadow: ${(props: BackgroundProps) => props.theme.menuShadow};
`};
`;
@@ -1,23 +1,25 @@
// @flow
import copy from "copy-to-clipboard";
import * as React from "react";
import env from "~/env";
type Props = {
text: string,
children?: React.Node,
onClick?: () => void,
onCopy: () => void,
text: string;
children?: React.ReactElement;
onClick?: React.MouseEventHandler<HTMLButtonElement>;
onCopy?: () => void;
};
class CopyToClipboard extends React.PureComponent<Props> {
onClick = (ev: SyntheticEvent<>) => {
onClick = (ev: React.SyntheticEvent) => {
const { text, onCopy, children } = this.props;
const elem = React.Children.only(children);
copy(text, {
debug: process.env.NODE_ENV !== "production",
debug: env.ENVIRONMENT !== "production",
format: "text/plain",
});
if (onCopy) onCopy();
onCopy?.();
if (elem && elem.props && typeof elem.props.onClick === "function") {
elem.props.onClick(ev);
@@ -25,8 +27,12 @@ class CopyToClipboard extends React.PureComponent<Props> {
};
render() {
const { text: _text, onCopy: _onCopy, children, ...rest } = this.props;
const { text, onCopy, children, ...rest } = this.props;
const elem = React.Children.only(children);
if (!elem) {
return null;
}
return React.cloneElement(elem, { ...rest, onClick: this.onClick });
}
}
@@ -0,0 +1,104 @@
import { HomeIcon } from "outline-icons";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Optional } from "utility-types";
import CollectionIcon from "~/components/CollectionIcon";
import Flex from "~/components/Flex";
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>
> & {
onSelectCollection: (collection: string) => void;
defaultCollectionId: string | null;
};
const DefaultCollectionInputSelect = ({
onSelectCollection,
defaultCollectionId,
...rest
}: DefaultCollectionInputSelectProps) => {
const { t } = useTranslation();
const { collections } = useStores();
const [fetching, setFetching] = useState(false);
const [fetchError, setFetchError] = useState();
const { showToast } = useToasts();
React.useEffect(() => {
async function load() {
if (!collections.isLoaded && !fetching && !fetchError) {
try {
setFetching(true);
await collections.fetchPage({
limit: 100,
});
} catch (error) {
showToast(
t("Collections could not be loaded, please reload the app"),
{
type: "error",
}
);
setFetchError(error);
} finally {
setFetching(false);
}
}
}
load();
}, [showToast, fetchError, t, fetching, collections]);
const options = React.useMemo(
() =>
collections.publicCollections.reduce(
(acc, collection) => [
...acc,
{
label: (
<Flex align="center">
<IconWrapper>
<CollectionIcon collection={collection} />
</IconWrapper>
{collection.name}
</Flex>
),
value: collection.id,
},
],
[
{
label: (
<Flex align="center">
<IconWrapper>
<HomeIcon color="currentColor" />
</IconWrapper>
{t("Home")}
</Flex>
),
value: "home",
},
]
),
[collections.publicCollections, t]
);
if (fetching) {
return null;
}
return (
<InputSelect
value={defaultCollectionId ?? "home"}
options={options}
onChange={onSelectCollection}
ariaLabel={t("Default collection")}
short
{...rest}
/>
);
};
export default DefaultCollectionInputSelect;
@@ -1,12 +1,11 @@
// @flow
import * as React from "react";
type Props = {
delay?: number,
children: React.Node,
delay?: number;
children: JSX.Element;
};
export default function DelayedMount({ delay = 150, children }: Props) {
export default function DelayedMount({ delay = 250, children }: Props) {
const [isShowing, setShowing] = React.useState(false);
React.useEffect(() => {
@@ -14,7 +13,7 @@ export default function DelayedMount({ delay = 150, children }: Props) {
return () => {
clearTimeout(timeout);
};
}, []);
}, [delay]);
if (!isShowing) {
return null;
+36
View File
@@ -0,0 +1,36 @@
import { observer } from "mobx-react-lite";
import * as React from "react";
import Guide from "~/components/Guide";
import Modal from "~/components/Modal";
import useStores from "~/hooks/useStores";
function Dialogs() {
const { dialogs } = useStores();
const { guide, modalStack } = dialogs;
return (
<>
{guide ? (
<Guide
isOpen={guide.isOpen}
onRequestClose={dialogs.closeGuide}
title={guide.title}
>
{guide.content}
</Guide>
) : undefined}
{[...modalStack].map(([id, modal]) => (
<Modal
key={id}
isOpen={modal.isOpen}
isCentered={modal.isCentered}
onRequestClose={() => dialogs.closeModal(id)}
title={modal.title}
>
{modal.content}
</Modal>
))}
</>
);
}
export default observer(Dialogs);
+10
View File
@@ -0,0 +1,10 @@
import styled from "styled-components";
const Divider = styled.hr`
border: 0;
border-bottom: 1px solid ${(props) => props.theme.divider};
margin: 0;
padding: 0;
`;
export default Divider;
+134
View File
@@ -0,0 +1,134 @@
import { observer } from "mobx-react";
import { ArchiveIcon, GoToIcon, ShapesIcon, TrashIcon } from "outline-icons";
import * as React from "react";
import { useTranslation } from "react-i18next";
import styled from "styled-components";
import Document from "~/models/Document";
import Breadcrumb from "~/components/Breadcrumb";
import CollectionIcon from "~/components/CollectionIcon";
import useStores from "~/hooks/useStores";
import { MenuInternalLink, NavigationNode } from "~/types";
import { collectionUrl } from "~/utils/routeHelpers";
type Props = {
document: Document;
onlyText?: boolean;
};
function useCategory(document: Document): MenuInternalLink | null {
const { t } = useTranslation();
if (document.isDeleted) {
return {
type: "route",
icon: <TrashIcon color="currentColor" />,
title: t("Trash"),
to: "/trash",
};
}
if (document.isArchived) {
return {
type: "route",
icon: <ArchiveIcon color="currentColor" />,
title: t("Archive"),
to: "/archive",
};
}
if (document.isTemplate) {
return {
type: "route",
icon: <ShapesIcon color="currentColor" />,
title: t("Templates"),
to: "/templates",
};
}
return null;
}
const DocumentBreadcrumb: React.FC<Props> = ({
document,
children,
onlyText,
}) => {
const { collections } = useStores();
const { t } = useTranslation();
const category = useCategory(document);
const collection = collections.get(document.collectionId);
let collectionNode: MenuInternalLink;
if (collection) {
collectionNode = {
type: "route",
title: collection.name,
icon: <CollectionIcon collection={collection} expanded />,
to: collectionUrl(collection.url),
};
} else {
collectionNode = {
type: "route",
title: t("Deleted Collection"),
icon: undefined,
to: collectionUrl("deleted-collection"),
};
}
const path = React.useMemo(
() => collection?.pathToDocument?.(document.id).slice(0, -1) || [],
[collection, document]
);
const items = React.useMemo(() => {
const output = [];
if (category) {
output.push(category);
}
output.push(collectionNode);
path.forEach((node: NavigationNode) => {
output.push({
type: "route",
title: node.title,
to: node.url,
});
});
return output;
}, [path, category, collectionNode]);
if (!collections.isLoaded) {
return null;
}
if (onlyText === true) {
return (
<>
{collection?.name}
{path.map((node: NavigationNode) => (
<React.Fragment key={node.id}>
<SmallSlash />
{node.title}
</React.Fragment>
))}
</>
);
}
return <Breadcrumb items={items} children={children} highlightFirstItem />;
};
const SmallSlash = styled(GoToIcon)`
width: 12px;
height: 12px;
vertical-align: middle;
flex-shrink: 0;
fill: ${(props) => props.theme.slate};
opacity: 0.5;
`;
export default observer(DocumentBreadcrumb);
+267
View File
@@ -0,0 +1,267 @@
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { m } from "framer-motion";
import { observer } from "mobx-react";
import { CloseIcon, DocumentIcon, ClockIcon } from "outline-icons";
import { getLuminance, transparentize } from "polished";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import styled, { css } from "styled-components";
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 Text from "./Text";
import Tooltip from "./Tooltip";
type Props = {
/** The pin record */
pin: Pin | undefined;
/** The document related to the pin */
document: Document;
/** Whether the user has permission to delete or reorder the pin */
canUpdatePin?: boolean;
/** Whether this pin can be reordered by dragging */
isDraggable?: boolean;
};
function DocumentCard(props: Props) {
const { t } = useTranslation();
const { collections } = useStores();
const { document, pin, canUpdatePin, isDraggable } = props;
const collection = collections.get(document.collectionId);
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging,
} = useSortable({ id: props.document.id });
const style = {
transform: CSS.Transform.toString(transform),
transition,
};
const handleUnpin = React.useCallback(() => {
pin?.delete();
}, [pin]);
return (
<Reorderable
ref={setNodeRef}
style={style}
$isDragging={isDragging}
{...attributes}
>
<AnimatePresence
initial={{ opacity: 0, scale: 0.95 }}
animate={{
opacity: 1,
scale: 1,
transition: {
type: "spring",
bounce: 0.6,
},
}}
exit={{ opacity: 0, scale: 0.95 }}
>
<DocumentLink
dir={document.dir}
style={{
background:
collection?.color && getLuminance(collection.color) < 0.6
? collection.color
: undefined,
}}
$isDragging={isDragging}
to={{
pathname: document.url,
state: {
title: document.titleWithDefault,
},
}}
>
<Content justify="space-between" column>
{collection?.icon &&
collection?.icon !== "collection" &&
!pin?.collectionId ? (
<CollectionIcon collection={collection} color="white" />
) : (
<DocumentIcon color="white" />
)}
<div>
<Heading dir={document.dir}>{document.titleWithDefault}</Heading>
<DocumentMeta size="xsmall">
<ClockIcon color="currentColor" size={18} />{" "}
<Time dateTime={document.updatedAt} addSuffix shorten />
</DocumentMeta>
</div>
</Content>
</DocumentLink>
{canUpdatePin && (
<Actions dir={document.dir} gap={4}>
{!isDragging && pin && (
<Tooltip tooltip={t("Unpin")}>
<PinButton onClick={handleUnpin} aria-label={t("Unpin")}>
<CloseIcon color="currentColor" />
</PinButton>
</Tooltip>
)}
{isDraggable && (
<DragHandle $isDragging={isDragging} {...listeners}>
:::
</DragHandle>
)}
</Actions>
)}
</AnimatePresence>
</Reorderable>
);
}
const PinButton = styled(NudeButton)`
color: ${(props) => props.theme.white75};
&:hover,
&:active {
color: ${(props) => props.theme.white};
}
`;
const Actions = styled(Flex)`
position: absolute;
top: 12px;
right: ${(props) => (props.dir === "rtl" ? "auto" : "12px")};
left: ${(props) => (props.dir === "rtl" ? "12px" : "auto")};
opacity: 0;
transition: opacity 100ms ease-in-out;
// move actions above content
z-index: 2;
`;
const DragHandle = styled.div<{ $isDragging: boolean }>`
cursor: ${(props) => (props.$isDragging ? "grabbing" : "grab")};
padding: 0 4px;
font-weight: bold;
color: ${(props) => props.theme.white75};
line-height: 1.35;
&:hover,
&:active {
color: ${(props) => props.theme.white};
}
`;
const AnimatePresence = m.div;
const Reorderable = styled.div<{ $isDragging: boolean }>`
position: relative;
user-select: none;
border-radius: 8px;
// move above other cards when dragging
z-index: ${(props) => (props.$isDragging ? 1 : "inherit")};
transform: scale(${(props) => (props.$isDragging ? "1.025" : "1")});
box-shadow: ${(props) =>
props.$isDragging ? "0 0 20px rgba(0,0,0,0.3);" : "0 0 0 rgba(0,0,0,0)"};
&:hover ${Actions} {
opacity: 1;
}
`;
const Content = styled(Flex)`
min-width: 0;
height: 100%;
// move content above ::after
position: relative;
z-index: 1;
`;
const DocumentMeta = styled(Text)`
display: flex;
align-items: center;
gap: 2px;
color: ${(props) => transparentize(0.25, props.theme.white)};
margin: 0;
`;
const DocumentLink = styled(Link)<{
$menuOpen?: boolean;
$isDragging?: boolean;
}>`
position: relative;
display: block;
padding: 12px;
border-radius: 8px;
height: 160px;
background: ${(props) => props.theme.slate};
color: ${(props) => props.theme.white};
transition: transform 50ms ease-in-out;
&:after {
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(transparent, rgba(0, 0, 0, 0.1));
border-radius: 8px;
pointer-events: none;
}
${Actions} {
opacity: 0;
}
&:hover,
&:active,
&:focus,
&:focus-within {
${Actions} {
opacity: 1;
}
${(props) =>
!props.$isDragging &&
css`
&:after {
background: rgba(0, 0, 0, 0.1);
}
`}
}
${(props) =>
props.$menuOpen &&
css`
background: ${(props) => props.theme.listItemHoverBackground};
${Actions} {
opacity: 1;
}
`}
`;
const Heading = styled.h3`
margin-top: 0;
margin-bottom: 0.35em;
line-height: 22px;
max-height: 66px; // 3*line-height
overflow: hidden;
color: ${(props) => props.theme.white};
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
`;
export default observer(DocumentCard);
+133
View File
@@ -0,0 +1,133 @@
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 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 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 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(
{
name: "documents.latest_version",
documentId: document.id,
createdAt: document.updatedAt,
actor: document.updatedBy,
},
events
)
);
}
return eventsInDocument;
}, [eventsInDocument, events, document]);
return (
<Sidebar>
{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={<Empty>{t("Oh weird, there's nothing here")}</Empty>}
/>
</Scrollable>
</Position>
) : null}
</Sidebar>
);
}
const Position = styled(Flex)`
position: fixed;
top: 0;
bottom: 0;
width: ${(props) => props.theme.sidebarWidth}px;
`;
const Sidebar = styled(Flex)`
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: 12px;
color: ${(props) => props.theme.text};
flex-shrink: 0;
`;
export default observer(DocumentHistory);
@@ -1,149 +0,0 @@
// @flow
import ArrowKeyNavigation from "boundless-arrow-key-navigation";
import { observable, action } from "mobx";
import { observer, inject } from "mobx-react";
import * as React from "react";
import { type RouterHistory, type Match } from "react-router-dom";
import { Waypoint } from "react-waypoint";
import styled from "styled-components";
import { DEFAULT_PAGINATION_LIMIT } from "stores/BaseStore";
import DocumentsStore from "stores/DocumentsStore";
import RevisionsStore from "stores/RevisionsStore";
import Flex from "components/Flex";
import { ListPlaceholder } from "components/LoadingPlaceholder";
import Revision from "./components/Revision";
import { documentHistoryUrl } from "utils/routeHelpers";
type Props = {
match: Match,
documents: DocumentsStore,
revisions: RevisionsStore,
history: RouterHistory,
};
@observer
class DocumentHistory extends React.Component<Props> {
@observable isLoaded: boolean = false;
@observable isFetching: boolean = false;
@observable offset: number = 0;
@observable allowLoadMore: boolean = true;
async componentDidMount() {
await this.loadMoreResults();
this.selectFirstRevision();
}
fetchResults = async () => {
this.isFetching = true;
const limit = DEFAULT_PAGINATION_LIMIT;
const results = await this.props.revisions.fetchPage({
limit,
offset: this.offset,
documentId: this.props.match.params.documentSlug,
});
if (
results &&
(results.length === 0 || results.length < DEFAULT_PAGINATION_LIMIT)
) {
this.allowLoadMore = false;
} else {
this.offset += DEFAULT_PAGINATION_LIMIT;
}
this.isLoaded = true;
this.isFetching = false;
};
selectFirstRevision = () => {
if (this.revisions.length) {
const document = this.props.documents.getByUrl(
this.props.match.params.documentSlug
);
if (!document) return;
this.props.history.replace(
documentHistoryUrl(document, this.revisions[0].id)
);
}
};
@action
loadMoreResults = async () => {
// Don't paginate if there aren't more results or were in the middle of fetching
if (!this.allowLoadMore || this.isFetching) return;
await this.fetchResults();
};
get revisions() {
const document = this.props.documents.getByUrl(
this.props.match.params.documentSlug
);
if (!document) return [];
return this.props.revisions.getDocumentRevisions(document.id);
}
render() {
const document = this.props.documents.getByUrl(
this.props.match.params.documentSlug
);
const showLoading = (!this.isLoaded && this.isFetching) || !document;
return (
<Sidebar>
<Wrapper column>
{showLoading ? (
<Loading>
<ListPlaceholder count={5} />
</Loading>
) : (
<ArrowKeyNavigation
mode={ArrowKeyNavigation.mode.VERTICAL}
defaultActiveChildIndex={0}
>
{this.revisions.map((revision, index) => (
<Revision
key={revision.id}
revision={revision}
document={document}
showMenu={index !== 0}
selected={this.props.match.params.revisionId === revision.id}
/>
))}
</ArrowKeyNavigation>
)}
{this.allowLoadMore && (
<Waypoint key={this.offset} onEnter={this.loadMoreResults} />
)}
</Wrapper>
</Sidebar>
);
}
}
const Loading = styled.div`
margin: 0 16px;
`;
const Wrapper = styled(Flex)`
position: fixed;
top: 0;
right: 0;
z-index: 1;
min-width: ${(props) => props.theme.sidebarWidth};
height: 100%;
overflow-y: auto;
overscroll-behavior: none;
`;
const Sidebar = styled(Flex)`
background: ${(props) => props.theme.background};
min-width: ${(props) => props.theme.sidebarWidth};
border-left: 1px solid ${(props) => props.theme.divider};
z-index: 1;
`;
export default inject("documents", "revisions")(DocumentHistory);
@@ -1,89 +0,0 @@
// @flow
import format from "date-fns/format";
import { MoreIcon } from "outline-icons";
import * as React from "react";
import { NavLink } from "react-router-dom";
import styled, { withTheme } from "styled-components";
import Document from "models/Document";
import Revision from "models/Revision";
import Avatar from "components/Avatar";
import Flex from "components/Flex";
import Time from "components/Time";
import RevisionMenu from "menus/RevisionMenu";
import { documentHistoryUrl } from "utils/routeHelpers";
type Props = {
theme: Object,
showMenu: boolean,
selected: boolean,
document: Document,
revision: Revision,
};
class RevisionListItem extends React.Component<Props> {
render() {
const { revision, document, showMenu, selected, theme } = this.props;
return (
<StyledNavLink
to={documentHistoryUrl(document, revision.id)}
activeStyle={{ background: theme.primary, color: theme.white }}
>
<Author>
<StyledAvatar src={revision.createdBy.avatarUrl} />{" "}
{revision.createdBy.name}
</Author>
<Meta>
<Time dateTime={revision.createdAt}>
{format(revision.createdAt, "MMMM Do, YYYY h:mm a")}
</Time>
</Meta>
{showMenu && (
<StyledRevisionMenu
document={document}
revision={revision}
label={
<MoreIcon color={selected ? theme.white : theme.textTertiary} />
}
/>
)}
</StyledNavLink>
);
}
}
const StyledAvatar = styled(Avatar)`
border-color: transparent;
margin-right: 4px;
`;
const StyledRevisionMenu = styled(RevisionMenu)`
position: absolute;
right: 16px;
top: 20px;
`;
const StyledNavLink = styled(NavLink)`
color: ${(props) => props.theme.text};
display: block;
padding: 8px 16px;
font-size: 15px;
position: relative;
`;
const Author = styled(Flex)`
font-weight: 500;
padding: 0;
margin: 0;
`;
const Meta = styled.p`
font-size: 14px;
opacity: 0.75;
margin: 0 0 2px;
padding: 0;
`;
export default withTheme(RevisionListItem);
-3
View File
@@ -1,3 +0,0 @@
// @flow
import DocumentHistory from "./DocumentHistory";
export default DocumentHistory;
-25
View File
@@ -1,25 +0,0 @@
// @flow
import ArrowKeyNavigation from "boundless-arrow-key-navigation";
import * as React from "react";
import Document from "models/Document";
import DocumentPreview from "components/DocumentPreview";
type Props = {
documents: Document[],
limit?: number,
};
export default function DocumentList({ limit, documents, ...rest }: Props) {
const items = limit ? documents.splice(0, limit) : documents;
return (
<ArrowKeyNavigation
mode={ArrowKeyNavigation.mode.VERTICAL}
defaultActiveChildIndex={0}
>
{items.map((document) => (
<DocumentPreview key={document.id} document={document} {...rest} />
))}
</ArrowKeyNavigation>
);
}
+288
View File
@@ -0,0 +1,288 @@
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 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";
import Highlight from "~/components/Highlight";
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";
type Props = {
document: Document;
highlight?: string | undefined;
context?: string | undefined;
showParentDocuments?: boolean;
showCollection?: boolean;
showPublished?: boolean;
showPin?: boolean;
showDraft?: boolean;
showTemplate?: boolean;
} & CompositeStateReturn;
const SEARCH_RESULT_REGEX = /<b\b[^>]*>(.*?)<\/b>/gi;
function replaceResultMarks(tag: string) {
// don't use SEARCH_RESULT_REGEX here as it causes
// an infinite loop to trigger a regex inside it's own callback
return tag.replace(/<b\b[^>]*>(.*?)<\/b>/gi, "$1");
}
function DocumentListItem(
props: Props,
ref: React.RefObject<HTMLAnchorElement>
) {
const { t } = useTranslation();
const user = useCurrentUser();
const team = useCurrentTeam();
const [menuOpen, handleMenuOpen, handleMenuClose] = useBoolean();
const {
document,
showParentDocuments,
showCollection,
showPublished,
showPin,
showDraft = true,
showTemplate,
highlight,
context,
...rest
} = props;
const queryIsInTitle =
!!highlight &&
!!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
as={DocumentLink}
ref={ref}
dir={document.dir}
role="menuitem"
$isStarred={document.isStarred}
$menuOpen={menuOpen}
to={{
pathname: document.url,
state: {
title: document.titleWithDefault,
},
}}
{...rest}
>
<Content>
<Heading dir={document.dir}>
<Title
text={document.titleWithDefault}
highlight={highlight}
dir={document.dir}
/>
{document.isBadgedNew && document.createdBy.id !== user.id && (
<Badge yellow>{t("New")}</Badge>
)}
{canStar && (
<StarPositioner>
<StarButton document={document} />
</StarPositioner>
)}
{document.isDraft && showDraft && (
<Tooltip
tooltip={t("Only visible to you")}
delay={500}
placement="top"
>
<Badge>{t("Draft")}</Badge>
</Tooltip>
)}
{document.isTemplate && showTemplate && (
<Badge primary>{t("Template")}</Badge>
)}
</Heading>
{!queryIsInTitle && (
<ResultContext
text={context}
highlight={highlight ? SEARCH_RESULT_REGEX : undefined}
processResult={replaceResultMarks}
/>
)}
<DocumentMeta
document={document}
showCollection={showCollection}
showPublished={showPublished}
showParentDocuments={showParentDocuments}
showLastViewed
/>
</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}
onOpen={handleMenuOpen}
onClose={handleMenuClose}
modal={false}
/>
</Actions>
</CompositeItem>
);
}
const Content = styled.div`
flex-grow: 1;
flex-shrink: 1;
min-width: 0;
`;
const Actions = styled(EventBoundary)`
display: none;
align-items: center;
margin: 8px;
flex-shrink: 0;
flex-grow: 0;
${NudeButton} {
&:hover,
&[aria-expanded="true"] {
background: ${(props) => props.theme.sidebarControlHoverBackground};
}
}
${breakpoint("tablet")`
display: flex;
`};
`;
const DocumentLink = styled(Link)<{
$isStarred?: boolean;
$menuOpen?: boolean;
}>`
display: flex;
align-items: center;
margin: 10px -8px;
padding: 6px 8px;
border-radius: 8px;
max-height: 50vh;
width: calc(100vw - 8px);
&:focus-visible {
outline: none;
}
${breakpoint("tablet")`
width: auto;
`};
${Actions} {
opacity: 0;
}
${AnimatedStar} {
opacity: ${(props) => (props.$isStarred ? "1 !important" : 0)};
}
&:${hover},
&:active,
&:focus,
&:focus-within {
background: ${(props) => props.theme.listItemHoverBackground};
${Actions} {
opacity: 1;
}
${AnimatedStar} {
opacity: 0.5;
&:hover {
opacity: 1;
}
}
}
${(props) =>
props.$menuOpen &&
css`
background: ${(props) => props.theme.listItemHoverBackground};
${Actions} {
opacity: 1;
}
${AnimatedStar} {
opacity: 0.5;
}
`}
`;
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;
`;
const StarPositioner = styled(Flex)`
margin-left: 4px;
align-items: center;
`;
const Title = styled(Highlight)`
max-width: 90%;
overflow: hidden;
text-overflow: ellipsis;
`;
const ResultContext = styled(Highlight)`
display: block;
color: ${(props) => props.theme.textTertiary};
font-size: 14px;
margin-top: -0.25em;
margin-bottom: 0.25em;
`;
export default observer(React.forwardRef(DocumentListItem));

Some files were not shown because too many files have changed in this diff Show More