Compare commits

...
Author SHA1 Message Date
sriram veeraghantaandGitHub 768b4abf22 Merge pull request #3287 from makeplane/preview
promote: preview to master
2023-12-29 22:11:37 +05:30
sriram veeraghantaandGitHub 6f0af4689b Merge pull request #3286 from makeplane/develop
promote: develop to preview
2023-12-29 22:10:24 +05:30
sriram veeraghanta 22bbdd5ab8 fix: add validations 2023-12-29 22:07:52 +05:30
sriram veeraghantaandGitHub 28a9c53202 Merge pull request #3281 from makeplane/preview
release: preview to master
2023-12-29 20:28:18 +05:30
sriram veeraghantaandGitHub 33d88f56da Merge pull request #3280 from makeplane/develop
promote: develop changes to preview
2023-12-29 18:21:26 +05:30
sriram veeraghanta 23001d425f Merge branch 'preview' of github.com:makeplane/plane into develop 2023-12-29 18:16:08 +05:30
sriram veeraghantaandGitHub 5de94c575a fix: workspace invitation status fixes (#3279) 2023-12-29 17:49:39 +05:30
AbId KhAnandGitHub f200acc1e8 fix websocket connection issue in docker makeplane/plane#3195 (#3196)
* fix websocket connection issue in docker makeplane/plane#3195

* fix websocket connection issue for local env with removing from the prod nginx conf template makeplane/plane#319
2023-12-29 16:49:09 +05:30
Prateek ShouryaandGitHub f132fe59ae Chore/user role validation (#3260)
* chore: remove `Save View` option for guest/ viewer from project issues header.

* chore: allow guest/ viewer to clear applied filters in project issues.

* chore: disable `date`, `label` property access for guests/ viewer in all project issue views.

* chore: update `Workspace Issues` -> `All Issues` header.

* chore: refactor apply/ clear filter implementation in All Issues.

* Revert "chore: refactor apply/ clear filter implementation in All Issues."

This reverts commit 024822d54f.

* Revert "chore: allow guest/ viewer to clear applied filters in project issues."

This reverts commit 3dae871d23.

* Revert "chore: update `Workspace Issues` -> `All Issues` header."

This reverts commit 03f90be188.

* chore: remove `cursor-pointer` style from non actionable issue properties.
2023-12-29 16:35:03 +05:30
NikhilandGitHub e584259c04 feat: add external id and external source field to issue, cycle, module, label, comment, state and inbox issues (#3277) 2023-12-29 16:32:12 +05:30
sriram veeraghanta a77ceb636f Merge branches 'develop' and 'develop' of github.com:makeplane/plane into develop 2023-12-29 16:25:54 +05:30
10ab081a0b chore: cycle current status (#3270)
* dev: cycle status

* chore: cycle status logic updated

---------

Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
2023-12-29 15:24:07 +05:30
Anmol Singh BhatiaandGitHub 1d5a3a02c1 fix: issue parent select (#3267) 2023-12-29 15:22:30 +05:30
sriram veeraghantaandGitHub 62b9b259c0 fix: adding issue title to the activity (#3271) 2023-12-28 18:53:06 +05:30
Anmol Singh BhatiaandGitHub 91e84aede1 fix: onboarding redirection loop and bug fixes (#3250)
* chore: try and catch added in handleSignInRedirection

* chore: remove unnecessary hooks

* fix: handleCopyIssueLink url updated

* chore: swap next_url with next_path and validate redirection logic for next_path url
2023-12-28 17:17:04 +05:30
Prateek ShouryaandGitHub 71bf049e89 Style/UI improvements (#3269)
* style: update `Workspace Issues` -> `All Issues` header.

* style: fix issue activity text overflow issue.
2023-12-28 14:30:33 +05:30
sriram veeraghantaandGitHub 685e62a72f fix: replacing onclick redirections with link tag. (#3263)
* fix: adding links to dashboard summary items

* fix: adding links to workspace sidebar dropdown

* fix: adding links to the sidebar
2023-12-28 14:29:20 +05:30
sriram veeraghanta d9bd43f43c fix: adding links to the sidebar 2023-12-28 11:54:16 +05:30
sriram veeraghanta 10bdcc906c fix: adding links to workspace sidebar dropdown 2023-12-27 16:35:43 +05:30
sriram veeraghanta 54964924f0 fix: adding links to dashboard summary items 2023-12-27 16:15:56 +05:30
sriram veeraghanta ff8008cbed Merge branch 'preview' of github.com:makeplane/plane into develop 2023-12-27 15:37:03 +05:30
78428fb564 chore: estimates and issue parent id fixes (#3188)
* chore: validations and bug fixes

* chore: estimate point character limit validation

---------

Co-authored-by: LAKHAN BAHETI <lakhanbaheti9@gmail.com>
2023-12-27 15:35:15 +05:30
Bavisetti NarayanandGitHub b2824366a8 fix: external api serializer (#3259)
* fix: passed workspace id and project id as context

* fix: issue activity
2023-12-27 15:33:31 +05:30
Anmol Singh BhatiaandGitHub 05eb728c40 chore: cycle & module sidebar improvement (#3251)
* chore: no lead option added in module lead select dropdown

* chore: module lead select dropdown code refactor

* chore: cycle sidebar improvement

* chore: module sidebar improvement

* style: cycle and module sidebar improvement

* style: app sidebar improvement
2023-12-27 15:16:13 +05:30
sriram veeraghantaandGitHub ad2471c5a7 Merge pull request #3258 from makeplane/develop
fix: adding access token to build Pr (#3257)
2023-12-26 19:00:10 +05:30
sriram veeraghantaandGitHub 440cfc0f20 fix: adding access token to build Pr (#3257) 2023-12-26 18:59:24 +05:30
sriram veeraghantaandGitHub 9a32d722dc Merge pull request #3256 from makeplane/develop
promote: develop to preview
2023-12-26 18:22:04 +05:30
sriram veeraghantaandGitHub 37fe9a185c fix: adding token to the build pr workflow (#3254)
* fix: adding token to the build pr workflow

* fix: using automatic github token
2023-12-26 18:13:13 +05:30
sriram veeraghanta eabb31a764 fix: upgrading turbo repo changes 2023-12-26 17:04:59 +05:30
sriram veeraghanta 1e27c7936d fix: eslint dependencies fixes 2023-12-26 17:03:43 +05:30
M. PalanikannanandGitHub 0a617eec26 🔧 fix: Pages mutation on component mount (#3230)
* 🔧 chore: Update revalidate option and add useEffect hook in PageDetailsPage component

- Set the `revalidate` option to `false` in the `commonSwrOptions` object.
- Add an `useEffect` hook that calls the `mutatePageDetails` function with specific options.
- Inside the `useEffect` hook, set `revalidate` to `true`, `populateCache` to `true`, and define a rollback function for error handling.
- If an error occurs during the rollback, display an error alert message using the `actionCompleteAlert` function.
- In the `updatePage` function, ensure that `workspaceSlug`, `projectId`, and `pageId` are all defined before proceeding.

* ♻️ refactor: Update code styling for inline code in CoreEditorExtensions

In the `packages/editor/core/src/ui/extensions/index.tsx` file, the code for inline code styling in the CoreEditorExtensions component has been updated. Previously, it was set to `false`, but now it is defined as an object with specific HTML attributes. The code styling includes a rounded-md background, custom primary color, margin, padding, font styling, and disabling spellcheck. This change improves the visual appearance and readability of inline code elements in the editor.
2023-12-26 16:45:00 +05:30
sriram veeraghantaandGitHub ad20079e0c Merge pull request #3249 from makeplane/develop
promote: moving stable changes from develop to preview
2023-12-26 14:25:01 +05:30
Lakhan BahetiandGitHub e14baf17a7 style: create webhook page to modal (#3223)
* style: create webhook page to modal

* fix: create page removed

* fix: auto modal close on empty state

* fix: secret key heading removed from generated modal
2023-12-26 13:28:47 +05:30
Anmol Singh BhatiaandGitHub 542b18a585 fix: custom theme validation added (#3246) 2023-12-26 13:11:59 +05:30
sriram veeraghantaandGitHub 37d88cc05b Merge pull request #3233 from makeplane/fix/types-slash-command
fix: Fixed types for slash commands by inspecting generics
2023-12-22 19:02:20 +05:30
Palanikannan1437 b652d1a8f1 fix: Fixed types for slash commands by inspecting generics 2023-12-22 18:52:00 +05:30
sriram veeraghanta 98b7a941f9 fix: yarn lock fixes 2023-12-22 18:37:14 +05:30
sriram veeraghantaandGitHub dc131ee05b Merge pull request #3232 from makeplane/release-0.15
fix: moving patch fixes from release 0.15 to 0.14.2
2023-12-22 18:19:47 +05:30
M. Palanikannanandsriram veeraghanta 0e3d15215d [fix] Image insertion position at cursor position and Updated placeholder text. (#3224)
* Fix position bug in the UploadImagesPlugin widget decoration and adjust transaction to correctly insert image node and set meta data for image removal.

* Update CSS styles in editor.css to remove margin top and bottom on images and img placeholders and adjust the margin on the table in the editor container.

* Better typescript support for images extension.

Update the `Command` extension in `slash-commands.tsx` to include a `SlashCommandOptions` type for better TS support and allow spaces in the suggestion options and modify the `image` suggestion's search terms to include "img" in addition to "photo", "picture", and "media".
2023-12-22 18:10:21 +05:30
Lakhan Bahetiandsriram veeraghanta 816b6abf3b chore: allow non-latin characters to project identifier (#3226) 2023-12-22 18:10:21 +05:30
Lakhan Bahetiandsriram veeraghanta 6ecaa661a7 style: email placeholder changed across the platform (#3206)
* style: email placeholder changed across the platform

* fix: placeholder text
2023-12-22 18:10:21 +05:30
M. Palanikannanandsriram veeraghanta 0b1efb173f [refactor] Editor code refactoring (#3194)
* removed relative imports from editor core

* Update issue widget file paths and imports to use kebab case instead of camel case, to align with coding conventions and improve consistency.

* Update Tiptap core and extensions versions to 2.1.13 and Tiptap React version to 2.1.13. Update Tiptap table imports to use the new location in package @tiptap/pm/tables. Update AlertLabel component to use the new type definition for LucideIcon.

* updated lock file

* removed default exports from editor/core

* fixed injecting css into the core package itself

* seperated css code to have single source of origin wrt to the package

* removed default imports from document editor

* all instances using index as key while mapping fixed

* Update Lite Text Editor package.json to remove @plane/editor-types as a dependency.

Update Lite Text Editor index.ts to update the import of IMentionSuggestion and IMentionHighlight from @plane/editor-types to @plane/editor-core.

Update Lite Text Editor ui/index.tsx to update the import of UploadImage, DeleteImage, IMentionSuggestion, and RestoreImage from @plane/editor-types to @plane/editor-core.

Update Lite Text Editor ui/menus/fixed-menu/index.tsx to update the import of UploadImage from @plane/editor-types to @plane/editor-core.

Update turbo.json to remove @plane/editor-types#build as a dependency for @plane/lite-text-editor#build, @plane/rich-text-editor#build, and @plane/document-editor#build.

* Remove deprecated import and adjust tippy.js usage in the slash-commands.tsx file of the editor extensions package.

* Update dependencies in `rich-text-editor/package.json`, remove `@plane/editor-types` and add `@plane/editor-core` in `rich-text-editor/src/index.ts`, and update imports in `rich-text-editor/src/ui/extensions/index.tsx` and `rich-text-editor/src/ui/index.tsx` to use `@plane/editor-core` instead of `@plane/editor-types`.

* Update package.json dependencies and add new types for image deletion, upload, restore, mention highlight, mention suggestion, and slash command item.

* Update import statements in various files to use the new package "@plane/editor-core" instead of "@plane/editor-types".

* fixed document editor to follow conventions

* Refactor imports in the Rich Text Editor package to use relative paths instead of absolute paths.

- Updated imports in `index.ts`, `ui/index.tsx`, and `ui/menus/bubble-menu/index.tsx` to use relative paths.
- Updated `tsconfig.json` to include the `baseUrl` compiler option and adjust the `include` and `exclude` paths.

* Refactor Lite Text Editor code to use relative import paths instead of absolute import paths.

* Added LucideIconType to the exports in index.ts for use in other files.
Created a new file lucide-icon.ts which contains the type LucideIconType.
Updated the icon type in HeadingOneItem in menu-items/index.tsx to use LucideIconType.
Updated the Icon type in AlertLabel in alert-label.tsx to use LucideIconType.
Updated the Icon type in VerticalDropdownItemProps in vertical-dropdown-menu.tsx to use LucideIconType.
Updated the Icon type in BubbleMenuItem in fixed-menu/index.tsx to use LucideIconType.
Deleted the file tooltip.tsx since it is no longer used.
Updated the Icon type in BubbleMenuItem in bubble-menu/index.tsx to use LucideIconType.

* ♻️ refactor: simplify rendering logic in slash-commands.tsx

The rendering logic in the file "slash-commands.tsx" has been simplified. Previously, the code used inline positioning for the popup, but it has now been removed. Instead of appending the popup to the document body, it is now appended to the element with the ID "tiptap-container". The "flip" option has also been removed. These changes have improved the readability and maintainability of the code.

* fixed build errors caused due to core's internal imports

* regression: fixed pages not saving issue and not duplicating with proper content issue

* build: Update @tiptap dependencies

Updated the @tiptap dependencies in the package.json files of `document-editor`, `extensions`, and `rich-text-editor` packages to version 2.1.13.

* 🚑 fix: Correct appendTo selector in slash-commands.tsx

Update the `appendTo` function call in `slash-commands.tsx` to use the correct selector `#editor-container` instead of `#tiptap-container`. This ensures that the component is appended to the appropriate container in the editor extension.

Note: The commit message assumes that the change is a fix for an issue or error. If it's not a fix, please provide more context so that an appropriate commit type can be determined.
2023-12-22 18:10:18 +05:30
Lakhan Bahetiandsriram veeraghanta aceee7d2e2 fix: bugs & improvements (#3189)
* fix: workspace invitation modal form values reset

* fix: profile sidebar avatar letter
2023-12-22 18:09:41 +05:30
Anmol Singh Bhatiaandsriram veeraghanta 0a41eff435 chore: bug fixes & improvement (#3218)
* chore: draft issue validation added to prevent saving empty or whitespace title

* chore: resolve scrolling issue in page empty state

* chore: kanban layout quick add issue improvement
2023-12-22 18:09:41 +05:30
Prateek Shouryaandsriram veeraghanta 5f681973a0 style: instance admin email settings ui & ux update. (#3186) 2023-12-22 18:09:41 +05:30
9c65657a66 fix - file size limit not work on plane.settings.production (#3160)
* fix - file size limit not work on plane.settings.production

* fix - file size limit not work on plane.settings.production

* fix - file size limit not work on plane.settings.production, move to common.py

---------

Co-authored-by: luanduongtel4vn <hoangluan@tel4vn.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
2023-12-22 18:09:39 +05:30
Manish Guptaandsriram veeraghanta 6fab75f9ab fix: branch build fix (#3214)
* branch build fix for release-* in case of space,backend,proxy

* fixes
2023-12-22 18:08:36 +05:30
sriram veeraghantaandGitHub 111070bdb9 Merge pull request #3231 from makeplane/release-0.14.2
fix: branch build custom docker repo with suffix (#3182)
2023-12-22 17:49:25 +05:30
David ChiangandGitHub d76840ff6f Fix spelling error in setting-label-list.tsx (#3210) 2023-12-22 17:24:02 +05:30
sriram veeraghantaandGitHub d4b6f4faf1 Merge pull request #3227 from makeplane/develop
fix: posthog events trigger in staging (#3220)
2023-12-22 14:05:51 +05:30
Ramesh Kumar ChandraandGitHub fe9519314a fix: posthog events trigger in staging (#3220)
* fix: posthog events trigger in staging

* refactor: cleared comment lines for warnings, added dependancy values

* refactor: removed unnecessary dependency
2023-12-22 14:05:17 +05:30
M. PalanikannanandGitHub e141091e99 fix: Resolved page not saving/not copying contents bug (#3203)
This commit adds a duplicate_page function to the PageDetailsPage component, which allows users to duplicate a page. If the current page does not have a description_html value, it will be set to the default value from the pageDetails object. The formData object is updated with the necessary values for duplication, including the new page name and description. Additionally, the handleSubmit dependency is included in the useEffect hook to ensure proper form submission.
2023-12-20 18:54:16 +05:30
Lakhan BahetiandGitHub 40b8b0ac35 fix: role authorization for create project button in project empty state (#3204) 2023-12-20 18:53:35 +05:30
Manish GuptaandGitHub 47d6b152a0 branch build custom docker repo with suffix (#3182) 2023-12-20 16:58:04 +05:30
sriram veeraghanta 216a7c8fda fix: adding additional headers to restrict iframe 2023-12-20 13:49:17 +05:30
sriram veeraghantaandGitHub e7468292c7 Merge pull request #3175 from makeplane/preview
release: moving changes from preview to master
2023-12-18 19:29:43 +05:30
Anmol Singh BhatiaandGitHub 7bff8d2ec5 chore: cycle and module sidebar mutation fix (#3174)
* chore: issue action cycle sidebar mutation fix

* chore: issue action module sidebar mutation fix
2023-12-18 19:01:10 +05:30
sriram veeraghantaandGitHub 6f2cce081f Merge pull request #3171 from makeplane/develop
Promote: develop change to preview
2023-12-18 15:37:53 +05:30
sriram veeraghantaandGitHub a86dafc11c Merge pull request #3170 from makeplane/preview
sync: moving contributions from preview to develop
2023-12-18 15:25:34 +05:30
Aaryan KhandelwalandGitHub 81256d6373 chore: add tooltips to issue properties with no value (#3169)
* chore: add tolltips to properties with no value

* chore: update property types
2023-12-18 15:17:38 +05:30
Lakhan BahetiandGitHub c9792da4a1 fix: bug fixes & improvements (#3159)
* fix: on issue update updates_on not updating

* fix: on project change cycle update

* fix: update issue
2023-12-18 14:59:25 +05:30
Prateek ShouryaandGitHub 37df0bcdd8 fix: issue with peek view properties not editable and options not being shown in all workspace issues. (#3100)
* fix: issue with peek view properties not editable and options not being shown in `all workspace issues`..

* refactor: use projectId from props instead of router query.
fix: issue in add to module/ cycle not working properly.
2023-12-18 14:47:40 +05:30
Prateek ShouryaandGitHub 18c86bd8cc chore: add email from address in Instance Admin Email Settings. (#3155) 2023-12-18 13:36:09 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0ee6c20272 chore(deps): bump cryptography in /apiserver/requirements (#3166)
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.5 to 41.0.6.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.5...41.0.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-18 13:26:21 +05:30
Prateek ShouryaandGitHub 184db0156c User role validation across workspace and projects. (#3167)
* chore: remove `add link` button for guests & viewer in modules sidebar.

* chore: remove `+` (add view) icon for guests & viewer in `All Issues`.

* chore: remove `Start Project` button from Dashboard & Projects empty state for guests & viewers.

* chore: project level user role validation for empty states.
2023-12-18 13:25:03 +05:30
NikhilandGitHub b7a0f3c693 fix: project cover list endpoint (#3168) 2023-12-18 13:19:04 +05:30
Ikko Eltociear AshimineandGitHub e40f38e2e1 fix: typo in install.sh (#3136)
availabe -> available
2023-12-18 12:17:15 +05:30
Lakhan BahetiandGitHub 05e7afab8d fix: issue peek-overview delete functionality (#3134)
* fix: peek-overview delete issue

* refactor: removed unused variables
2023-12-18 12:14:57 +05:30
969a51f425 chore: issue click & peek overview improvement (#3157)
* improve issue popover to detect outside click

* chore: stopPropagation event added to prevent peekoverview triggering in action menu & issue properties

* chore: stopPropagation event added to prevent peekoverview triggering in issue properties

* chore: enable entire issue card clickability in list and kanban layout, introduce control-click functionality
to open issues in new tabs

* chore: build error fix and unused variable removed

* chore: build error fix

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
2023-12-18 12:11:14 +05:30
sriram veeraghantaandGitHub 849bc92aea Merge pull request #3121 from notpushkin/patch-1
Fix .vertical-lr in Firefox
2023-12-18 01:11:31 +05:30
Lakhan BahetiandGitHub a37dec45d9 chore: made project-identifier rule consistent (#3148) 2023-12-17 00:39:23 +05:30
Lakhan BahetiandGitHub e1793dda74 chore: role restriction to issue detail & peek-overview (#3146)
* chore: disabled interaction with title & description in peekview & issue detail

* chore: restriction to attachments delete for lower roles

* chore: kanban & calendar block drag restriction for lower roles

* fix: module/issue sidebar links access for lower roles

* fix: issue detail role validation

* fix: user role validation condition
2023-12-17 00:38:05 +05:30
Anmol Singh BhatiaandGitHub 31fdaf2659 fix: project members fetch fix (#3145)
* chore: all issues assignee fetch fix

* chore: assignee fetch logic updated
2023-12-17 00:36:56 +05:30
Aaryan KhandelwalandGitHub 8a1a6c6f62 chore: disable API calls for un-authorized users (#3144)
* fix: disable api calls if user doesn't have access

* chore: remove permissions from component level

* chore: rmeove console log and organize import statements
2023-12-17 00:35:53 +05:30
Prateek ShouryaandGitHub 3d83101f69 fix: issue with cycle and module sidebar filter implementation. (#3142) 2023-12-17 00:34:42 +05:30
Lakhan BahetiandGitHub d473ba9d0d fix: create issue project ID (#3131) 2023-12-17 00:32:00 +05:30
Aaryan KhandelwalandGitHub e5902152ab fix: overflow issues in the profile settings layout (#3163) 2023-12-17 00:21:03 +05:30
sriram veeraghantaandGitHub f03a9a6de8 fix: sync changes (#3156)
* fix: sync changes

* fix: sync changes

* fix: sync changes updated
2023-12-15 18:12:16 +05:30
Anmol Singh BhatiaandGitHub b7e2f1e57a chore: resolve priority sorting order (#3141) 2023-12-15 17:37:37 +05:30
sriram veeraghantaandGitHub 885de6f679 fix: sync changes (#3154) 2023-12-15 17:36:26 +05:30
sriram veeraghantaandGitHub ce9714ff12 fix: sync pr changes (#3153) 2023-12-15 17:31:14 +05:30
sriram veeraghantaandGitHub 74b141eea2 fix: sync changes (#3152) 2023-12-15 17:24:24 +05:30
sriram veeraghantaandGitHub 08425c9614 fix: sync changes (#3151) 2023-12-15 17:21:06 +05:30
sriram veeraghantaandGitHub ecfcc03ef0 fix: removing unneccessary checks (#3150) 2023-12-15 17:12:57 +05:30
sriram veeraghantaandGitHub 829c08f0ee fix: making changes to sync job (#3149) 2023-12-15 17:08:37 +05:30
Anmol Singh BhatiaandGitHub 2edd2d947e chore: implement validation for accepting 'http://' and 'https://' url in link modal (#3147) 2023-12-15 16:39:32 +05:30
Aaryan KhandelwalandGitHub 5b67f27345 fix: remove get requests from the catch block (#3135)
* fix: refetching project filters on error

* fix: get request in the catch block
2023-12-14 19:55:45 +05:30
Anmol Singh BhatiaandGitHub 7684a2c091 chore: sidebar quick action improvement (#3133) 2023-12-14 17:24:42 +05:30
Lakhan BahetiandGitHub 4e2bf24e8d chore: filter edit operation in views is disabled for lower roles (#3113)
* chore: edit/delete view options hidden for lower roles

* chore: project -> views access restriction for lower roles

* refactor: allowance condition
2023-12-14 16:49:36 +05:30
Anmol Singh BhatiaandGitHub aafac9ed1d chore: state sequence ordering (#3130) 2023-12-14 16:45:39 +05:30
Prateek ShouryaandGitHub 3adf48e429 chore: add new or existing issues validation for guest & viewers in cycles and modules empty state. (#3126) 2023-12-14 16:31:57 +05:30
Lakhan BahetiandGitHub 1c546e3cc5 fix: cycle & module sidebar date range picker (#3127)
* fix: cycle sidebar date range picker

* chore: cycle sidebar hover pointer

* fix: module sidebar date range picker

* fix: module sidebar state select popover pointer
2023-12-14 16:31:39 +05:30
5c7382d894 fix: environment file missing for space (#3105)
* fix: environment file missing for space

* dev: remove container name from the docker-compose local

* dockerfile.dev modified for volumes

* local dev fixes

---------

Co-authored-by: Manish Gupta <manish@mgupta.me>
2023-12-14 16:18:02 +05:30
Bavisetti NarayanandGitHub 1f8ae3a5ad chore: project member list (#3087) 2023-12-14 16:14:50 +05:30
Bavisetti NarayanandGitHub f1ed0c979c chore: workspace project reinvite (#3112)
* chore: user can rejoin a project by invite

* chore: workspace member leave
2023-12-14 16:14:12 +05:30
Bavisetti NarayanandGitHub 78b29eb81b chore: resolved the use tls error (#3114) 2023-12-14 16:11:46 +05:30
Anmol Singh BhatiaandGitHub 8d3a0a2eec fix: build error (#3128) 2023-12-14 16:07:53 +05:30
sriram veeraghanta 910d1a1de3 Merge branch 'preview' of github.com:makeplane/plane into develop 2023-12-13 23:18:09 +05:30
Ehtesham SiddiquiandGitHub 6004f29bbc Fix: update self-host docs link in README (#3109)
* Fix: update self-host docs link

* fix: update readme.md to link to self-hosting docker compose
2023-12-13 23:11:48 +05:30
Lakhan BahetiandGitHub 9d0056cfee fix: spreadsheet layout sub-issues property update (#3110)
* fix: spreadsheet subissues property update

* fix: hover effect for sub-issues

* refactor: mutate sub-issues
2023-12-13 23:07:26 +05:30
Lakhan BahetiandGitHub 4bb99d5fbf fix: cycle delete & active cycle loading (#3088) 2023-12-13 23:06:38 +05:30
Anmol Singh BhatiaandGitHub 6c61fbd102 chore: guest user profile access-related problem (#3089)
* fix: resolve guest user profile access-related problem

* chore: header and app sidebar permission validation added
2023-12-13 23:05:50 +05:30
Anmol Singh BhatiaandGitHub 2605b938f0 chore: empty state action button validation (#3094) 2023-12-13 23:05:23 +05:30
Anmol Singh BhatiaandGitHub b4f51cb5af chore: cycle and module sidebar permission validation (#3095) 2023-12-13 23:05:02 +05:30
Anmol Singh BhatiaandGitHub fe80ca3e1c chore: issue sidebar and project view improvement and validation (#3098)
* chore: project view header button validation

* chore: copy view link option added in project view list item and role action validation added

* chore: issue sidebar improvement
2023-12-13 23:04:33 +05:30
Anmol Singh BhatiaandGitHub b78e83d81b chore: image file update, icon consistency, bug fixes and code refactor (#3107)
* chore: workspace view icon consistency

* chore: icon added in breadcrumb dropdown

* chore: svg image replaced with webp

* fix: build fix

* chore: unused variables removed

* chore: module sidebar copy module link fix
2023-12-13 23:03:54 +05:30
sriram veeraghantaandGitHub ee68c3ae86 Merge pull request #3111 from makeplane/chore/calendar_layout_improvement
chore: calendar layout improvement
2023-12-13 23:03:07 +05:30
sriram veeraghantaandGitHub 239f68e260 Merge pull request #3117 from makeplane/chore/issue_related_bug_and_improvement
chore: issue details related bug fixes and improvement
2023-12-13 23:01:19 +05:30
sriram veeraghantaandGitHub f949d57fa0 Merge pull request #3119 from makeplane/chore/analytics_permission_validation
chore: analytics permission validation added
2023-12-13 23:00:05 +05:30
Alexander PushkovandGitHub dadd2cf39b Fix .vertical-lr in Firefox 2023-12-13 19:04:12 +03:00
Anmol Singh Bhatia 13d7832d35 chore: app sidebar quick action permission validation added 2023-12-13 20:32:39 +05:30
Anmol Singh Bhatia 0f892d4670 chore: analytics permission validation added 2023-12-13 20:15:50 +05:30
Anmol Singh Bhatia e8945f244d chore: remove parent option added in issue sidebar and peek overview 2023-12-13 19:29:49 +05:30
Anmol Singh Bhatia a0588be405 chore: remove parent option added in issue sidebar and peek overview 2023-12-13 18:57:50 +05:30
Anmol Singh Bhatia 29a0ba4ddc chore: sub issue propery permission validation 2023-12-13 18:40:46 +05:30
Anmol Singh Bhatia 644073f063 chore: issue detail page title and indicator improvement 2023-12-13 18:32:21 +05:30
Anmol Singh Bhatia 63a15f2bf9 chore: calendar layout day tile improvement 2023-12-13 14:48:42 +05:30
390 changed files with 3597 additions and 4721 deletions
+13 -12
View File
@@ -9,6 +9,7 @@ on:
- preview
- qa
- develop
- release-*
release:
types: [released, prereleased]
@@ -62,14 +63,14 @@ jobs:
runs-on: ubuntu-20.04
needs: [branch_build_setup]
env:
FRONTEND_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend:${{ needs.branch_build_setup.outputs.gh_branch_name }}
FRONTEND_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ needs.branch_build_setup.outputs.gh_branch_name }}
steps:
- name: Set Frontend Docker Tag
run: |
if [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ] && [ "${{ github.event_name }}" == "release" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend:${{ github.event.release.tag_name }}
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ github.event.release.tag_name }}
elif [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend:stable
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-frontend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:stable
else
TAG=${{ env.FRONTEND_TAG }}
fi
@@ -104,14 +105,14 @@ jobs:
runs-on: ubuntu-20.04
needs: [branch_build_setup]
env:
SPACE_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-space:${{ needs.branch_build_setup.outputs.gh_branch_name }}
SPACE_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-space${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ needs.branch_build_setup.outputs.gh_branch_name }}
steps:
- name: Set Space Docker Tag
run: |
if [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ] && [ "${{ github.event_name }}" == "release" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-space:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-space:${{ github.event.release.tag_name }}
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-space${{ secrets.DOCKER_REPO_SUFFIX || '' }}:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-space${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ github.event.release.tag_name }}
elif [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-space:stable
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-space${{ secrets.DOCKER_REPO_SUFFIX || '' }}:stable
else
TAG=${{ env.SPACE_TAG }}
fi
@@ -146,14 +147,14 @@ jobs:
runs-on: ubuntu-20.04
needs: [branch_build_setup]
env:
BACKEND_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-backend:${{ needs.branch_build_setup.outputs.gh_branch_name }}
BACKEND_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-backend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ needs.branch_build_setup.outputs.gh_branch_name }}
steps:
- name: Set Backend Docker Tag
run: |
if [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ] && [ "${{ github.event_name }}" == "release" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-backend:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-backend:${{ github.event.release.tag_name }}
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-backend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-backend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ github.event.release.tag_name }}
elif [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-backend:stable
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-backend${{ secrets.DOCKER_REPO_SUFFIX || '' }}:stable
else
TAG=${{ env.BACKEND_TAG }}
fi
@@ -188,14 +189,14 @@ jobs:
runs-on: ubuntu-20.04
needs: [branch_build_setup]
env:
PROXY_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy:${{ needs.branch_build_setup.outputs.gh_branch_name }}
PROXY_TAG: ${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ needs.branch_build_setup.outputs.gh_branch_name }}
steps:
- name: Set Proxy Docker Tag
run: |
if [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ] && [ "${{ github.event_name }}" == "release" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy:${{ github.event.release.tag_name }}
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy${{ secrets.DOCKER_REPO_SUFFIX || '' }}:latest,${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy${{ secrets.DOCKER_REPO_SUFFIX || '' }}:${{ github.event.release.tag_name }}
elif [ "${{ needs.branch_build_setup.outputs.gh_branch_name }}" == "master" ]; then
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy:stable
TAG=${{ secrets.DOCKERHUB_USERNAME }}/plane-proxy${{ secrets.DOCKER_REPO_SUFFIX || '' }}:stable
else
TAG=${{ env.PROXY_TAG }}
fi
@@ -1,6 +1,6 @@
name: Build Pull Request Contents
on:
on:
pull_request:
types: ["opened", "synchronize"]
@@ -14,13 +14,15 @@ jobs:
steps:
- name: Checkout Repository to Actions
uses: actions/checkout@v3.3.0
with:
token: ${{ secrets.ACCESS_TOKEN }}
- name: Setup Node.js 18.x
uses: actions/setup-node@v2
with:
node-version: 18.x
cache: 'yarn'
cache: "yarn"
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v38
@@ -44,5 +46,3 @@ jobs:
run: |
yarn
yarn build --filter=space
+9 -42
View File
@@ -1,11 +1,13 @@
name: Create PR in Plane EE Repository to sync the changes
name: Create Sync Action
on:
pull_request:
branches:
- master
- preview
types:
- closed
env:
SOURCE_BRANCH_NAME: ${{github.event.pull_request.base.ref}}
jobs:
create_pr:
@@ -16,27 +18,13 @@ jobs:
pull-requests: write
contents: read
steps:
- name: Check SOURCE_REPO
id: check_repo
env:
SOURCE_REPO: ${{ secrets.SOURCE_REPO_NAME }}
run: |
echo "::set-output name=is_correct_repo::$(if [[ "$SOURCE_REPO" == "makeplane/plane" ]]; then echo 'true'; else echo 'false'; fi)"
- name: Checkout Code
if: steps.check_repo.outputs.is_correct_repo == 'true'
uses: actions/checkout@v2
with:
persist-credentials: false
fetch-depth: 0
- name: Set up Branch Name
if: steps.check_repo.outputs.is_correct_repo == 'true'
run: |
echo "SOURCE_BRANCH_NAME=${{ github.head_ref }}" >> $GITHUB_ENV
- name: Setup GH CLI
if: steps.check_repo.outputs.is_correct_repo == 'true'
run: |
type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
@@ -45,35 +33,14 @@ jobs:
sudo apt update
sudo apt install gh -y
- name: Create Pull Request
if: steps.check_repo.outputs.is_correct_repo == 'true'
- name: Push Changes to Target Repo
env:
GH_TOKEN: ${{ secrets.ACCESS_TOKEN }}
run: |
TARGET_REPO="${{ secrets.TARGET_REPO_NAME }}"
TARGET_BRANCH="${{ secrets.TARGET_REPO_BRANCH }}"
TARGET_REPO="${{ secrets.SYNC_TARGET_REPO_NAME }}"
TARGET_BRANCH="${{ secrets.SYNC_TARGET_BRANCH_NAME }}"
SOURCE_BRANCH="${{ env.SOURCE_BRANCH_NAME }}"
git checkout $SOURCE_BRANCH
git remote add target "https://$GH_TOKEN@github.com/$TARGET_REPO.git"
git push target $SOURCE_BRANCH:$SOURCE_BRANCH
PR_TITLE="${{ github.event.pull_request.title }}"
PR_BODY="${{ github.event.pull_request.body }}"
# Remove double quotes
PR_TITLE_CLEANED="${PR_TITLE//\"/}"
PR_BODY_CLEANED="${PR_BODY//\"/}"
# Construct PR_BODY_CONTENT using a here-document
PR_BODY_CONTENT=$(cat <<EOF
$PR_BODY_CLEANED
EOF
)
gh pr create \
--base $TARGET_BRANCH \
--head $SOURCE_BRANCH \
--title "[SYNC] $PR_TITLE_CLEANED" \
--body "$PR_BODY_CONTENT" \
--repo $TARGET_REPO
git remote add target-origin "https://$GH_TOKEN@github.com/$TARGET_REPO.git"
git push target-origin $SOURCE_BRANCH:$TARGET_BRANCH
+4 -25
View File
@@ -33,8 +33,8 @@ The backend is a django project which is kept inside apiserver
1. Clone the repo
```bash
git clone https://github.com/makeplane/plane
cd plane
git clone https://github.com/makeplane/plane.git [folder-name]
cd [folder-name]
chmod +x setup.sh
```
@@ -44,33 +44,12 @@ chmod +x setup.sh
./setup.sh
```
3. Define `NEXT_PUBLIC_API_BASE_URL=http://localhost` in **web/.env** and **space/.env** file
3. Start the containers
```bash
echo "\nNEXT_PUBLIC_API_BASE_URL=http://localhost\n" >> ./web/.env
docker compose -f docker-compose-local.yml up
```
```bash
echo "\nNEXT_PUBLIC_API_BASE_URL=http://localhost\n" >> ./space/.env
```
4. Run Docker compose up
```bash
docker compose up -d
```
5. Install dependencies
```bash
yarn install
```
6. Run the web app in development mode
```bash
yarn dev
```
## Missing a Feature?
+2 -2
View File
@@ -37,7 +37,7 @@ Meet [Plane](https://plane.so). An open-source software development tool to mana
> Plane is still in its early days, not everything will be perfect yet, and hiccups may happen. Please let us know of any suggestions, ideas, or bugs that you encounter on our [Discord](https://discord.com/invite/A92xrEGCge) or GitHub issues, and we will use your feedback to improve on our upcoming releases.
The easiest way to get started with Plane is by creating a [Plane Cloud](https://app.plane.so) account. Plane Cloud offers a hosted solution for Plane. If you prefer to self-host Plane, please refer to our [deployment documentation](https://docs.plane.so/self-hosting).
The easiest way to get started with Plane is by creating a [Plane Cloud](https://app.plane.so) account. Plane Cloud offers a hosted solution for Plane. If you prefer to self-host Plane, please refer to our [deployment documentation](https://docs.plane.so/self-hosting/docker-compose).
## ⚡️ Contributors Quick Start
@@ -63,7 +63,7 @@ Thats it!
## 🍙 Self Hosting
For self hosting environment setup, visit the [Self Hosting](https://docs.plane.so/self-hosting) documentation page
For self hosting environment setup, visit the [Self Hosting](https://docs.plane.so/self-hosting/docker-compose) documentation page
## 🚀 Features
+1 -1
View File
@@ -49,5 +49,5 @@ USER captain
# Expose container port and run entry point script
EXPOSE 8000
# CMD [ "./bin/takeoff" ]
CMD [ "./bin/takeoff.local" ]
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
set -e
python manage.py wait_for_db
python manage.py migrate
# Create the default bucket
#!/bin/bash
# Collect system information
HOSTNAME=$(hostname)
MAC_ADDRESS=$(ip link show | awk '/ether/ {print $2}' | head -n 1)
CPU_INFO=$(cat /proc/cpuinfo)
MEMORY_INFO=$(free -h)
DISK_INFO=$(df -h)
# Concatenate information and compute SHA-256 hash
SIGNATURE=$(echo "$HOSTNAME$MAC_ADDRESS$CPU_INFO$MEMORY_INFO$DISK_INFO" | sha256sum | awk '{print $1}')
# Export the variables
export MACHINE_SIGNATURE=$SIGNATURE
# Register instance
python manage.py register_instance $MACHINE_SIGNATURE
# Load the configuration variable
python manage.py configure_instance
# Create the default bucket
python manage.py create_bucket
python manage.py runserver 0.0.0.0:8000 --settings=plane.settings.local
+2 -2
View File
@@ -96,7 +96,7 @@ class IssueSerializer(BaseSerializer):
if (
data.get("state")
and not State.objects.filter(
project_id=self.context.get("project_id"), pk=data.get("state")
project_id=self.context.get("project_id"), pk=data.get("state").id
).exists()
):
raise serializers.ValidationError(
@@ -107,7 +107,7 @@ class IssueSerializer(BaseSerializer):
if (
data.get("parent")
and not Issue.objects.filter(
workspace_id=self.context.get("workspace_id"), pk=data.get("parent")
workspace_id=self.context.get("workspace_id"), pk=data.get("parent").id
).exists()
):
raise serializers.ValidationError(
+7 -7
View File
@@ -65,18 +65,18 @@ class ModuleSerializer(BaseSerializer):
def create(self, validated_data):
members = validated_data.pop("members", None)
project = self.context["project"]
module = Module.objects.create(**validated_data, project=project)
project_id = self.context["project_id"]
workspace_id = self.context["workspace_id"]
module = Module.objects.create(**validated_data, project_id=project_id)
if members is not None:
ModuleMember.objects.bulk_create(
[
ModuleMember(
module=module,
member=member,
project=project,
workspace=project.workspace,
member_id=str(member),
project_id=project_id,
workspace_id=workspace_id,
created_by=module.created_by,
updated_by=module.updated_by,
)
@@ -97,7 +97,7 @@ class ModuleSerializer(BaseSerializer):
[
ModuleMember(
module=instance,
member=member,
member_id=str(member),
project=instance.project,
workspace=instance.project.workspace,
created_by=instance.created_by,
+10 -1
View File
@@ -221,11 +221,20 @@ class IssueAPIEndpoint(WebhookMixin, BaseAPIView):
def patch(self, request, slug, project_id, pk=None):
issue = Issue.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
project = Project.objects.get(pk=project_id)
current_instance = json.dumps(
IssueSerializer(issue).data, cls=DjangoJSONEncoder
)
requested_data = json.dumps(self.request.data, cls=DjangoJSONEncoder)
serializer = IssueSerializer(issue, data=request.data, partial=True)
serializer = IssueSerializer(
issue,
data=request.data,
context={
"project_id": project_id,
"workspace_id": project.workspace_id,
},
partial=True,
)
if serializer.is_valid():
serializer.save()
issue_activity.delay(
+3 -3
View File
@@ -121,8 +121,8 @@ class ModuleAPIEndpoint(WebhookMixin, BaseAPIView):
)
def post(self, request, slug, project_id):
project = Project.objects.get(workspace__slug=slug, pk=project_id)
serializer = ModuleSerializer(data=request.data, context={"project": project})
project = Project.objects.get(pk=project_id, workspace__slug=slug)
serializer = ModuleSerializer(data=request.data, context={"project_id": project_id, "workspace_id": project.workspace_id})
if serializer.is_valid():
serializer.save()
module = Module.objects.get(pk=serializer.data["id"])
@@ -132,7 +132,7 @@ class ModuleAPIEndpoint(WebhookMixin, BaseAPIView):
def patch(self, request, slug, project_id, pk):
module = Module.objects.get(pk=pk, project_id=project_id, workspace__slug=slug)
serializer = ModuleSerializer(module, data=request.data)
serializer = ModuleSerializer(module, data=request.data, context={"project_id": project_id}, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
+1
View File
@@ -40,6 +40,7 @@ class CycleSerializer(BaseSerializer):
started_estimates = serializers.IntegerField(read_only=True)
workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
project_detail = ProjectLiteSerializer(read_only=True, source="project")
status = serializers.CharField(read_only=True)
def validate(self, data):
if (
@@ -4,6 +4,7 @@ from .base import BaseSerializer
from plane.db.models import Estimate, EstimatePoint
from plane.app.serializers import WorkspaceLiteSerializer, ProjectLiteSerializer
from rest_framework import serializers
class EstimateSerializer(BaseSerializer):
workspace_detail = WorkspaceLiteSerializer(read_only=True, source="workspace")
@@ -19,6 +20,15 @@ class EstimateSerializer(BaseSerializer):
class EstimatePointSerializer(BaseSerializer):
def validate(self, data):
if not data:
raise serializers.ValidationError("Estimate points are required")
value = data.get("value")
if value and len(value) > 20:
raise serializers.ValidationError("Value can't be more than 20 characters")
return data
class Meta:
model = EstimatePoint
fields = "__all__"
+31 -3
View File
@@ -11,6 +11,10 @@ from django.db.models import (
Count,
Prefetch,
Sum,
Case,
When,
Value,
CharField
)
from django.core import serializers
from django.utils import timezone
@@ -157,6 +161,28 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
),
)
)
.annotate(
status=Case(
When(
Q(start_date__lte=timezone.now()) & Q(end_date__gte=timezone.now()),
then=Value("CURRENT")
),
When(
start_date__gt=timezone.now(),
then=Value("UPCOMING")
),
When(
end_date__lt=timezone.now(),
then=Value("COMPLETED")
),
When(
Q(start_date__isnull=True) & Q(end_date__isnull=True),
then=Value("DRAFT")
),
default=Value("DRAFT"),
output_field=CharField(),
)
)
.prefetch_related(
Prefetch(
"issue_cycle__issue__assignees",
@@ -177,7 +203,7 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
queryset = self.get_queryset()
cycle_view = request.GET.get("cycle_view", "all")
queryset = queryset.order_by("-is_favorite","-created_at")
queryset = queryset.order_by("-is_favorite", "-created_at")
# Current Cycle
if cycle_view == "current":
@@ -575,7 +601,9 @@ class CycleIssueViewSet(WebhookMixin, BaseViewSet):
)
)
issues = IssueStateSerializer(issues, many=True, fields=fields if fields else None).data
issues = IssueStateSerializer(
issues, many=True, fields=fields if fields else None
).data
issue_dict = {str(issue["id"]): issue for issue in issues}
return Response(issue_dict, status=status.HTTP_200_OK)
@@ -805,4 +833,4 @@ class TransferCycleIssueEndpoint(BaseAPIView):
updated_cycles, ["cycle_id"], batch_size=100
)
return Response({"message": "Success"}, status=status.HTTP_200_OK)
return Response({"message": "Success"}, status=status.HTTP_200_OK)
+4 -4
View File
@@ -53,11 +53,11 @@ class BulkEstimatePointEndpoint(BaseViewSet):
)
estimate_points = request.data.get("estimate_points", [])
if not len(estimate_points) or len(estimate_points) > 8:
serializer = EstimatePointSerializer(data=request.data.get("estimate_points"), many=True)
if not serializer.is_valid():
return Response(
{"error": "Estimate points are required"},
status=status.HTTP_400_BAD_REQUEST,
serializer.errors, status=status.HTTP_400_BAD_REQUEST
)
estimate_serializer = EstimateSerializer(data=request.data.get("estimate"))
+54 -18
View File
@@ -145,6 +145,16 @@ class ProjectViewSet(WebhookMixin, BaseViewSet):
)
)
)
.prefetch_related(
Prefetch(
"project_projectmember",
queryset=ProjectMember.objects.filter(
workspace__slug=self.kwargs.get("slug"),
is_active=True,
).select_related("member"),
to_attr="members_list",
)
)
.distinct()
)
@@ -160,16 +170,6 @@ class ProjectViewSet(WebhookMixin, BaseViewSet):
projects = (
self.get_queryset()
.annotate(sort_order=Subquery(sort_order_query))
.prefetch_related(
Prefetch(
"project_projectmember",
queryset=ProjectMember.objects.filter(
workspace__slug=slug,
is_active=True,
).select_related("member"),
to_attr="members_list",
)
)
.order_by("sort_order", "name")
)
if request.GET.get("per_page", False) and request.GET.get("cursor", False):
@@ -679,6 +679,25 @@ class ProjectMemberViewSet(BaseViewSet):
)
)
# Check if the user is already a member of the project and is inactive
if ProjectMember.objects.filter(
workspace__slug=slug,
project_id=project_id,
member_id=member.get("member_id"),
is_active=False,
).exists():
member_detail = ProjectMember.objects.get(
workspace__slug=slug,
project_id=project_id,
member_id=member.get("member_id"),
is_active=False,
)
# Check if the user has not deactivated the account
user = User.objects.filter(pk=member.get("member_id")).first()
if user.is_active:
member_detail.is_active = True
member_detail.save(update_fields=["is_active"])
project_members = ProjectMember.objects.bulk_create(
bulk_project_members,
batch_size=10,
@@ -991,11 +1010,18 @@ class ProjectPublicCoverImagesEndpoint(BaseAPIView):
def get(self, request):
files = []
s3 = boto3.client(
"s3",
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
)
s3_client_params = {
"service_name": "s3",
"aws_access_key_id": settings.AWS_ACCESS_KEY_ID,
"aws_secret_access_key": settings.AWS_SECRET_ACCESS_KEY,
}
# Use AWS_S3_ENDPOINT_URL if it is present in the settings
if hasattr(settings, "AWS_S3_ENDPOINT_URL") and settings.AWS_S3_ENDPOINT_URL:
s3_client_params["endpoint_url"] = settings.AWS_S3_ENDPOINT_URL
s3 = boto3.client(**s3_client_params)
params = {
"Bucket": settings.AWS_STORAGE_BUCKET_NAME,
"Prefix": "static/project-cover/",
@@ -1008,9 +1034,19 @@ class ProjectPublicCoverImagesEndpoint(BaseAPIView):
if not content["Key"].endswith(
"/"
): # This line ensures we're only getting files, not "sub-folders"
files.append(
f"https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.{settings.AWS_REGION}.amazonaws.com/{content['Key']}"
)
if (
hasattr(settings, "AWS_S3_CUSTOM_DOMAIN")
and settings.AWS_S3_CUSTOM_DOMAIN
and hasattr(settings, "AWS_S3_URL_PROTOCOL")
and settings.AWS_S3_URL_PROTOCOL
):
files.append(
f"{settings.AWS_S3_URL_PROTOCOL}//{settings.AWS_S3_CUSTOM_DOMAIN}/{content['Key']}"
)
else:
files.append(
f"https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.{settings.AWS_REGION}.amazonaws.com/{content['Key']}"
)
return Response(files, status=status.HTTP_200_OK)
+2 -1
View File
@@ -50,7 +50,8 @@ class GlobalSearchEndpoint(BaseAPIView):
q = Q()
for field in fields:
if field == "sequence_id":
sequences = re.findall(r"\d+\.\d+|\d+", query)
# Match whole integers only (exclude decimal numbers)
sequences = re.findall(r"\b\d+\b", query)
for sequence_id in sequences:
q |= Q(**{"sequence_id": sequence_id})
else:
+13
View File
@@ -70,6 +70,7 @@ from plane.app.permissions import (
WorkSpaceAdminPermission,
WorkspaceEntityPermission,
WorkspaceViewerPermission,
WorkspaceUserPermission,
)
from plane.bgtasks.workspace_invitation_task import workspace_invitation
from plane.utils.issue_filters import issue_filters
@@ -495,6 +496,18 @@ class WorkSpaceMemberViewSet(BaseViewSet):
WorkspaceEntityPermission,
]
def get_permissions(self):
if self.action == "leave":
self.permission_classes = [
WorkspaceUserPermission,
]
else:
self.permission_classes = [
WorkspaceEntityPermission,
]
return super(WorkSpaceMemberViewSet, self).get_permissions()
search_fields = [
"member__display_name",
"member__first_name",
@@ -65,7 +65,7 @@ def send_export_email(email, slug, csv_buffer, rows):
port=int(EMAIL_PORT),
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=bool(EMAIL_USE_TLS),
use_tls=EMAIL_USE_TLS == "1",
)
msg = EmailMultiAlternatives(
@@ -51,7 +51,7 @@ def forgot_password(first_name, email, uidb64, token, current_site):
port=int(EMAIL_PORT),
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=bool(EMAIL_USE_TLS),
use_tls=EMAIL_USE_TLS == "1",
)
msg = EmailMultiAlternatives(
@@ -112,8 +112,8 @@ def track_parent(
epoch,
):
if current_instance.get("parent") != requested_data.get("parent"):
old_parent = Issue.objects.filter(pk=current_instance.get("parent")).first()
new_parent = Issue.objects.filter(pk=requested_data.get("parent")).first()
old_parent = Issue.objects.filter(pk=current_instance.get("parent")).first() if current_instance.get("parent") is not None else None
new_parent = Issue.objects.filter(pk=requested_data.get("parent")).first() if requested_data.get("parent") is not None else None
issue_activities.append(
IssueActivity(
@@ -41,7 +41,7 @@ def magic_link(email, key, token, current_site):
port=int(EMAIL_PORT),
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=bool(EMAIL_USE_TLS),
use_tls=EMAIL_USE_TLS == "1",
)
msg = EmailMultiAlternatives(
@@ -60,7 +60,7 @@ def project_invitation(email, project_id, token, current_site, invitor):
port=int(EMAIL_PORT),
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=bool(EMAIL_USE_TLS),
use_tls=EMAIL_USE_TLS == "1",
)
msg = EmailMultiAlternatives(
@@ -70,7 +70,7 @@ def workspace_invitation(email, workspace_id, token, current_site, invitor):
port=int(EMAIL_PORT),
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=bool(EMAIL_USE_TLS),
use_tls=EMAIL_USE_TLS == "1",
)
msg = EmailMultiAlternatives(
@@ -0,0 +1,83 @@
# Generated by Django 4.2.7 on 2023-12-29 10:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('db', '0050_user_use_case_alter_workspace_organization_size'),
]
operations = [
migrations.AddField(
model_name='cycle',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='cycle',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='inboxissue',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='inboxissue',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='issue',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='issue',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='issuecomment',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='issuecomment',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='label',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='label',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='module',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='module',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='state',
name='external_id',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='state',
name='external_source',
field=models.CharField(blank=True, max_length=255, null=True),
),
]
+2
View File
@@ -18,6 +18,8 @@ class Cycle(ProjectBaseModel):
)
view_props = models.JSONField(default=dict)
sort_order = models.FloatField(default=65535)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
class Meta:
verbose_name = "Cycle"
+2
View File
@@ -39,6 +39,8 @@ class InboxIssue(ProjectBaseModel):
"db.Issue", related_name="inbox_duplicate", on_delete=models.SET_NULL, null=True
)
source = models.TextField(blank=True, null=True)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
class Meta:
verbose_name = "InboxIssue"
+6
View File
@@ -102,6 +102,8 @@ class Issue(ProjectBaseModel):
completed_at = models.DateTimeField(null=True)
archived_at = models.DateField(null=True)
is_draft = models.BooleanField(default=False)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
objects = models.Manager()
issue_objects = IssueManager()
@@ -366,6 +368,8 @@ class IssueComment(ProjectBaseModel):
default="INTERNAL",
max_length=100,
)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
def save(self, *args, **kwargs):
self.comment_stripped = (
@@ -416,6 +420,8 @@ class Label(ProjectBaseModel):
description = models.TextField(blank=True)
color = models.CharField(max_length=255, blank=True)
sort_order = models.FloatField(default=65535)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
class Meta:
unique_together = ["name", "project"]
+2
View File
@@ -41,6 +41,8 @@ class Module(ProjectBaseModel):
)
view_props = models.JSONField(default=dict)
sort_order = models.FloatField(default=65535)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
class Meta:
unique_together = ["name", "project"]
+2
View File
@@ -24,6 +24,8 @@ class State(ProjectBaseModel):
max_length=20,
)
default = models.BooleanField(default=False)
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
"""Return name of the state"""
+5 -1
View File
@@ -291,7 +291,9 @@ CELERY_IMPORTS = (
# Sentry Settings
# Enable Sentry Settings
if bool(os.environ.get("SENTRY_DSN", False)) and os.environ.get("SENTRY_DSN").startswith("https://"):
if bool(os.environ.get("SENTRY_DSN", False)) and os.environ.get(
"SENTRY_DSN"
).startswith("https://"):
sentry_sdk.init(
dsn=os.environ.get("SENTRY_DSN", ""),
integrations=[
@@ -334,3 +336,5 @@ INSTANCE_KEY = os.environ.get(
# Skip environment variable configuration
SKIP_ENV_VAR = os.environ.get("SKIP_ENV_VAR", "1") == "1"
DATA_UPLOAD_MAX_MEMORY_SIZE = int(os.environ.get("FILE_SIZE_LIMIT", 5242880))
+1 -1
View File
@@ -30,7 +30,7 @@ openpyxl==3.1.2
beautifulsoup4==4.12.2
dj-database-url==2.1.0
posthog==3.0.2
cryptography==41.0.5
cryptography==41.0.6
lxml==4.9.3
boto3==1.28.40
+1 -1
View File
@@ -39,7 +39,7 @@ function download(){
echo ""
echo "Latest version is now available for you to use"
echo ""
echo "In case of Upgrade, your new setting file is availabe as 'variables-upgrade.env'. Please compare and set the required values in '.env 'file."
echo "In case of Upgrade, your new setting file is available as 'variables-upgrade.env'. Please compare and set the required values in '.env 'file."
echo ""
}
+4 -17
View File
@@ -12,7 +12,6 @@ volumes:
services:
plane-redis:
container_name: plane-redis
image: redis:6.2.7-alpine
restart: unless-stopped
networks:
@@ -21,7 +20,6 @@ services:
- redisdata:/data
plane-minio:
container_name: plane-minio
image: minio/minio
restart: unless-stopped
networks:
@@ -36,7 +34,6 @@ services:
MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY}
plane-db:
container_name: plane-db
image: postgres:15.2-alpine
restart: unless-stopped
networks:
@@ -53,7 +50,6 @@ services:
PGDATA: /var/lib/postgresql/data
web:
container_name: web
build:
context: .
dockerfile: ./web/Dockerfile.dev
@@ -61,8 +57,7 @@ services:
networks:
- dev_env
volumes:
- .:/app
command: yarn dev --filter=web
- ./web:/app/web
env_file:
- ./web/.env
depends_on:
@@ -73,22 +68,17 @@ services:
build:
context: .
dockerfile: ./space/Dockerfile.dev
container_name: space
restart: unless-stopped
networks:
- dev_env
volumes:
- .:/app
command: yarn dev --filter=space
env_file:
- ./space/.env
- ./space:/app/space
depends_on:
- api
- worker
- web
api:
container_name: api
build:
context: ./apiserver
dockerfile: Dockerfile.dev
@@ -99,7 +89,7 @@ services:
- dev_env
volumes:
- ./apiserver:/code
command: /bin/sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000 --settings=plane.settings.local"
# command: /bin/sh -c "python manage.py migrate && python manage.py runserver 0.0.0.0:8000 --settings=plane.settings.local"
env_file:
- ./apiserver/.env
depends_on:
@@ -107,7 +97,6 @@ services:
- plane-redis
worker:
container_name: bgworker
build:
context: ./apiserver
dockerfile: Dockerfile.dev
@@ -127,7 +116,6 @@ services:
- plane-redis
beat-worker:
container_name: beatworker
build:
context: ./apiserver
dockerfile: Dockerfile.dev
@@ -147,10 +135,9 @@ services:
- plane-redis
proxy:
container_name: proxy
build:
context: ./nginx
dockerfile: Dockerfile
dockerfile: Dockerfile.dev
restart: unless-stopped
networks:
- dev_env
+10
View File
@@ -0,0 +1,10 @@
FROM nginx:1.25.0-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf.dev /etc/nginx/nginx.conf.template
COPY ./env.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
# Update all environment variables
CMD ["/docker-entrypoint.sh"]
+1 -1
View File
@@ -18,7 +18,7 @@ server {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /space/ {
location /spaces/ {
proxy_pass http://localhost:4000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
+39
View File
@@ -0,0 +1,39 @@
events {
}
http {
sendfile on;
server {
listen 80;
root /www/data/;
access_log /var/log/nginx/access.log;
client_max_body_size ${FILE_SIZE_LIMIT};
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Permissions-Policy "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://web:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api/ {
proxy_pass http://api:8000/api/;
}
location /spaces/ {
rewrite ^/spaces/?$ /spaces/login break;
proxy_pass http://space:4000/spaces/;
}
location /${BUCKET_NAME}/ {
proxy_pass http://plane-minio:9000/uploads/;
}
}
}
+1 -1
View File
@@ -27,7 +27,7 @@
"prettier": "latest",
"prettier-plugin-tailwindcss": "^0.5.4",
"tailwindcss": "^3.3.3",
"turbo": "^1.11.1"
"turbo": "^1.11.2"
},
"resolutions": {
"@types/react": "18.2.42"
+15 -21
View File
@@ -28,28 +28,22 @@
"react-dom": "18.2.0"
},
"dependencies": {
"@plane/editor-types": "*",
"@tiptap/core": "^2.1.7",
"@tiptap/core": "^2.1.13",
"@tiptap/extension-blockquote": "^2.1.13",
"@tiptap/extension-code-block-lowlight": "^2.1.12",
"@tiptap/extension-color": "^2.1.11",
"@tiptap/extension-image": "^2.1.7",
"@tiptap/extension-link": "^2.1.7",
"@tiptap/extension-list-item": "^2.1.12",
"@tiptap/extension-mention": "^2.1.12",
"@tiptap/extension-table": "^2.1.6",
"@tiptap/extension-table-cell": "^2.1.6",
"@tiptap/extension-table-header": "^2.1.6",
"@tiptap/extension-table-row": "^2.1.6",
"@tiptap/extension-task-item": "^2.1.7",
"@tiptap/extension-task-list": "^2.1.7",
"@tiptap/extension-text-style": "^2.1.11",
"@tiptap/extension-underline": "^2.1.7",
"@tiptap/pm": "^2.1.7",
"@tiptap/prosemirror-tables": "^1.1.4",
"@tiptap/react": "^2.1.7",
"@tiptap/starter-kit": "^2.1.10",
"@tiptap/suggestion": "^2.0.4",
"@tiptap/extension-code-block-lowlight": "^2.1.13",
"@tiptap/extension-color": "^2.1.13",
"@tiptap/extension-image": "^2.1.13",
"@tiptap/extension-link": "^2.1.13",
"@tiptap/extension-list-item": "^2.1.13",
"@tiptap/extension-mention": "^2.1.13",
"@tiptap/extension-task-item": "^2.1.13",
"@tiptap/extension-task-list": "^2.1.13",
"@tiptap/extension-text-style": "^2.1.13",
"@tiptap/extension-underline": "^2.1.13",
"@tiptap/pm": "^2.1.13",
"@tiptap/react": "^2.1.13",
"@tiptap/starter-kit": "^2.1.13",
"@tiptap/suggestion": "^2.0.13",
"class-variance-authority": "^0.7.0",
"clsx": "^1.2.1",
"highlight.js": "^11.8.0",
@@ -1,10 +1,13 @@
import { useEditor as useCustomEditor, Editor } from "@tiptap/react";
import { useImperativeHandle, useRef, MutableRefObject } from "react";
import { CoreEditorProps } from "../props";
import { CoreEditorExtensions } from "../extensions";
import { CoreEditorProps } from "src/ui/props";
import { CoreEditorExtensions } from "src/ui/extensions";
import { EditorProps } from "@tiptap/pm/view";
import { getTrimmedHTML } from "../../lib/utils";
import { DeleteImage, IMentionSuggestion, RestoreImage, UploadImage } from "@plane/editor-types";
import { getTrimmedHTML } from "src/lib/utils";
import { DeleteImage } from "src/types/delete-image";
import { IMentionSuggestion } from "src/types/mention-suggestion";
import { RestoreImage } from "src/types/restore-image";
import { UploadImage } from "src/types/upload-image";
interface CustomEditorProps {
uploadFile: UploadImage;
@@ -1,9 +1,9 @@
import { useEditor as useCustomEditor, Editor } from "@tiptap/react";
import { useImperativeHandle, useRef, MutableRefObject } from "react";
import { CoreReadOnlyEditorExtensions } from "../read-only/extensions";
import { CoreReadOnlyEditorProps } from "../read-only/props";
import { CoreReadOnlyEditorExtensions } from "src/ui/read-only/extensions";
import { CoreReadOnlyEditorProps } from "src/ui/read-only/props";
import { EditorProps } from "@tiptap/pm/view";
import { IMentionSuggestion } from "@plane/editor-types";
import { IMentionSuggestion } from "src/types/mention-suggestion";
interface CustomReadOnlyEditorProps {
value: string;
+21 -12
View File
@@ -1,23 +1,32 @@
// styles
// import "./styles/tailwind.css";
// import "./styles/editor.css";
import "./styles/github-dark.css";
import "src/styles/editor.css";
import "src/styles/table.css";
import "src/styles/github-dark.css";
export { isCellSelection } from "./ui/extensions/table/table/utilities/is-cell-selection";
export { isCellSelection } from "src/ui/extensions/table/table/utilities/is-cell-selection";
// utils
export * from "./lib/utils";
export * from "./ui/extensions/table/table";
export { startImageUpload } from "./ui/plugins/upload-image";
export * from "src/lib/utils";
export * from "src/ui/extensions/table/table";
export { startImageUpload } from "src/ui/plugins/upload-image";
// components
export { EditorContainer } from "./ui/components/editor-container";
export { EditorContentWrapper } from "./ui/components/editor-content";
export { EditorContainer } from "src/ui/components/editor-container";
export { EditorContentWrapper } from "src/ui/components/editor-content";
// hooks
export { useEditor } from "./ui/hooks/use-editor";
export { useReadOnlyEditor } from "./ui/hooks/use-read-only-editor";
export { useEditor } from "src/hooks/use-editor";
export { useReadOnlyEditor } from "src/hooks/use-read-only-editor";
// helper items
export * from "./ui/menus/menu-items";
export * from "./lib/editor-commands";
export * from "src/ui/menus/menu-items";
export * from "src/lib/editor-commands";
// types
export type { DeleteImage } from "src/types/delete-image";
export type { UploadImage } from "src/types/upload-image";
export type { RestoreImage } from "src/types/restore-image";
export type { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion";
export type { ISlashCommandItem, CommandProps } from "src/types/slash-commands-suggestion";
export type { LucideIconType } from "src/types/lucide-icon";
@@ -1,7 +1,7 @@
import { UploadImage } from "@plane/editor-types";
import { Editor, Range } from "@tiptap/core";
import { startImageUpload } from "../ui/plugins/upload-image";
import { findTableAncestor } from "./utils";
import { startImageUpload } from "src/ui/plugins/upload-image";
import { findTableAncestor } from "src/lib/utils";
import { UploadImage } from "src/types/upload-image";
export const toggleHeadingOne = (editor: Editor, range?: Range) => {
if (range) editor.chain().focus().deleteRange(range).setNode("heading", { level: 1 }).run();
+50 -8
View File
@@ -6,6 +6,12 @@
height: 0;
}
/* block quotes */
.ProseMirror blockquote p::before,
.ProseMirror blockquote p::after {
display: none;
}
.ProseMirror .is-empty::before {
content: attr(data-placeholder);
float: left;
@@ -15,9 +21,10 @@
}
/* Custom image styles */
.ProseMirror img {
transition: filter 0.1s ease-in-out;
margin-top: 0 !important;
margin-bottom: 0 !important;
&:hover {
cursor: pointer;
@@ -53,11 +60,12 @@ ul[data-type="taskList"] li > label input[type="checkbox"] {
background-color: rgb(var(--color-background-100));
margin: 0;
cursor: pointer;
width: 1.2rem;
height: 1.2rem;
width: 0.8rem;
height: 0.8rem;
position: relative;
border: 2px solid rgb(var(--color-text-100));
margin-right: 0.3rem;
border: 1.5px solid rgb(var(--color-text-100));
margin-right: 0.2rem;
margin-top: 0.15rem;
display: grid;
place-content: center;
@@ -71,8 +79,8 @@ ul[data-type="taskList"] li > label input[type="checkbox"] {
&::before {
content: "";
width: 0.65em;
height: 0.65em;
width: 0.5em;
height: 0.5em;
transform: scale(0);
transition: 120ms transform ease-in-out;
box-shadow: inset 1em 1em;
@@ -133,6 +141,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
.img-placeholder {
position: relative;
width: 35%;
margin-top: 0 !important;
margin-bottom: 0 !important;
&:before {
content: "";
@@ -159,7 +169,8 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
table {
border-collapse: collapse;
table-layout: fixed;
margin: 0;
margin: 0.5em 0 0.5em 0;
border: 1px solid rgb(var(--color-border-200));
width: 100%;
@@ -229,3 +240,34 @@ ul[data-type="taskList"] li[data-checked="true"] > div > p {
.ProseMirror table * .is-empty::before {
opacity: 0;
}
.ProseMirror pre {
background: rgba(var(--color-background-80));
border-radius: 0.5rem;
color: rgba(var(--color-text-100));
font-family: "JetBrainsMono", monospace;
padding: 0.75rem 1rem;
}
.ProseMirror pre code {
background: none;
color: inherit;
font-size: 0.8rem;
padding: 0;
}
div[data-type="horizontalRule"] {
line-height: 0;
padding: 0.25rem 0;
margin-top: 0;
margin-bottom: 0;
& > div {
border-bottom: 1px solid rgb(var(--color-text-100));
}
}
/* image resizer */
.moveable-control-box {
z-index: 10 !important;
}
@@ -0,0 +1,3 @@
import { Smile } from "lucide-react";
export type LucideIconType = typeof Smile;
@@ -1,6 +1,6 @@
import { Editor, EditorContent } from "@tiptap/react";
import { ReactNode } from "react";
import { ImageResizer } from "../extensions/image/image-resize";
import { ImageResizer } from "src/ui/extensions/image/image-resize";
interface EditorContentProps {
editor: Editor | null;
@@ -1,7 +1,7 @@
import { getNodeAtPosition } from "@tiptap/core";
import { EditorState } from "@tiptap/pm/state";
import { findListItemPos } from "./find-list-item-pos";
import { findListItemPos } from "src/ui/extensions/custom-list-keymap/list-helpers/find-list-item-pos";
export const getNextListDepth = (typeOrName: string, state: EditorState) => {
const listItemPos = findListItemPos(typeOrName, state);
@@ -1,8 +1,8 @@
import { Editor, isAtStartOfNode, isNodeActive } from "@tiptap/core";
import { Node } from "@tiptap/pm/model";
import { findListItemPos } from "./find-list-item-pos";
import { hasListBefore } from "./has-list-before";
import { findListItemPos } from "src/ui/extensions/custom-list-keymap/list-helpers/find-list-item-pos";
import { hasListBefore } from "src/ui/extensions/custom-list-keymap/list-helpers/has-list-before";
export const handleBackspace = (editor: Editor, name: string, parentListTypes: string[]) => {
// this is required to still handle the undo handling
@@ -1,7 +1,7 @@
import { Editor, isAtEndOfNode, isNodeActive } from "@tiptap/core";
import { nextListIsDeeper } from "./next-list-is-deeper";
import { nextListIsHigher } from "./next-list-is-higher";
import { nextListIsDeeper } from "src/ui/extensions/custom-list-keymap/list-helpers/next-list-is-deeper";
import { nextListIsHigher } from "src/ui/extensions/custom-list-keymap/list-helpers/next-list-is-higher";
export const handleDelete = (editor: Editor, name: string) => {
// if the cursor is not inside the current node type
@@ -1,7 +1,7 @@
import { EditorState } from "@tiptap/pm/state";
import { findListItemPos } from "./find-list-item-pos";
import { getNextListDepth } from "./get-next-list-depth";
import { findListItemPos } from "src/ui/extensions/custom-list-keymap/list-helpers/find-list-item-pos";
import { getNextListDepth } from "src/ui/extensions/custom-list-keymap/list-helpers/get-next-list-depth";
export const nextListIsDeeper = (typeOrName: string, state: EditorState) => {
const listDepth = getNextListDepth(typeOrName, state);
@@ -1,7 +1,7 @@
import { EditorState } from "@tiptap/pm/state";
import { findListItemPos } from "./find-list-item-pos";
import { getNextListDepth } from "./get-next-list-depth";
import { findListItemPos } from "src/ui/extensions/custom-list-keymap/list-helpers/find-list-item-pos";
import { getNextListDepth } from "src/ui/extensions/custom-list-keymap/list-helpers/get-next-list-depth";
export const nextListIsHigher = (typeOrName: string, state: EditorState) => {
const listDepth = getNextListDepth(typeOrName, state);
@@ -1,6 +1,6 @@
import { Extension } from "@tiptap/core";
import { handleBackspace, handleDelete } from "./list-helpers";
import { handleBackspace, handleDelete } from "src/ui/extensions/custom-list-keymap/list-helpers";
export type ListKeymapOptions = {
listTypes: Array<{
@@ -22,7 +22,7 @@ declare module "@tiptap/core" {
}
}
export default Node.create<HorizontalRuleOptions>({
export const HorizontalRule = Node.create<HorizontalRuleOptions>({
name: "horizontalRule",
addOptions() {
@@ -1,9 +1,10 @@
import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
import UploadImagesPlugin from "../../plugins/upload-image";
import { UploadImagesPlugin } from "src/ui/plugins/upload-image";
import ImageExt from "@tiptap/extension-image";
import { onNodeDeleted, onNodeRestored } from "../../plugins/delete-image";
import { DeleteImage, RestoreImage } from "@plane/editor-types";
import { onNodeDeleted, onNodeRestored } from "src/ui/plugins/delete-image";
import { DeleteImage } from "src/types/delete-image";
import { RestoreImage } from "src/types/restore-image";
interface ImageNode extends ProseMirrorNode {
attrs: {
@@ -15,7 +16,7 @@ interface ImageNode extends ProseMirrorNode {
const deleteKey = new PluginKey("delete-image");
const IMAGE_NODE_TYPE = "image";
const ImageExtension = (deleteImage: DeleteImage, restoreFile: RestoreImage, cancelUploadImage?: () => any) =>
export const ImageExtension = (deleteImage: DeleteImage, restoreFile: RestoreImage, cancelUploadImage?: () => any) =>
ImageExt.extend({
addProseMirrorPlugins() {
return [
@@ -130,5 +131,3 @@ const ImageExtension = (deleteImage: DeleteImage, restoreFile: RestoreImage, can
};
},
});
export default ImageExtension;
@@ -1,6 +1,6 @@
import Image from "@tiptap/extension-image";
const ReadOnlyImageExtension = Image.extend({
export const ReadOnlyImageExtension = Image.extend({
addAttributes() {
return {
...this.parent?.(),
@@ -13,5 +13,3 @@ const ReadOnlyImageExtension = Image.extend({
};
},
});
export default ReadOnlyImageExtension;
@@ -7,22 +7,25 @@ import TaskItem from "@tiptap/extension-task-item";
import TaskList from "@tiptap/extension-task-list";
import { Markdown } from "tiptap-markdown";
import TableHeader from "./table/table-header/table-header";
import Table from "./table/table";
import TableCell from "./table/table-cell/table-cell";
import TableRow from "./table/table-row/table-row";
import HorizontalRule from "./horizontal-rule";
import { TableHeader } from "src/ui/extensions/table/table-header/table-header";
import { Table } from "src/ui/extensions/table/table";
import { TableCell } from "src/ui/extensions/table/table-cell/table-cell";
import { TableRow } from "src/ui/extensions/table/table-row/table-row";
import { HorizontalRule } from "src/ui/extensions/horizontal-rule";
import ImageExtension from "./image";
import { ImageExtension } from "src/ui/extensions/image";
import { isValidHttpUrl } from "../../lib/utils";
import { Mentions } from "../mentions";
import { isValidHttpUrl } from "src/lib/utils";
import { Mentions } from "src/ui/mentions";
import { CustomKeymap } from "./keymap";
import { CustomCodeBlock } from "./code";
import { CustomQuoteExtension } from "./quote";
import { ListKeymap } from "./custom-list-keymap";
import { IMentionSuggestion, DeleteImage, RestoreImage } from "@plane/editor-types";
import { CustomKeymap } from "src/ui/extensions/keymap";
import { CustomCodeBlock } from "src/ui/extensions/code";
import { CustomQuoteExtension } from "src/ui/extensions/quote";
import { ListKeymap } from "src/ui/extensions/custom-list-keymap";
import { DeleteImage } from "src/types/delete-image";
import { IMentionSuggestion } from "src/types/mention-suggestion";
import { RestoreImage } from "src/types/restore-image";
export const CoreEditorExtensions = (
mentionConfig: {
@@ -49,12 +52,12 @@ export const CoreEditorExtensions = (
class: "leading-normal -mb-2",
},
},
// blockquote: {
// HTMLAttributes: {
// class: "border-l-4 border-custom-border-300",
// },
// },
code: false,
code: {
HTMLAttributes: {
class: "rounded-md bg-custom-primary-30 mx-1 px-1 py-1 font-mono font-medium text-custom-text-1000",
spellcheck: "false",
},
},
codeBlock: false,
horizontalRule: false,
dropcursor: {
@@ -1 +1 @@
export { default as default } from "./table-cell";
export { TableCell } from "./table-cell";
@@ -4,7 +4,7 @@ export interface TableCellOptions {
HTMLAttributes: Record<string, any>;
}
export default Node.create<TableCellOptions>({
export const TableCell = Node.create<TableCellOptions>({
name: "tableCell",
addOptions() {
@@ -1 +1 @@
export { default as default } from "./table-header";
export { TableHeader } from "./table-header";
@@ -3,7 +3,8 @@ import { mergeAttributes, Node } from "@tiptap/core";
export interface TableHeaderOptions {
HTMLAttributes: Record<string, any>;
}
export default Node.create<TableHeaderOptions>({
export const TableHeader = Node.create<TableHeaderOptions>({
name: "tableHeader",
addOptions() {
@@ -1 +1 @@
export { default as default } from "./table-row";
export { TableRow } from "./table-row";
@@ -4,7 +4,7 @@ export interface TableRowOptions {
HTMLAttributes: Record<string, any>;
}
export default Node.create<TableRowOptions>({
export const TableRow = Node.create<TableRowOptions>({
name: "tableRow",
addOptions() {
@@ -1,4 +1,4 @@
const icons = {
export const icons = {
colorPicker: `<svg xmlns="http://www.w3.org/2000/svg" length="24" viewBox="0 0 24 24" style="transform: ;msFilter:;"><path fill="rgb(var(--color-text-300))" d="M20 14c-.092.064-2 2.083-2 3.5 0 1.494.949 2.448 2 2.5.906.044 2-.891 2-2.5 0-1.5-1.908-3.436-2-3.5zM9.586 20c.378.378.88.586 1.414.586s1.036-.208 1.414-.586l7-7-.707-.707L11 4.586 8.707 2.293 7.293 3.707 9.586 6 4 11.586c-.378.378-.586.88-.586 1.414s.208 1.036.586 1.414L9.586 20zM11 7.414 16.586 13H5.414L11 7.414z"></path></svg>`,
deleteColumn: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" length="24"><path fill="#e53e3e" d="M0 0H24V24H0z"/><path d="M12 3c.552 0 1 .448 1 1v8c.835-.628 1.874-1 3-1 2.761 0 5 2.239 5 5s-2.239 5-5 5c-1.032 0-1.99-.313-2.787-.848L13 20c0 .552-.448 1-1 1H6c-.552 0-1-.448-1-1V4c0-.552.448-1 1-1h6zm-1 2H7v14h4V5zm8 10h-6v2h6v-2z"/></svg>`,
deleteRow: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" length="24"><path fill="#e53e3e" d="M0 0H24V24H0z"/><path d="M20 5c.552 0 1 .448 1 1v6c0 .552-.448 1-1 1 .628.835 1 1.874 1 3 0 2.761-2.239 5-5 5s-5-2.239-5-5c0-1.126.372-2.165 1-3H4c-.552 0-1-.448-1-1V6c0-.552.448-1 1-1h16zm-7 10v2h6v-2h-6zm6-8H5v4h14V7z"/></svg>`,
@@ -47,5 +47,3 @@ const icons = {
</svg>
`,
};
export default icons;
@@ -1 +1 @@
export { default as default } from "./table";
export { Table } from "./table";
@@ -4,9 +4,9 @@ import { Decoration, NodeView } from "@tiptap/pm/view";
import tippy, { Instance, Props } from "tippy.js";
import { Editor } from "@tiptap/core";
import { CellSelection, TableMap, updateColumnsOnResize } from "@tiptap/prosemirror-tables";
import { CellSelection, TableMap, updateColumnsOnResize } from "@tiptap/pm/tables";
import icons from "./icons";
import { icons } from "src/ui/extensions/table/table/icons";
export function updateColumns(
node: ProseMirrorNode,
@@ -19,12 +19,12 @@ import {
tableEditing,
toggleHeader,
toggleHeaderCell,
} from "@tiptap/prosemirror-tables";
} from "@tiptap/pm/tables";
import { tableControls } from "./table-controls";
import { TableView } from "./table-view";
import { createTable } from "./utilities/create-table";
import { deleteTableWhenAllCellsSelected } from "./utilities/delete-table-when-all-cells-selected";
import { tableControls } from "src/ui/extensions/table/table/table-controls";
import { TableView } from "src/ui/extensions/table/table/table-view";
import { createTable } from "src/ui/extensions/table/table/utilities/create-table";
import { deleteTableWhenAllCellsSelected } from "src/ui/extensions/table/table/utilities/delete-table-when-all-cells-selected";
export interface TableOptions {
HTMLAttributes: Record<string, any>;
@@ -72,7 +72,7 @@ declare module "@tiptap/core" {
}
}
export default Node.create({
export const Table = Node.create({
name: "table",
addOptions() {
@@ -1,7 +1,7 @@
import { Fragment, Node as ProsemirrorNode, Schema } from "@tiptap/pm/model";
import { createCell } from "./create-cell";
import { getTableNodeTypes } from "./get-table-node-types";
import { createCell } from "src/ui/extensions/table/table/utilities/create-cell";
import { getTableNodeTypes } from "src/ui/extensions/table/table/utilities/get-table-node-types";
export function createTable(
schema: Schema,
@@ -1,6 +1,6 @@
import { findParentNodeClosestToPos, KeyboardShortcutCommand } from "@tiptap/core";
import { isCellSelection } from "./is-cell-selection";
import { isCellSelection } from "src/ui/extensions/table/table/utilities/is-cell-selection";
export const deleteTableWhenAllCellsSelected: KeyboardShortcutCommand = ({ editor }) => {
const { selection } = editor.state;
@@ -1,4 +1,4 @@
import { CellSelection } from "@tiptap/prosemirror-tables";
import { CellSelection } from "@tiptap/pm/tables";
export function isCellSelection(value: unknown): value is CellSelection {
return value instanceof CellSelection;
@@ -1,8 +1,8 @@
import { Mention, MentionOptions } from "@tiptap/extension-mention";
import { mergeAttributes } from "@tiptap/core";
import { ReactNodeViewRenderer } from "@tiptap/react";
import mentionNodeView from "./mentionNodeView";
import { IMentionHighlight } from "@plane/editor-types";
import { MentionNodeView } from "src/ui/mentions/mention-node-view";
import { IMentionHighlight } from "src/types/mention-suggestion";
export interface CustomMentionOptions extends MentionOptions {
mentionHighlights: IMentionHighlight[];
@@ -31,7 +31,7 @@ export const CustomMention = Mention.extend<CustomMentionOptions>({
},
addNodeView() {
return ReactNodeViewRenderer(mentionNodeView);
return ReactNodeViewRenderer(MentionNodeView);
},
parseHTML() {
@@ -1,8 +1,8 @@
// @ts-nocheck
import suggestion from "./suggestion";
import { CustomMention } from "./custom";
import { IMentionHighlight, IMentionSuggestion } from "@plane/editor-types";
import { Suggestion } from "src/ui/mentions/suggestion";
import { CustomMention } from "src/ui/mentions/custom";
import { IMentionHighlight } from "src/types/mention-suggestion";
export const Mentions = (mentionSuggestions: IMentionSuggestion[], mentionHighlights: IMentionHighlight[], readonly) =>
CustomMention.configure({
@@ -11,5 +11,5 @@ export const Mentions = (mentionSuggestions: IMentionSuggestion[], mentionHighli
},
readonly: readonly,
mentionHighlights: mentionHighlights,
suggestion: suggestion(mentionSuggestions),
suggestion: Suggestion(mentionSuggestions),
});
@@ -1,6 +1,6 @@
import { IMentionSuggestion } from "@plane/editor-types";
import { Editor } from "@tiptap/react";
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from "react";
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
import { IMentionSuggestion } from "src/types/mention-suggestion";
interface MentionListProps {
items: IMentionSuggestion[];
@@ -9,7 +9,7 @@ interface MentionListProps {
}
// eslint-disable-next-line react/display-name
const MentionList = forwardRef((props: MentionListProps, ref) => {
export const MentionList = forwardRef((props: MentionListProps, ref) => {
const [selectedIndex, setSelectedIndex] = useState(0);
const selectItem = (index: number) => {
@@ -98,5 +98,3 @@ const MentionList = forwardRef((props: MentionListProps, ref) => {
});
MentionList.displayName = "MentionList";
export default MentionList;
@@ -1,12 +1,12 @@
/* eslint-disable react/display-name */
// @ts-nocheck
import { NodeViewWrapper } from "@tiptap/react";
import { cn } from "../../lib/utils";
import { cn } from "src/lib/utils";
import { useRouter } from "next/router";
import { IMentionHighlight } from "@plane/editor-types";
import { IMentionHighlight } from "src/types/mention-suggestion";
// eslint-disable-next-line import/no-anonymous-default-export
export default (props) => {
export const MentionNodeView = (props) => {
const router = useRouter();
const highlights = props.extension.options.mentionHighlights as IMentionHighlight[];
@@ -2,10 +2,10 @@ import { ReactRenderer } from "@tiptap/react";
import { Editor } from "@tiptap/core";
import tippy from "tippy.js";
import MentionList from "./MentionList";
import { IMentionSuggestion } from "@plane/editor-types";
import { MentionList } from "src/ui/mentions/mention-list";
import { IMentionSuggestion } from "src/types/mention-suggestion";
const Suggestion = (suggestions: IMentionSuggestion[]) => ({
export const Suggestion = (suggestions: IMentionSuggestion[]) => ({
items: ({ query }: { query: string }) =>
suggestions.filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase())).slice(0, 5),
render: () => {
@@ -55,5 +55,3 @@ const Suggestion = (suggestions: IMentionSuggestion[]) => ({
};
},
});
export default Suggestion;
@@ -30,14 +30,15 @@ import {
toggleStrike,
toggleTaskList,
toggleUnderline,
} from "../../../lib/editor-commands";
import { UploadImage } from "@plane/editor-types";
} from "src/lib/editor-commands";
import { LucideIconType } from "src/types/lucide-icon";
import { UploadImage } from "src/types/upload-image";
export interface EditorMenuItem {
name: string;
isActive: () => boolean;
command: () => void;
icon: typeof BoldIcon;
icon: LucideIconType;
}
export const HeadingOneItem = (editor: Editor): EditorMenuItem => ({
@@ -1,6 +1,7 @@
import { EditorState, Plugin, PluginKey, Transaction } from "@tiptap/pm/state";
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
import { DeleteImage, RestoreImage } from "@plane/editor-types";
import { DeleteImage } from "src/types/delete-image";
import { RestoreImage } from "src/types/restore-image";
const deleteKey = new PluginKey("delete-image");
const IMAGE_NODE_TYPE = "image";
@@ -12,7 +13,7 @@ interface ImageNode extends ProseMirrorNode {
};
}
const TrackImageDeletionPlugin = (deleteImage: DeleteImage): Plugin =>
export const TrackImageDeletionPlugin = (deleteImage: DeleteImage): Plugin =>
new Plugin({
key: deleteKey,
appendTransaction: (transactions: readonly Transaction[], oldState: EditorState, newState: EditorState) => {
@@ -53,8 +54,6 @@ const TrackImageDeletionPlugin = (deleteImage: DeleteImage): Plugin =>
},
});
export default TrackImageDeletionPlugin;
export async function onNodeDeleted(src: string, deleteImage: DeleteImage): Promise<void> {
try {
const assetUrlWithWorkspaceId = new URL(src).pathname.substring(1);
@@ -1,10 +1,10 @@
import { UploadImage } from "@plane/editor-types";
import { EditorState, Plugin, PluginKey } from "@tiptap/pm/state";
import { Decoration, DecorationSet, EditorView } from "@tiptap/pm/view";
import { UploadImage } from "src/types/upload-image";
const uploadKey = new PluginKey("upload-image");
const UploadImagesPlugin = (cancelUploadImage?: () => any) =>
export const UploadImagesPlugin = (cancelUploadImage?: () => any) =>
new Plugin({
key: uploadKey,
state: {
@@ -43,7 +43,7 @@ const UploadImagesPlugin = (cancelUploadImage?: () => any) =>
cancelButton.appendChild(svgElement);
placeholder.appendChild(cancelButton);
const deco = Decoration.widget(pos + 1, placeholder, {
const deco = Decoration.widget(pos, placeholder, {
id,
});
set = set.add(tr.doc, [deco]);
@@ -60,8 +60,6 @@ const UploadImagesPlugin = (cancelUploadImage?: () => any) =>
},
});
export default UploadImagesPlugin;
function findPlaceholder(state: EditorState, id: {}) {
const decos = uploadKey.getState(state);
const found = decos.find(undefined, undefined, (spec: { id: number | undefined }) => spec.id == id);
@@ -133,7 +131,8 @@ export async function startImageUpload(
const imageSrc = typeof src === "object" ? reader.result : src;
const node = schema.nodes.image.create({ src: imageSrc });
const transaction = view.state.tr.replaceWith(pos, pos, node).setMeta(uploadKey, { remove: { id } });
const transaction = view.state.tr.insert(pos - 1, node).setMeta(uploadKey, { remove: { id } });
view.dispatch(transaction);
} catch (error) {
console.error("Upload error: ", error);
+3 -3
View File
@@ -1,7 +1,7 @@
import { UploadImage } from "@plane/editor-types";
import { EditorProps } from "@tiptap/pm/view";
import { findTableAncestor } from "../lib/utils";
import { startImageUpload } from "./plugins/upload-image";
import { findTableAncestor } from "src/lib/utils";
import { UploadImage } from "src/types/upload-image";
import { startImageUpload } from "src/ui/plugins/upload-image";
export function CoreEditorProps(
uploadFile: UploadImage,
@@ -8,15 +8,16 @@ import TaskList from "@tiptap/extension-task-list";
import { Markdown } from "tiptap-markdown";
import Gapcursor from "@tiptap/extension-gapcursor";
import TableHeader from "../extensions/table/table-header/table-header";
import Table from "../extensions/table/table";
import TableCell from "../extensions/table/table-cell/table-cell";
import TableRow from "../extensions/table/table-row/table-row";
import { TableHeader } from "src/ui/extensions/table/table-header/table-header";
import { Table } from "src/ui/extensions/table/table";
import { TableCell } from "src/ui/extensions/table/table-cell/table-cell";
import { TableRow } from "src/ui/extensions/table/table-row/table-row";
import { HorizontalRule } from "src/ui/extensions/horizontal-rule";
import ReadOnlyImageExtension from "../extensions/image/read-only-image";
import { isValidHttpUrl } from "../../lib/utils";
import { Mentions } from "../mentions";
import { IMentionSuggestion } from "@plane/editor-types";
import { ReadOnlyImageExtension } from "src/ui/extensions/image/read-only-image";
import { isValidHttpUrl } from "src/lib/utils";
import { Mentions } from "src/ui/mentions";
import { IMentionSuggestion } from "src/types/mention-suggestion";
export const CoreReadOnlyEditorExtensions = (mentionConfig: {
mentionSuggestions: IMentionSuggestion[];
@@ -71,6 +72,7 @@ export const CoreReadOnlyEditorExtensions = (mentionConfig: {
class: "rounded-lg border border-custom-border-300",
},
}),
HorizontalRule,
TiptapUnderline,
TextStyle,
Color,
+12 -2
View File
@@ -1,5 +1,15 @@
{
"extends": "tsconfig/react-library.json",
"include": ["src/**/*", "index.d.ts"],
"exclude": ["dist", "build", "node_modules"]
"include": [
"src/**/*",
"index.d.ts"
],
"exclude": [
"dist",
"build",
"node_modules"
],
"compilerOptions": {
"baseUrl": "."
}
}
+5 -7
View File
@@ -30,13 +30,11 @@
"dependencies": {
"@plane/editor-core": "*",
"@plane/editor-extensions": "*",
"@plane/editor-types": "*",
"@plane/ui": "*",
"@tiptap/core": "^2.1.7",
"@tiptap/extension-placeholder": "^2.1.11",
"@tiptap/pm": "^2.1.12",
"@tiptap/suggestion": "^2.1.12",
"eslint": "8.36.0",
"@tiptap/core": "^2.1.13",
"@tiptap/extension-placeholder": "^2.1.13",
"@tiptap/pm": "^2.1.13",
"@tiptap/suggestion": "^2.1.13",
"eslint-config-next": "13.2.4",
"react-popper": "^2.3.0",
"tippy.js": "^6.3.7",
@@ -46,7 +44,7 @@
"@types/node": "18.15.3",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.2.17",
"eslint": "^7.32.0",
"eslint": "8.36.0",
"postcss": "^8.4.29",
"tailwind-config-custom": "*",
"tsconfig": "*",
@@ -1,6 +1,5 @@
import { Editor } from "@tiptap/react";
import { useState } from "react";
import { IMarking } from "..";
import { IMarking } from "src/types/editor-types";
export const useEditorMarkings = () => {
const [markings, setMarkings] = useState<IMarking[]>([]);
+3 -3
View File
@@ -1,3 +1,3 @@
export { DocumentEditor, DocumentEditorWithRef } from "./ui";
export { DocumentReadOnlyEditor, DocumentReadOnlyEditorWithRef } from "./ui/readonly";
export { FixedMenu } from "./ui/menu/fixed-menu";
export { DocumentEditor, DocumentEditorWithRef } from "src/ui";
export { DocumentReadOnlyEditor, DocumentReadOnlyEditorWithRef } from "src/ui/readonly";
export { FixedMenu } from "src/ui/menu/fixed-menu";
@@ -5,3 +5,9 @@ export interface DocumentDetails {
last_updated_by: string;
last_updated_at: Date;
}
export interface IMarking {
type: "heading";
level: number;
text: string;
sequence: number;
}
@@ -1,12 +1,11 @@
import { Icon } from "lucide-react";
import { LucideIconType } from "@plane/editor-core";
interface IAlertLabelProps {
Icon?: Icon;
Icon?: LucideIconType;
backgroundColor: string;
textColor?: string;
label: string;
}
export const AlertLabel = (props: IAlertLabelProps) => {
const { Icon, backgroundColor, textColor, label } = props;
@@ -1,7 +1,7 @@
import { HeadingComp, HeadingThreeComp, SubheadingComp } from "./heading-component";
import { IMarking } from "..";
import { HeadingComp, HeadingThreeComp, SubheadingComp } from "src/ui/components/heading-component";
import { IMarking } from "src/types/editor-types";
import { Editor } from "@tiptap/react";
import { scrollSummary } from "../utils/editor-summary-utils";
import { scrollSummary } from "src/utils/editor-summary-utils";
interface ContentBrowserProps {
editor: Editor;
@@ -1,13 +1,12 @@
import { Editor } from "@tiptap/react";
import { Archive, RefreshCw, Lock } from "lucide-react";
import { IMarking } from "..";
import { FixedMenu } from "../menu";
import { UploadImage } from "@plane/editor-types";
import { DocumentDetails } from "../types/editor-types";
import { AlertLabel } from "./alert-label";
import { IVerticalDropdownItemProps, VerticalDropdownMenu } from "./vertical-dropdown-menu";
import { SummaryPopover } from "./summary-popover";
import { InfoPopover } from "./info-popover";
import { IMarking, DocumentDetails } from "src/types/editor-types";
import { FixedMenu } from "src/ui/menu";
import { UploadImage } from "@plane/editor-core";
import { AlertLabel } from "src/ui/components/alert-label";
import { IVerticalDropdownItemProps, VerticalDropdownMenu } from "src/ui/components/vertical-dropdown-menu";
import { SummaryPopover } from "src/ui/components/summary-popover";
import { InfoPopover } from "src/ui/components/info-popover";
interface IEditorHeader {
editor: Editor;
@@ -2,7 +2,7 @@ import { useState } from "react";
import { usePopper } from "react-popper";
import { Calendar, History, Info } from "lucide-react";
// types
import { DocumentDetails } from "../types/editor-types";
import { DocumentDetails } from "src/types/editor-types";
type Props = {
documentDetails: DocumentDetails;
@@ -1,7 +1,7 @@
import { EditorContainer, EditorContentWrapper } from "@plane/editor-core";
import { Editor } from "@tiptap/react";
import { useState } from "react";
import { DocumentDetails } from "../types/editor-types";
import { DocumentDetails } from "src/types/editor-types";
type IPageRenderer = {
documentDetails: DocumentDetails;
@@ -3,9 +3,9 @@ import { Editor } from "@tiptap/react";
import { usePopper } from "react-popper";
import { List } from "lucide-react";
// components
import { ContentBrowser } from "./content-browser";
import { ContentBrowser } from "src/ui/components/content-browser";
// types
import { IMarking } from "..";
import { IMarking } from "src/types/editor-types";
type Props = {
editor: Editor;
@@ -1,6 +1,6 @@
import { Editor } from "@tiptap/react";
import { IMarking } from "..";
import { ContentBrowser } from "./content-browser";
import { IMarking } from "src/types/editor-types";
import { ContentBrowser } from "src/ui/components/content-browser";
interface ISummarySideBarProps {
editor: Editor;
@@ -8,14 +8,12 @@ interface ISummarySideBarProps {
sidePeekVisible: boolean;
}
export const SummarySideBar = ({ editor, markings, sidePeekVisible }: ISummarySideBarProps) => {
return (
<div
className={`h-full transform overflow-hidden p-5 transition-all duration-200 ${
sidePeekVisible ? "translate-x-0" : "-translate-x-full"
}`}
>
<ContentBrowser editor={editor} markings={markings} />
</div>
);
};
export const SummarySideBar = ({ editor, markings, sidePeekVisible }: ISummarySideBarProps) => (
<div
className={`h-full transform overflow-hidden p-5 transition-all duration-200 ${
sidePeekVisible ? "translate-x-0" : "-translate-x-full"
}`}
>
<ContentBrowser editor={editor} markings={markings} />
</div>
);
@@ -1,5 +1,6 @@
import { Button, CustomMenu } from "@plane/ui";
import { ChevronUp, Icon, MoreVertical } from "lucide-react";
import { LucideIconType } from "@plane/editor-core";
import { CustomMenu } from "@plane/ui";
import { MoreVertical } from "lucide-react";
type TMenuItems =
| "archive_page"
@@ -14,7 +15,7 @@ type TMenuItems =
export interface IVerticalDropdownItemProps {
key: number;
type: TMenuItems;
Icon: Icon;
Icon: LucideIconType;
label: string;
action: () => Promise<void> | void;
}
@@ -23,27 +24,23 @@ export interface IVerticalDropdownMenuProps {
items: IVerticalDropdownItemProps[];
}
const VerticalDropdownItem = ({ Icon, label, action }: IVerticalDropdownItemProps) => {
return (
<CustomMenu.MenuItem onClick={action} className="flex items-center gap-2">
<Icon className="h-3 w-3" />
<div className="text-custom-text-300">{label}</div>
</CustomMenu.MenuItem>
);
};
const VerticalDropdownItem = ({ Icon, label, action }: IVerticalDropdownItemProps) => (
<CustomMenu.MenuItem onClick={action} className="flex items-center gap-2">
<Icon className="h-3 w-3" />
<div className="text-custom-text-300">{label}</div>
</CustomMenu.MenuItem>
);
export const VerticalDropdownMenu = ({ items }: IVerticalDropdownMenuProps) => {
return (
<CustomMenu
maxHeight={"md"}
className={"h-4.5 mt-1"}
placement={"bottom-start"}
optionsClassName={"border-custom-border border-r border-solid transition-all duration-200 ease-in-out "}
customButton={<MoreVertical size={14} />}
>
{items.map((item, index) => (
<VerticalDropdownItem key={index} type={item.type} Icon={item.Icon} label={item.label} action={item.action} />
))}
</CustomMenu>
);
};
export const VerticalDropdownMenu = ({ items }: IVerticalDropdownMenuProps) => (
<CustomMenu
maxHeight={"md"}
className={"h-4.5 mt-1"}
placement={"bottom-start"}
optionsClassName={"border-custom-border border-r border-solid transition-all duration-200 ease-in-out "}
customButton={<MoreVertical size={14} />}
>
{items.map((item) => (
<VerticalDropdownItem key={item.key} type={item.type} Icon={item.Icon} label={item.label} action={item.action} />
))}
</CustomMenu>
);

Some files were not shown because too many files have changed in this diff Show More