Compare commits

..
Author SHA1 Message Date
Pushya Mitra Thiruvooru 0046d54d25 version upgrade to 1.2.0 2025-12-09 23:23:53 +05:30
69b64680d1 [WIKI-829] fix: add option to only show placeholder on empty editor (#8232)
* feat: add placeholderOnEmpty functionality to editor components

* Update packages/editor/src/core/extensions/placeholder.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* refactor: rename placeholderOnEmpty to showPlaceholderOnEmpty across editor components

* chore : make optional

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-09 21:13:20 +05:30
Vamsi KrishnaandGitHub 2f45bfb7f6 [WEB-5256]chore: quick actions refactor (#8019)
* chore: quick actions refactor

* chore: lint fix

* chore: unified factory for actions

* chore: lint fix

* * chore: removed redundant files
* chore: updated imports

* chore: updated interfaces to types

* chore: updated undefined handling
2025-12-09 21:12:15 +05:30
NikhilandGitHub 4b59998e52 [WEB-5592] chore: add static files update settings for static files support (#8251)
* chore: add static files collection and update settings for static files support

* chore: add WhiteNoise middleware for static file handling

* chore(deps): upgrade WhiteNoise to version 6.11.0 and add static file reverse proxy in Caddyfile
2025-12-09 21:05:26 +05:30
b-saikrishnakanthandGitHub f70384bff7 [WEB-5603] feat: enhance workspace settings layout and members page (#8266)
* feat: enhance workspace settings layout and members page with new components

* refactor: update workspace settings layout and members page to use default exports

* refactor: settings layout import changes

* refactor: simplify workspaceSlug usage in settings layout
2025-12-09 21:04:33 +05:30
pratapalakshmiandGitHub 7caa1bb482 [PAI-963] feat: enhance CustomSelect component with context for dropdown management (#8202)
* feat: enhance CustomSelect component with context for dropdown management

* refactor: streamline CustomSelect component structure and improve dropdown options rendering
2025-12-09 20:57:15 +05:30
Anmol Singh BhatiaandGitHub af939fca41 [WEB-5604] Label layout title column and content wrapper styling #8273 2025-12-09 18:37:46 +05:30
sriram veeraghantaandGitHub a3e651854a fix: updated npmrc with hoist patterns (#8271) 2025-12-09 16:32:49 +05:30
NikhilandGitHub 2240ac0e74 [WEB-5583]feat: add avatar download and upload functionality in authentication adapter (#8247)
* feat: add avatar download and upload functionality in authentication adapter

- Implemented `download_and_upload_avatar` method to fetch and store user avatars from OAuth providers.
- Enhanced user data saving process to include avatar handling.
- Updated `S3Storage` class with a new `upload_file` method for direct file uploads to S3.

* feat: enhance avatar download functionality with size limit checks

- Added checks for content length before downloading avatar images to ensure they do not exceed the maximum allowed size.
- Implemented chunked downloading of avatar images to handle large files efficiently.
- Updated the upload process to return None if the upload fails, improving error handling.

* feat: improve avatar filename generation with content type handling

- Refactored avatar download logic to determine file extension based on the content type from the response headers.
- Removed redundant code for extension mapping, ensuring a cleaner implementation.
- Enhanced error handling by returning None for unsupported content types.

* fix: remove authorization header for avatar download

- Updated the avatar download logic to remove the Authorization header when token data is not present, ensuring compatibility with scenarios where authentication is not required.

* feat: add method for avatar download headers

- Introduced `get_avatar_download_headers` method to centralize header management for avatar downloads.
- Updated `download_and_upload_avatar` method to utilize the new header method, improving code clarity and maintainability.
2025-12-09 15:48:27 +05:30
AaronandGitHub 11e7bd115b docs: eslint (#8269) 2025-12-09 13:26:22 +05:30
0ab94ed6d6 chore: run fixes (#8257)
* chore: run fixes

* fix: type, just use hocuspocusservercontext

* fix: codemod

---------

Co-authored-by: Palanikannan M <akashmalinimurugu@gmail.com>
2025-12-08 22:26:50 +05:30
a9e9cb2983 fix: activity tracking description (#8268)
* feat: add no_activity flag to control issue activity tracking during partial updates

* refactor: rename no_activity flag to skip_activity for clarity in issue activity tracking

* enhance description input handling with migration update support

* feat: implement skip_activity flag to conditionally log issue updates during partial updates

* refactor: skip-activity

* feat: add migration description update check to conditionally log issue updates

---------

Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
2025-12-08 22:18:14 +05:30
Anmol Singh BhatiaandGitHub f0bc2bd3bd [WEB-5600] chore: project identifier char limit updated and table layout enhancements (#8263) 2025-12-08 20:00:54 +05:30
Prateek ShouryaandGitHub 7659997b53 [WEB-5594] feat: enhance authentication method handling in member columns and introduce new login labels (#8260) 2025-12-08 18:25:48 +05:30
Prateek ShouryaandGitHub 316856a555 [WEB-5599] refactor: enhance Kanban swimlane components with improved props and structure (#8262) 2025-12-08 18:17:29 +05:30
Anmol Singh BhatiaandGitHub f41e121e58 [WEB-5317] chore: enable multi-select for use case in onboarding flow (#8049)
* chore: update use_case type from string to array

* chore: convert use_case field to JSONField with array support

* feat: implement multi-select UI for use case in onboarding

* chore: code refactor

* chore: revert backend changes

* chore: code refactor

* chore: code refactor

* chore: code refactor
2025-12-08 15:48:15 +05:30
sriram veeraghantaandGitHub 85daa1572c fix: upgrade turbo version (#8259) 2025-12-08 15:46:23 +05:30
Aaryan KhandelwalandGitHub b359849606 [WIKI-840] chore: accept spaces while searching for mentions #8258 2025-12-08 15:16:22 +05:30
b-saikrishnakanthandGitHub 5ea74e1112 [WEB-5591] chore: update discount info component to use local SVG assets #8250 2025-12-08 13:47:26 +05:30
Anmol Singh BhatiaandGitHub d9ea119588 [WEB-5589] chore: intake icon updated #8249 2025-12-08 13:46:23 +05:30
NikhilandGitHub d34c7f9a0e [WEB-5254] chore: add bot user to create workspace seed data (#8225)
* chore: add bot user to workspace seed task

* refactor: use BotTypeEnum for bot type in workspace seed task

* refactor: update bot user display name and last name in workspace seed task

* fix: return empty dictionary for missing cycle and module seeds in workspace seed task
2025-12-05 18:03:58 +05:30
NikhilandGitHub f81e120328 chore(deps): upgrade psycopg packages to version 3.3.0 (#8222)
* chore(deps): upgrade psycopg packages to version 3.3.0

* chore: update Python version to 3.12.x in CI workflow

* refactor: clean up imports and improve code formatting across multiple files
2025-12-05 16:06:19 +05:30
85d90030cf fix: eslint (#8185)
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
2025-12-05 16:03:51 +05:30
M. PalanikannanandGitHub 82c970ac4b [WIKI-804] fix: refactor image uploader (#8210)
* fix: refactor uploader

* fix: props

* fix: sites fix
2025-12-05 13:20:15 +05:30
Anmol Singh BhatiaandGitHub 392c8cf2e1 [WEB-5582] chore: top nav and user menu improvement (#8245)
* chore: user menu code refactor

* chore: CustomizeNavigationDialog enhancements
2025-12-04 21:25:09 +05:30
sriram veeraghantaandGitHub c3906048ea fix(CI): upgrade prettier oxc plugin version (#8242)
* fix: upgrade prettier oxc plugin version

* fix: type errors
2025-12-04 18:27:50 +05:30
Anmol Singh BhatiaandGitHub 1090b3e938 [WEB-5573] refactor: app rail enhancements (#8239)
* chore: app rail context added

* chore: dock/undock app rail implementation

* chore: refactor

* chore: code refactor

* chore: code refactor
2025-12-04 18:14:59 +05:30
sriramveeraghanta fe867135c4 Merge branch 'preview' of github.com:makeplane/plane into canary 2025-12-04 16:35:46 +05:30
sriramveeraghanta 65166d19be fix: docker ngnix version 2025-12-04 16:35:19 +05:30
sriramveeraghanta 3bc85c8430 fix: docker pnpm installation setup 2025-12-04 16:30:42 +05:30
sriramveeraghanta cf84ade52c fix: turbo version upgrade in docker files 2025-12-04 16:11:59 +05:30
Anmol Singh BhatiaandGitHub 9699a01fb8 [WEB-5572] fix storybook 500 error #8231 2025-12-04 15:37:14 +05:30
Prateek ShouryaandGitHub bc96d34cb7 [WEB-5576] fix: remove optionsClassName from email and workspace forms (#8240) 2025-12-04 15:36:39 +05:30
Vipin ChaudharyandGitHub 739b1bfb75 fix: undo unique id (#8238) 2025-12-04 14:45:43 +05:30
NikhilandGitHub 22da26742c chore(deps): update Django version to 4.2.27 in base requirements (#8237) 2025-12-04 14:07:52 +05:30
Prateek ShouryaandGitHub 63f3a57022 chore: add permanent redirects for /spaces and /god-mode in Caddyfile (#8236) 2025-12-04 14:03:07 +05:30
36d42856e9 [WEB-5493] feat: implement static cover image handling and selection (#8184)
* feat: implement cover image handling and static image selection

- Added functionality to handle cover image uploads and selections in project and profile forms.
- Introduced a new helper for managing cover images, including static images and uploaded assets.
- Updated components to utilize the new cover image helper for displaying and processing cover images.
- Added a set of static cover images for selection in the image picker.
- Enhanced error handling for image uploads and processing.

This update improves the user experience by providing a more robust cover image management system.

* refactor: rename STATIC_COVER_IMAGES_ARRAY to STATIC_COVER_IMAGES for consistency

- Updated the cover image helper to export STATIC_COVER_IMAGES instead of STATIC_COVER_IMAGES_ARRAY.
- Adjusted the ImagePickerPopover component to utilize the renamed export for rendering static cover images.

* feat: enhance project creation and image handling

- Introduced default project form values with a random emoji for logo props.
- Updated cover image handling in various components, ensuring consistent usage of the new cover image helper.
- Refactored image picker to improve search functionality and loading states.
- Removed unused constants and streamlined cover image type checks for better clarity and performance.

This update enhances the user experience in project creation and image selection processes.

* refactor: simplify cover image type definition and clean up code

- Removed duplicate type from TCoverImageType, streamlining the definition.
- Cleaned up whitespace in the cover image helper for improved readability.

This update enhances code clarity and maintains consistency in cover image handling.

* refactor: update cover image type definitions and simplify logic

- Changed ICoverImageResult and ICoverImagePayload interfaces to type aliases for better clarity.
- Simplified the logic in getCoverImageDisplayURL function to enhance readability and maintainability.

This update improves the structure and clarity of the cover image helper code.

* refactor: remove unused project cover image endpoint and update cover image handling

- Removed the ProjectPublicCoverImagesEndpoint and its associated URL from the project.
- Updated the cover image handling in the cover-image helper to utilize imported assets instead of static paths.
- Cleaned up the ProjectFavoritesViewSet and FileService by removing the now obsolete getProjectCoverImages method.

This update streamlines the cover image management and eliminates unnecessary code, enhancing overall maintainability.

* refactor: update cover image imports to new asset structure

- Replaced static path imports for cover images with updated paths to the new asset structure.
- This change improves organization and maintainability of cover image assets in the project.

This update aligns with recent refactoring efforts to streamline cover image handling.

* feat: add additional cover images to the helper

- Imported new cover images (24 to 29) into the cover-image helper.
- This update expands the available cover image options for use in the project, enhancing visual variety.

* refactor: remove ProjectPublicCoverImagesEndpoint from project URLs and views

* refactor: update cover image imports to include URL query parameter

- Modified cover image imports in the cover-image helper to append a URL query parameter for better asset handling.
- This change enhances the way cover images are processed and utilized within the project.

* refactor: extract default project form values into a utility function

- Created a new utility function `getProjectFormValues` to encapsulate the default project form values.
- Updated the `CreateProjectForm` component to use this utility function for setting default form values, improving code organization and maintainability.

* feat: integrate project update functionality in CreateProjectForm

- Added `updateProject` method to the `CreateProjectForm` component for updating project cover images after creation.
- Enhanced cover image handling by ensuring the correct URL is set for both uploaded and existing cover images.
This update improves the project creation workflow and ensures cover images are accurately updated.

* fix: update documentation for cover image handling

- Corrected the comment regarding local static images to reflect that they are served from the assets folder instead of the public folder.
- This change ensures accurate documentation for the `getCoverImageType` and `getCoverImageDisplayURL` functions, improving clarity for future developers.

* feat: implement random cover image selection for project forms

- Replaced the default cover image URL with a new utility function `getRandomCoverImage` that selects a random cover image from the available options.
- Updated the `getProjectFormValues` function to utilize this new method, enhancing the project creation experience with varied cover images.

---------

Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
2025-12-03 16:20:38 +05:30
Anmol Singh BhatiaandGitHub 105ac5ece5 [WEB-5569] chore: top nav search enhancements (#8226)
* chore: top nav power k search menu enhancements

* chore: expandable search panel refactor
2025-12-03 16:09:12 +05:30
SangeethaandGitHub b8a41ad5a0 [WEB-5560] fix: restrict guest users to view all details of a workspace members (#8215)
* fix: separate retrieve method in WorkspaceMemberViewSet

* fix: non project members accessing member detail:

* chore: error handle

* fix: role based response

* fix: use Enum
2025-12-03 16:06:46 +05:30
7c74d0a403 [WEB-5290] feat: selfhosted check (#8227)
* feat: add in common py

* fix: update marketing consent screen based on is self managed flag

* improvement: enhance ImagePickerPopover with dynamic tab options based on Unsplash configuration

* refactor: product updates modal to include changelog

* [WEB-5290] feat: implement fallback for product updates changelog with loading state and error handling

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-12-03 15:53:42 +05:30
Gustavo de OliveiraandGitHub 5f7ffcb37a - Add SIGNED_URL_EXPIRATION environment variable (#8136)
- Update S3Storage to use configurable expiration time
  - Default remains 3600 seconds (1 hour) for backward compatibility
  - Add comprehensive unit tests with mocked S3 client
  - Update .env.example with documentation and examples
2025-12-03 10:52:19 +05:30
Samuel TorresandGitHub 584a1aa725 fix: PATCH endpoint project estimate validation (#7872) 2025-12-03 01:44:31 +05:30
Saurabh KumarandGitHub 1e1520b85f [SILO-699] chore: add check for feature enabled for module and cycle create (#8146)
* add check for feature enabled for module and cycle create

* add more checks
2025-12-03 01:26:52 +05:30
b-saikrishnakanthandGitHub 0bc45e3047 [WEB-5503] fix: enhance error handling for label creation and update operations (#8175)
* fix: enhance error handling for label creation and update operations

* fix: improve error handling for label creation and update operations

* refactor: change error codes from enum to object for label operations

* refactor: update error code references in label handling to use consistent naming

* fix: improve error handling for label creation and update
2025-12-03 00:05:44 +05:30
Prateek ShouryaandGitHub cacd1b489e [WEB-5559] improvement: chat support functionality and remove Intercom provider (#8217)
* [WEB-5559] improve: chat support functionality and remove Intercom provider

- Added ChatSupportModal component for chat support integration.
- Replaced IntercomProvider with ChatSupportModal in AppProvider.
- Introduced useChatSupport hook to manage chat support state and actions.
- Updated help commands to utilize chat support instead of Intercom.
- Removed obsolete Intercom-related components and hooks.

* refactor: lazy load ChatSupportModal in AppProvider
2025-12-03 00:03:56 +05:30
Anmol Singh BhatiaandGitHub e650b19933 [WEB-5556] chore: tab navigation and sidebar improvements (#8218) 2025-12-02 18:05:01 +05:30
sriram veeraghantaandGitHub ec478a8979 chore: standard replacement from dotenv to dotenvx (#8216) 2025-12-02 15:32:00 +05:30
sriramveeraghanta e07d91e857 fix: update express version in overrides 2025-12-02 15:09:25 +05:30
sriramveeraghanta 9ccb3e321a chore(deps): upgrade express version 2025-12-02 15:01:12 +05:30
sriramveeraghanta f2c046dff9 fix: update mdast-util-to-hast package in overrides 2025-12-02 14:58:06 +05:30
Anmol Singh BhatiaandGitHub 2a378b3bc1 [WEB-5556] chore: tab navigation project header enhancement (#8212) 2025-12-02 14:35:19 +05:30
SangeethaandGitHub 8b0a797906 fix: import error (#8213) 2025-12-02 13:55:54 +05:30
Saurabh KumarandGitHub cea6f7530b [SILO-671] feat: add sticky external apis (#8139)
* add sticky external apis

* add created_at sort by to list

* remove select related method from query set
2025-12-01 18:57:54 +05:30
NikhilandGitHub a7e2e596bf [WEB-5518]: update magic code token to send code as 6 digit numbers (#8188)
* refactor: simplify token generation in MagicCodeProvider by using a numeric approach

* fix: update placeholder text for unique code input across multiple languages

* refactor: replace token generation with a numeric approach for user email updates

* fix: update placeholder text for unique code input in multiple languages to a numeric format

* refactor: replace random token generation with secrets for enhanced security in user email updates and magic code provider
2025-12-01 18:56:14 +05:30
Anmol Singh BhatiaandGitHub 980428b204 [WEB-5536] feat: prevent search panels from reopening on programmatic focus restoration (#8207) 2025-12-01 18:37:06 +05:30
Anmol Singh BhatiaandGitHub f428c3bdaf [WEB-5542] chore: scrollIntoView implementation for sidebar active project (#8208) 2025-12-01 17:43:05 +05:30
Prateek ShouryaandGitHub a05cd88a53 [WEB-5491] refactor: onboarding tour components (#8167) 2025-12-01 17:14:28 +05:30
60220801ac [WEB-4338] fix: incorrect error code in project retrieve API (#7234)
* fix: project error message and status code

* fix: incorrect member role check

* fix: project error message and status code

* fix: improve project permission checks and error handling in ProjectViewSet

* feat: enhance project settings layout with better loading strategy and fix all flicker

* fix: prevent rendering during project loading in ProjectAuthWrapper

* refactor: adjust layout structure in ProjectDetailSettingsLayout and enhance access restriction logic in ProjectAccessRestriction

* refactor: replace ProjectAccessRestriction component with updated version and enhance error handling

- Deleted the old ProjectAccessRestriction component.
- Introduced a new ProjectAccessRestriction component with improved error handling and user prompts for joining projects.
- Updated translations for new error states in multiple languages.

* fix: enhance error handling in IssueDetailsPage and remove JoinProject component

---------

Co-authored-by: Dheeraj Kumar Ketireddy <dheeru0198@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
2025-12-01 17:14:01 +05:30
Vipin ChaudharyandGitHub 8db95d9ec0 [WIKI-823] fix: callout element emoji search (#8201)
* fix: emoji search input

* fix: enhance keyboard navigation in EmojiPicker component
2025-12-01 13:37:20 +05:30
b-saikrishnakanthandGitHub 27bf2575bd [WEB-5534] fix: intake state dropdown (#8199) 2025-12-01 12:50:01 +05:30
b-saikrishnakanthandGitHub 22bb3c5ecc [WEB-5490] fix: intake section filter persists incorrectly across projects (#8187) 2025-12-01 12:49:05 +05:30
Aaryan KhandelwalandGitHub 6b85d67f6c [WIKI-788] regression: copy markdown option #8200 2025-12-01 12:48:28 +05:30
Prateek ShouryaandGitHub 123f59e74b [WEB-5525] improvement: update WorkspaceMenuRoot to use variant prop for layout adjustments (#8196) 2025-11-28 19:00:25 +05:30
sriram veeraghantaandGitHub c7bf912cf2 fix: state group choices (#8198) 2025-11-28 18:06:00 +05:30
Aaryan KhandelwalandGitHub 2980836015 [WEB-5527] fix: extended sidebar (#8197) 2025-11-28 16:54:53 +05:30
78fbdde165 [WEB-5282] chore: triage state in intake (#8135)
* chore: traige state in intake

* chore: triage state changes

* feat: implement intake state dropdown component and integrate into issue properties

* chore: added the triage state validation

* chore: added triage state filter

* chore: added workspace filter

* fix: migration file

* chore: added triage group state check

* chore: updated the filters

* chore: updated the filters

* chore: added variables for intake state

* fix: import error

* refactor: improve project intake state retrieval logic and update TriageGroupIcon component

* chore: changed the intake validation logic

* refactor: update intake state types and clean up unused interfaces

* chore: changed the state color

* chore: changed the update serializer

* chore: updated with current instance

* chore: update TriageGroupIcon color to match new intake state group color

* chore: stringified value

* chore: added validation in serializer

* chore: added logger instead of print

* fix: correct component closing syntax in ActiveProjectItem

* chore: updated the migration file

* chore: added noop in migation

---------

Co-authored-by: b-saikrishnakanth <bsaikrishnakanth97@gmail.com>
2025-11-28 16:16:48 +05:30
b-saikrishnakanthandGitHub dbc5a6348d fix: disable timezone selection button for non-admin users (#8195) 2025-11-28 16:14:43 +05:30
Aaryan KhandelwalandGitHub c685042a47 regression: projects breadcrumb in accordion layout (#8194) 2025-11-28 14:05:38 +05:30
Vipin ChaudharyandGitHub a4de486cf7 [WIKI-811] fix: ensure only non-deleted project pages are retrieved in page queries (#8182)
* fix: ensure soft delete handling for pages in PageViewSet methods

* refactor: streamline query for project IDs in PageDuplicateEndpoint

* refactor: remove soft delete condition from ProjectPage queries in PageViewSet and PageDuplicateEndpoint

* refactor: simplify ProjectPage query in PageViewSet for improved readability

* refactor: replace filter with get for Page queries in PageViewSet and PageDuplicateEndpoint to enhance clarity

* refactor: replace filter with get for Page queries in PagesDescriptionViewSet to improve efficiency
2025-11-27 20:55:50 +05:30
Prateek ShouryaandGitHub 3c84e75350 [WEB-5510] fix: handle null values in context indicator for improved stability (#8190) 2025-11-27 20:53:42 +05:30
Aaryan KhandelwalandGitHub 39749106a2 regression: sidebar toggle button position (#8186)
* fix: sidebar toggle button position

* chore: remove border radius
2025-11-27 20:53:12 +05:30
Aaryan KhandelwalandGitHub 9bcb1fa469 [WEB-5515]: comments ordering (#8193)
* fix: comments ordering

* fix: comment timestamp:
2025-11-27 20:51:06 +05:30
SangeethaandGitHub c31a225775 [WEB-5506] fix: new navigation pre release bugs (#8181)
* chore: update navigation_project_limit and navigation_control_preference

* chore: set default true for user specific widgets

* chore: use serializer in ProjectMemberPreferenceEndpoint
chore: use serializer in WorkspaceUserPropertiesEndpoint
"

* fix: validate preferences

* fix: status code

* fix: remove saving from validate

* fix: simply validate_preferences

* chore: create WorkspaceUserProperties if it doesn't exist

* fix: create WorksapceUserProperties it not exist

* fix: copy the instance

* Revert "fix: copy the instance"

This reverts commit ddb0384b6d.

* chore: migrate WorkspaceUserPreference to set defaults

* fix: migration file name

* Revert "fix: migration file name"

This reverts commit 80a21dedf1.

* Revert "chore: migrate WorkspaceUserPreference to set defaults"

This reverts commit 25bc583a08.
2025-11-27 18:12:20 +05:30
sriramveeraghanta 73c317f283 chore(deps): adding pacakges to resolutions to resolve vulnerbailities 2025-11-27 16:37:36 +05:30
Aaryan KhandelwalandGitHub a0da806a79 [WEB-5520] fix: comments UI in space app #8189 2025-11-27 15:58:10 +05:30
Aaryan KhandelwalandGitHub eddf80aaed [WEB-5511] regression: revamped navigation UI bugs (#8183) 2025-11-26 18:51:03 +05:30
Aaryan KhandelwalandGitHub 05b1c147a9 [WEB-5506] regression: navigation revamp bugs (#8180) 2025-11-26 16:25:29 +05:30
Prateek ShouryaandGitHub ae7898aaee fix: move X-Frame-Options header to auth page for enhanced security (#8179) 2025-11-26 13:57:46 +05:30
Anmol Singh BhatiaandGitHub 4806bdf99c [WEB-5170] feat: navigation revamp (#8162) 2025-11-26 12:56:11 +05:30
Prateek ShouryaandGitHub 37c59ef0d1 [WEB-5507] fix: remove module checks in analytics sidebar link handlers (#8177) 2025-11-26 00:02:14 +05:30
Prateek ShouryaandGitHub 3f11183768 [WEB-5508] fix: improve error handling in AuthFormRoot by ensuring safe access to error_code (#8178) 2025-11-25 23:59:21 +05:30
Aaryan KhandelwalandGitHub d38147b875 fix: build error (#8171) 2025-11-25 19:15:35 +05:30
Prateek ShouryaandGitHub 3436c4f1f5 [WEB-5501] refactor: optimize component structures and improve hooks (#8174)
* [WEB-5501] refactor: optimize component structures and improve hooks

- Updated type definitions in AppProvider to use React.ReactNode for children.
- Enhanced HomePeekOverviewsRoot by using MobX observer and integrating issue detail hook.
- Optimized ContentOverflowWrapper to prevent unnecessary re-renders by adjusting useEffect dependencies.
- Updated DashboardQuickLinks to include necessary dependencies in useCallback.
- Refactored GlobalShortcutsProvider to utilize refs for context and handler management, improving performance.
- Changed useCurrentTime to update every minute instead of every second.
- Refactored outside click hooks to use useCallback for better performance.
- Improved IntercomProvider and PostHogProvider to prevent multiple initializations using refs.

* refactor: simplify conditional rendering in HomePeekOverviewsRoot component

* refactor: improve outside click detection in sidebar and peek overview hooks

* refactor: enhance IntercomProvider and PostHogProvider with hydration state management
2025-11-25 18:52:20 +05:30
sriramveeraghanta 31e8563725 chore(deps): upgrade sentry pacakges 2025-11-25 16:25:07 +05:30
b-saikrishnakanthandGitHub 5ddfd0e1a9 [WEB-5497] fix: update change email button label for localization consistency #8173 2025-11-25 15:47:14 +05:30
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ef99f8bbca chore(deps): bump @sentry/node (#8169)
Bumps the npm_and_yarn group with 1 update in the / directory: [@sentry/node](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/node` from 10.24.0 to 10.27.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/10.24.0...10.27.0)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-version: 10.27.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-25 13:35:01 +05:30
2804987fe8 [WEB-5358] fix: analytics enhancements (#8150)
* refactor: enhance analytics page tab functionality and UI

- Introduced state management for selected tabs using useState and useEffect hooks.
- Updated tab handling to improve user experience with onValueChange for Tabs component.
- Refactored AnalyticsFilterActions to remove unused duration selection.
- Added Tooltip to project name in ActiveProjectItem for better visibility.
- Minor styling adjustments in Tabs component for improved layout consistency.

* refactor: improve tab layout in analytics page by adding w-fit

* fix: update styling for ActiveProjectItem component

* refactor: simplify analytics page and introduce useAnalyticsTabs hook

- Removed unused imports and optimized the analytics page component.
- Replaced getAnalyticsTabs with a new custom hook useAnalyticsTabs for better modularity.
- Added useAnalyticsTabs hook to manage analytics tab logic.
- Created new files for useAnalyticsTabs and analytics tabs in the 'ce' and 'ee' directories.

* fix: ensure consistent export in use-analytics-tabs file

* style: format code for better readability in AnalyticsPage component

* fix: add missing newline at end of file in use-analytics-tabs

* chore: remove unused analytics tab components

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-24 21:29:34 +05:30
09f4e3d4ae [WIKI-774] refactor: space app mentions #8152
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-24 21:26:48 +05:30
7c8cbc4ead [WEB-4428] fix: duplicate labels with case insensitive (#7388)
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-24 21:22:17 +05:30
ce6299937f [WEB-5430] feat: allow users to change email (#8120)
* feat: change user email

* chore: optimised the logic

* feat: add email change functionality and related modals in profile form

* refactor: format checkEmail method for improved readability

* chore: added rate limit exceeded validation

* feat: implement change email modal with localization support

- Added translation support for the change email modal, including titles, descriptions, and error messages.
- Integrated the useTranslation hook for dynamic text rendering.
- Updated form validation messages to utilize localized strings.
- Enhanced user feedback with localized success and error toast messages.
- Updated button labels and placeholders to reflect localization changes.

* chore: added extra validation in cache key

* fix: format files

---------

Co-authored-by: b-saikrishnakanth <bsaikrishnakanth97@gmail.com>
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-24 21:21:52 +05:30
Dheeraj Kumar KetireddyandGitHub d6fce114d6 [SILO-663] chore: enhance error handling in ComplexFilterBackend with DRFValidationError (#8090)
* [SILO-663] chore: enhance error handling in ComplexFilterBackend with DRFValidationError

* Log the exception and re-raise it
2025-11-24 21:14:14 +05:30
Prateek ShouryaandGitHub e6d584fde7 [WEB-5489] fix: prevent AppRail hook usage outside context in disabled workspace components (#8164) 2025-11-24 16:03:36 +05:30
sriram veeraghantaandGitHub 0240e46f04 fix: live server docker build changes (#8166) 2025-11-24 14:08:37 +05:30
e36f4f47f1 [MOB-1199] dev: update index constraints for notifications to optimize query performance (#7870)
* dev: updated the index constraints for notification

* dev: updated migration file with AddIndexConcurrently

* dev: handled indexing for file asset with asset

* bumped migration sequence number

---------

Co-authored-by: Dheeraj Kumar Ketireddy <dheeru0198@gmail.com>
2025-11-23 19:41:27 +05:30
ba4e711f9b [WEB-5350] migration: navigation (#8156)
* migration: navigation related fields in workspace_user_properties

* fix: field names

* fix: remove max_length

* fix: create new migration

* fix: typo

* Renamed horizontal preference to tabbed

---------

Co-authored-by: Dheeraj Kumar Ketireddy <dheeru0198@gmail.com>
2025-11-21 20:51:47 +05:30
AaronandGitHub 0f4309659a [WEB-5478] chore: fix types (#8155) 2025-11-21 20:22:37 +05:30
SangeethaandGitHub 5cfb9538df [WEB-5312] migration: work item comments (#8072)
* migration: description field on issue_comment
sync: issue_comment and description

* fix: update if description already exists for the IssueComment

* feat: management command to copy IssueComment to Description

* fix: description creation order

* chore: add while loop

* fix: move write outside loop

* chore: change sync logic
chore: test cases

* chore: removed deleted_at filter and added order_by in management command

* fix: description_id

* migration: added parent_id for IssueComment

* fix: update update_by_id

* fix: use ChangeTrackerMixin in save

* chore: add docstring
fix: remove self.pk check
chore: wrap the description creation logic in transaction.atomic()

* fix: tests

* fix: use super save method

* fix: mulitple if conditions

* fix: update updated_at
2025-11-21 16:15:07 +05:30
Vipin ChaudharyandGitHub 6a26ce3a2b [WIKI-792] feat: add 'status' attribute to content validator (#8151) 2025-11-21 14:00:29 +05:30
sriramveeraghanta ec9c868f85 chore: file format using prettier 2025-11-21 13:48:01 +05:30
matutinalandGitHub 03c581433a chore: french localization updates (#8031) 2025-11-21 13:47:07 +05:30
2e15e4f786 fix: source map warning during build (#8148)
* [WEB-5473] fix: source map errors

* [WEB-5473] chore: run codemod

* fix: build errors in editor

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-21 13:43:52 +05:30
Aaryan KhandelwalandGitHub 9611cd1e73 [WIKI-786] refactor: bubble menu #8138 2025-11-21 12:49:30 +05:30
sriram veeraghantaandGitHub 8307badae5 fix: eslint errors and warnings (#8149) 2025-11-20 19:31:22 +05:30
83fdebf64d [WEB-5459] feat(codemods): add function declaration transformer with tests (#8137)
- Add jscodeshift-based codemod to convert arrow function components to function declarations
- Support React.FC, observer-wrapped, and forwardRef components
- Include comprehensive test suite covering edge cases
- Add npm script to run transformer across codebase
- Target only .tsx files in source directories, excluding node_modules and declaration files

* [WEB-5459] chore: updates after running codemod

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-20 17:39:40 +05:30
90866fb925 chore: use oxc tooling to speed up prettier (#8117)
Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
2025-11-20 17:30:27 +05:30
Aaryan KhandelwalandGitHub f3031a44f7 [WEB-5429] refactor: conditional hooks (#8114)
* fix: conditional hooks

* chore: remove unwanted file
2025-11-20 16:22:46 +05:30
Aaryan KhandelwalGitHubNarayanBavisettiBavisetti NarayanVipinDevelopscoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
83679806fd [WIKI-419] chore: new asset duplicate endpoint added (#7172)
* chore: new asset duplicate endpoint added

* chore: change the type in url

* chore: added rate limiting for image duplication endpoint

* chore: added rate limiting per asset id

* chore: added throttle class

* chore: added validations for entity

* chore: added extra validations

* chore: removed the comment

* chore: reverted the frontend code

* chore: added the response key

* feat: handle image duplication for web

* feat: custom image duplication update

* fix: remove paste logic for image

* fix : remove entity validation

* refactor: remove entity id for duplication

* feat: handle duplication in utils

* feat: add asset duplication registry

* chore: update the set attribute method

* fix: add ref for api check

* chore :remove logs

* chore : add entity types types

* refactor: rename duplication success status value

* chore: update attribute to enums

* chore: update variable name

* chore: set uploading state

* chore : update enum name

* chore : update replace command

* chore: fix retry UI

* chore: remove default logic

* refactor: optimize imports in custom image extension files and improve error handling in image duplication

* fix:type error

* Update packages/editor/src/core/extensions/custom-image/components/node-view.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: enhance asset duplication handler to ignore HTTP sources

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com>
Co-authored-by: VipinDevelops <vipinchaudhary1809@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-20 15:05:01 +05:30
Aaryan KhandelwalandGitHub d462546055 [WIKI-788] fix: editor markdown copy rules (#8140) 2025-11-20 14:46:12 +05:30
Dheeraj Kumar KetireddyandGitHub f510020daa [WEB-5285] feat: add ChangeTrackerMixin to track model field changes and original values #8145 2025-11-20 14:36:55 +05:30
Prateek ShouryaandGitHub 1eaa48c95c [WEB-5458] improvement: restructure layout components to enhance loading (#8141) 2025-11-19 19:11:17 +05:30
sriramveeraghanta d6503232de chore(deps): bump npm vulnerabilities 2025-11-19 14:56:29 +05:30
Jayash TripathyandGitHub 88a41479f4 [WEB-5000] feat: enhance exports settings with rich filters (#8124) 2025-11-19 14:31:48 +05:30
Vipin ChaudharyandGitHub b73cf4f0e2 [WEB-5449] fix: enhance content check for unique ID generation and update issue loader condition (#8132) 2025-11-18 15:27:01 +05:30
Aaryan KhandelwalandGitHub 2e6225a883 [WEB-5436] feat: work item preview (#8121) 2025-11-18 13:54:26 +05:30
Vipin ChaudharyandGitHub f34ca18a34 [WIKI-775] fix: remove fallback image from emojis #8130 2025-11-18 13:53:04 +05:30
Prateek ShouryaandGitHub 69323f4164 [WEB-5442] fix: favorites list on workspace switch (#8131) 2025-11-18 13:52:29 +05:30
Jayash TripathyandGitHub 06300d1a8e [WEB-5447] feat: add dataPreventOutsideClick prop to reafactor: ComboboxOptions for enhanced click handling #8112 2025-11-17 19:47:48 +05:30
Vipin ChaudharyandGitHub 6e32cb51b6 [WIKI-770] fix: update editor ref after editor ready #8115 2025-11-17 16:41:30 +05:30
Vipin ChaudharyandGitHub bd0361de92 [WIKI-480] feat: unique id extension (#8098) 2025-11-17 16:14:20 +05:30
Prateek ShouryaandGitHub ebab5e209f [WEB-5437] fix: remove temporary code for issue display filters to fix work item ordering. (#8125) 2025-11-17 14:28:02 +05:30
Aaryan KhandelwalandGitHub c65e2c4aab [WIKI-773] refactor: editor mention components and hooks (#8111) 2025-11-17 14:07:37 +05:30
Prateek ShouryaandGitHub c04ae51d20 [WEB-5423] revert: update imports for pragmatic-drag-and-drop to use cjs entry points and add TypeScript error handling (#8118) 2025-11-14 19:04:49 +05:30
Prateek ShouryaandGitHub 19a0ef490b [WEB-5423] fix: typescript errors and add types check step to pull request workflow (#8110) 2025-11-14 16:18:36 +05:30
sriram veeraghantaGitHubcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>Copilot
4e357c4ad0 [WEB-5404] chore: update next images with html default images (#8101)
* chore: update next images with html default images

* chore: sync related changes

* Update apps/admin/core/components/instance/failure.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update apps/space/app/not-found.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update apps/space/core/components/issues/issue-layouts/error.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update apps/space/core/components/ui/not-found.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore: replace classname styles in space

* fix: copoilot suggestions

* fix: copilot suggestions

* chore: format files

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-13 18:33:18 +05:30
Prateek ShouryaandGitHub 80670b2b3f [WEB-5128] refactor: remove local database dependencies and unused code (#8109) 2025-11-13 18:32:15 +05:30
64f90b828b [WEB-5419] chore: add dotenv dependency, hosts and configure environment variables in admin, space, and web apps (#8107)
* chore: add dotenv dependency and configure environment variables in admin, space, and web apps

* chore: allowed multiple hosts in dev mode

* chore: move dotenv to dev deps

* chore: update Vite configuration to set server host to 127.0.0.1 for admin, space, and web apps

---------

Co-authored-by: gakshita <akshitagoyal1516@gmail.com>
2025-11-13 17:57:47 +05:30
AaronandGitHub 95c742244e [WEB-5416] fix: Use proper import syntax (#8105) 2025-11-13 17:41:06 +05:30
sriramveeraghanta 34c0e81d8e chore: update tubro envs and removed plausible script 2025-11-13 15:24:17 +05:30
Vipin ChaudharyandGitHub 2a2c4921a7 [WIKI-768] fix: ordering and grouping of list-related toolbar and slash commands #8104 2025-11-13 15:20:07 +05:30
Vipin ChaudharyandGitHub f4c2d519fc [WIKI-718] feat: add full width options in table block menu (#8087) 2025-11-13 14:46:27 +05:30
Jayash TripathyandGitHub cbfdcd5638 [WEB-5390] refactor: gantt layout support in base layouts (#8089) 2025-11-13 14:33:24 +05:30
Prateek ShouryaandGitHub a04d3b5c29 [WEB-5414] fix: Use correct SWR cache key for fetching project details (#8103) 2025-11-12 23:31:26 +05:30
sriram veeraghantaandGitHub 30da349475 [WEB-5413] feat: adding sentry error handling in web, space and admin (#8099) 2025-11-12 19:03:47 +05:30
Anmol Singh BhatiaandGitHub 0b78e03055 [WEB-5394] fix: propel storybook circular dependencies (#8096)
* fix: resolve circular dependency crashes in storybook stories

* fix: toolbar circular dependency fix and code refactor
2025-11-11 19:29:16 +05:30
Prateek ShouryaandGitHub f8a9a1576d [WEB-5399] chore: update dependencies and improve PostHog integration (#8097)
- Updated PostHog React package to version 1.4.0 and posthog-js to version 1.255.1.
- Refactored PostHogProvider to include hydration state management for improved event tracking.
- Cleaned up version references in pnpm-lock.yaml for react-router and next-themes.
2025-11-11 19:27:49 +05:30
Krzysztof DąbrowskiandGitHub 6ba15545d9 fix: escape slashes in environment variable values during update (#8081) 2025-11-11 17:52:03 +05:30
sriramveeraghanta da22c2f670 chore(deps): bump turbo package and remove unused packages 2025-11-11 15:50:10 +05:30
sriramveeraghanta d47755b4c6 chore: remove unused files 2025-11-11 15:45:53 +05:30
sriramveeraghanta b51da2f997 chore: remove unused middleware files 2025-11-11 15:33:34 +05:30
Aaryan KhandelwalandGitHub 1447be12e6 [WEB-5370] fix: cycle and modules not being removed from the work item edit modal #8094 2025-11-11 14:55:27 +05:30
Prateek ShouryaandGitHub 433b5a4fe1 [WEB-5386] refactor: update all apps to use react-router for development and enable SSR for space app. (#8095) 2025-11-11 14:08:42 +05:30
sriramveeraghanta 4ae0763d0f chore: bump turbo version 2025-11-11 13:32:10 +05:30
Prateek ShouryaandGitHub a407105bb8 [WEB-5389] chore: enable progress bar for production builds and add logo spinner for hydration fallback (#8093)
* [WEB-5389] chore: enable progress bar for production builds

* feat: add LogoSpinner to HydrateFallback in admin, space, and web apps
2025-11-11 12:22:40 +05:30
M. PalanikannanandGitHub 5d7bf554dd [WEB-5381] fix: buffer issue with vite #8091 2025-11-10 20:33:41 +05:30
sriramveeraghanta 5ec09a7fe1 chore: update dockerfile pnpm install with ci=true 2025-11-10 18:28:51 +05:30
sriramveeraghanta 3f0721c59a chore: upgrade vite version using catalog 2025-11-10 13:13:22 +05:30
Prateek ShouryaandGitHub dfc49eea27 [WEB-5379] fix: optimize filter handling in work item components (#8079) 2025-11-07 20:28:10 +05:30
Akshita GoyalandGitHub 1e5f583a24 [WEB-5367] fix: removed integrations and imports from the routes #8073 2025-11-07 16:12:12 +05:30
Aaryan KhandelwalandGitHub d05c222d0a regression: fallback base url for redirection (#8075) 2025-11-07 16:10:52 +05:30
Vamsi KrishnaandGitHub 8853637e98 [WEB-5064] fix: peek overview reloading when parent is added (#7950) 2025-11-06 19:48:35 +05:30
Aaryan KhandelwalandGitHub 12a050e7d3 [WIKI-538] chore: common description component (#7785)
* chore: common description input component

* chore: replace existing description input components

* fix: await for update calls

* refactor: handle fallback values for description states and form data

* fix: import statements

* chore: add workspaceDetails check
2025-11-06 19:47:38 +05:30
Vipin ChaudharyandGitHub fd542a85fa [WIKI-728] fix: update emoji insertion method #7962 2025-11-06 19:46:32 +05:30
Jayash TripathyandGitHub 0a738d419e [WEB-5306] refactor: base layouts (#8051) 2025-11-06 19:45:56 +05:30
Vipin ChaudharyandGitHub c719d67f71 [WIKI-714] fix: close drag handle dropdown when any key is pressed #8040 2025-11-06 18:58:23 +05:30
Vamsi KrishnaandGitHub 7178627f6a [WEB-5339] chore: work item sidebar refactor #8058 2025-11-06 18:57:50 +05:30
Aaryan KhandelwalandGitHub 10590ffa13 [WEB-5360] fix: modules list board layout #8074 2025-11-06 18:57:22 +05:30
Akshita GoyalandGitHub 37aabe7d1d [PAI-923] fix: implemented fetch key functions for auth layouts #8067 2025-11-06 18:50:45 +05:30
Anmol Singh BhatiaandGitHub fd38b9b6d8 [WEB-4320] refactor: migrate emoji reactions to propel (#8039) 2025-11-06 18:25:43 +05:30
M. PalanikannanandGitHub d709465a89 [WIKI-564] fix: editor deps #8069 2025-11-06 17:33:51 +05:30
Anmol Singh BhatiaandGitHub 9b3bd11c03 [WEB-5305] refactor: migrate emoji and logo components to propel and remove duplication (#8038) 2025-11-06 17:33:06 +05:30
Aaryan KhandelwalandGitHub 4927ef8c71 [WEB-5352] fix: layout selection icon #8070 2025-11-06 16:58:38 +05:30
dependabot[bot]andGitHub 0dcea8db70 chore(deps): bump django (#8068) 2025-11-06 16:21:43 +05:30
Prateek ShouryaandGitHub 0941856f67 [WEB-5356] feat: update public environment keys in Vite config for improved configuration management #8071 2025-11-06 15:41:01 +05:30
Prateek ShouryaandGitHub 696fb96e87 [WEB-5043] feat: web vite migration (#7973) 2025-11-06 14:08:48 +05:30
Prateek ShouryaandGitHub 118ecc81ba [WEB-5042] feat: sites vite migration (#7965) 2025-11-06 13:58:24 +05:30
AaronandGitHub 315e1d5eb0 [WEB-5040] feat: admin react-router migration (#7922) 2025-11-06 13:39:35 +05:30
NikhilandGitHub 545bfa203e [WEB-5345] chore: update IssueActivity model to use DO_NOTHING #8065 2025-11-05 20:14:42 +05:30
Vamsi KrishnaandGitHub 78d4356cfa [WEB-5343]chore: updated view access for exports page at workspace level (#8062)
* chore: updated view access for exports page at workspace level

* fix: permissions
2025-11-04 16:25:07 +05:30
NikhilandGitHub 3c6f24de64 [WEB-5237] feat: add workspace invitation and project member management endpoints (#8059) 2025-11-04 14:56:21 +05:30
NikhilandGitHub 96bbbec588 [WEB-5342] fix: update Issue query to use the correct manager in state checks #8060 2025-11-04 14:47:05 +05:30
Dheeraj Kumar KetireddyandGitHub bfea2c8572 [SILO-598] fix: Fixed bugs identified while testing SDK (#8042) 2025-10-31 19:53:22 +05:30
sriram veeraghantaandGitHub 961cdf6c8f fix: storybook build error (#8041) 2025-10-30 19:21:32 +05:30
Surya PrashanthandGitHub e8bdc47d6a [SILO-640] fix: add missing title field in IssueLinkCreateSerializer #8036 2025-10-29 20:38:27 +05:30
Vamsi KrishnaandGitHub 710138f3a1 [WEB-5296]chore: grouping filter refactor (#8034) 2025-10-29 20:36:28 +05:30
Anmol Singh BhatiaandGitHub 0e8128594b [WEB-5191 | WEB-5197] chore: actions and arrows icon revamp (#7984) 2025-10-29 20:13:08 +05:30
350107d6c1 [WEB-5088] feat: Power K v2 (#7905)
* feat: add project shortcut in command palette

* feat: global project switcher shortcut

* refactor: generalize command palette entity handling

* feat: extend command palette navigation

* feat: add issue shortcut to command palette

* feat: add modular project selection for cycle navigation

* chore: add reusable command palette utilities

* fix: update key sequence handling to use window methods for timeout management

* fix: build errors

* chore: minor ux copy improvements

* feat: implement a new command registry and renderer for enhanced command palette functionality

* feat: introduce new command palette components and enhance search functionality

* feat: enhance command palette components with improved initialization and loading indicators

* feat: Implement new command palette architecture with multi-step commands, context-aware filtering, and reusable components. Add comprehensive documentation and integration guides. Enhance command execution with a dedicated executor and context provider. Introduce new command types and improve existing command definitions for better usability and maintainability.

* refactor: hook arguments

* refactor: folder structure

* refactor: update import paths

* fix: context prop drilling

* refactor: update search components

* refactor: create actions

* chore: add type to pages

* chore: init contextual actions

* refactor: context based actions code split

* chore: module context-based actions

* refactor: streamline command execution flow and enhance multi-step handling in command palette

* refactor: remove placeholder management from command execution and implement centralized placeholder mapping

* chore: cycle context based actions

* refactor: simplify command execution by consolidating selection steps and adding page change handling

* chore: added more options to work item contextual actions

* chore: page context actions

* refactor: update step type definitions and enhance page mapping for command execution

* feat: implement Command Palette V2 with global shortcuts and enhanced context handling

* refactor: power k v2

* refactor: creation commands

* feat: add navigation utility for Power K context handling

* feat: implement comprehensive navigation commands for Power K

* refactor: work item contextual actions

* fix: build errors

* refactor: remaining contextual actions

* refactor: remove old code

* chore: update placeholder

* refactor: enhance command registry with observable properties and context-aware shortcut handling

* refactor: improve command filtering logic in CommandPaletteModal

* chore: context indicator

* chore: misc actions

* style: shortcut badge

* feat: add open entity actions and enhance navigation commands for Power K

* refactor: rename and reorganize Power K components for improved clarity and structure

* refactor: update CommandPalette components and streamline global shortcuts handling

* refactor: adjust debounce timing in CommandPaletteModal for improved responsiveness

* feat: implement shortcuts modal and enhance command registry for better shortcut management

* fix: search implemented

* refactor: search results code split

* refactor: search results code split

* feat: introduce creation and navigation command modules for Power K, enhancing command organization and functionality

* chore: update menu logos

* refactor: remove unused PowerKOpenEntityActionsExtended component from command palette

* refactor: search menu

* fix: clear context on backspace and manual clear

* refactor: rename creation command keys for consistency and clarity in Power K

* chore: added intake in global search

* chore: preferences menu

* chore: removed the empty serach params

* revert: command palette changes

* cleanup

* refactor: update command IDs to use underscores for consistency across Power K components

* refactor: extended context based actions

* chore: modal command item status props

* refactor: replace CommandPalette with CommandPaletteProvider in settings and profile layouts

* refactor: update settings menu to use translated labels instead of i18n labels

* refactor: update command titles to use translation keys for creation actions

* refactor: update navigation command titles to use translation keys for consistency

* chore: minor cleanup

* chore: misc commands added

* chore: code split for no search results command

* chore: state menu items for work item context based commands

* chore: add more props to no search results command

* chore: add more props to no search results command

* refactor: remove shortcut key for create workspace command

* Refactor command palette to use PowerK store

- Replaced instances of `useCommandPalette` with `usePowerK` across various components, including `AppSearch`, `CommandModal`, and `CommandPalette`.
- Introduced `PowerKStore` to manage modal states and commands, enhancing the command palette functionality.
- Updated modal handling to toggle `PowerKModal` and `ShortcutsListModal` instead of the previous command palette modals.
- Refactored related components to ensure compatibility with the new store structure and maintain functionality.

* Refactor PowerK command handling to remove context dependency

- Updated `usePowerKCommands` and `usePowerKCreationCommands` to eliminate the need for a context parameter, simplifying their usage.
- Adjusted related command records to utilize the new structure, ensuring consistent access to command configurations.
- Enhanced permission checks in creation commands to utilize user project roles for better access control.

* chore: add context indicator

* chore: update type import

* chore: migrate toast implementation from @plane/ui to @plane/propel/toast across multiple command files

* refactor: power k modal wrapper and provider

* fix: type imports

* chore: update creation command shortcuts

* fix: page context commands

* chore: update navigation and open command shortcuts

* fix: work item standalone page modals

* fix: context indicator visibility

* fix: potential error points

* fix: build errors

* fix: lint errors

* fix: import order

---------

Co-authored-by: Vihar Kurama <vihar.kurama@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
2025-10-29 15:38:30 +05:30
Jayash TripathyandGitHub 73e0e8d529 [WEB-4944] feat: add base layouts for kanban and list with drag-and-drop support (#8032) 2025-10-29 14:49:34 +05:30
Anmol Singh BhatiaandGitHub 5247fedd23 [WEB-5271] chore: your work empty state updated #8029 2025-10-29 13:34:04 +05:30
Anmol Singh BhatiaandGitHub 0560849f88 [WEB-5271] fix: empty state translation error and code refactoring (#8027)
* fix: workspace view empty state translation

* chore: search empty state translation fix

* chore: workspace view empty state translation
2025-10-28 20:14:07 +05:30
sriram veeraghantaandGitHub 79537cd1df chore: code splitting instance config variables (#8028)
* chore: code splitting instance config variables

* chore: typo fixes
2025-10-28 19:52:23 +05:30
1126ca30b0 [WEB-5262] feat: gitea sso (#8022)
* Feature/7137/gitea sso (#7940)

* added gitea auth to admin panel with configs , added api calls

* added gitea to oauth root (for signup and signin)

* removed log

* replace github oauth with gitea ouath error messages

* added gitea to auth root

* fix: update token expiration handling and remove unused variable in Gitea callback

* fix: include Gitea in OAuth enabled checks

* fix: improve error handling when fetching emails from Gitea

* chore : remove logs and add semicolons

* refactor: update Gitea authentication components and imports for consistency

* fix: enhance Gitea authentication form to auto-populate host value and improve OAuth checks

* refactor: enhance Gitea OAuth provider with improved error handling and URL validation

* fix: update authentication success messages to check for string value "1"

---------

Co-authored-by: Shivam Jain <shivam.clgstash@gmail.com>
Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
2025-10-28 18:53:54 +05:30
SangeethaandGitHub 69fe581fd8 [WEB-5228] chore: IssueLink.DoesNotExist on crawl_work_item_link_title (#8003)
* chore: wrap IssueLink logic in a try-except block

* chore: user logger.warning

* fix: add id and url on the error message
2025-10-28 18:18:36 +05:30
Bavisetti NarayanandGitHub e09d986497 [WEB-5263] chore: removed the tracking of sanitized HTML (#8023)
* chore: removed the html sanitized tracking

* chore: added the greater than sign
2025-10-28 16:57:07 +05:30
SangeethaandGitHub 044003e7ec [WEB-5211] fix: accessing NoneType current_instance for delete_module_issue_activity bgtask (#7993)
* fix: accessing NoneType current_instance

* fix: return module_name

* fix: add none check
2025-10-28 16:56:39 +05:30
SangeethaandGitHub a8b6930486 [WEB-5224] chore: raise warning instead of logging an exception for webhook_send_task (#7996) 2025-10-28 16:49:19 +05:30
Anmol Singh BhatiaandGitHub 685e3fa2f8 [WEB-5236] chore: attachment icon revamp (#8009)
* chore: iconwrapper component added

* chore: attachments icon added to propel

* chore: code refactor

* chore: code refactor
2025-10-28 16:47:43 +05:30
Anmol Singh BhatiaandGitHub ec6e682044 [WEB-5255] fix: calendar layout weekly view (#8018)
* fix: calendar layout weekly view

* chore: code refactor
2025-10-28 16:47:10 +05:30
Anmol Singh BhatiaandGitHub b7aa25f2c6 [WEB-5248] chore: translations and empty state refactor (#8021)
* chore: translations code refactoring

* chore: empty state translation refactor

* chore: code refactor
2025-10-28 13:31:06 +05:30
Anmol Singh BhatiaandGitHub cf7f891bcb [WEB-5248] chore: empty state code refactor and translation fix (#8017)
* chore: empty state code refactor and translation fix

* chore: code refactor
2025-10-27 19:55:46 +05:30
Anmol Singh BhatiaandGitHub 3faf768112 [WEB-3567] chore: empty state refactoring and translation fix (#8014)
* chore: empty state component improvement and code refactor

* chore: translation code refactor

* chore: empty state code refactor
2025-10-27 17:03:35 +05:30
Vamsi KrishnaandGitHub be0d1871f0 [WEB-5241] fix: project features toggle #8015 2025-10-27 17:02:22 +05:30
Surya PrashanthandGitHub c07f7b7c1e [WEB-5245] fix: add is_time_tracking_enabled field in project serializer (#8016) 2025-10-27 16:54:03 +05:30
Surya PrashanthandGitHub 1d4cde9ba0 [WEB-5245] feat: auto-populate logo_props in project creation #8013 2025-10-27 16:19:52 +05:30
NikhilandGitHub c4dd4bd02f [WEB-5155]refactor: simplify user filtering logic in SearchEndpoint #8012 2025-10-27 16:17:19 +05:30
Anmol Singh BhatiaandGitHub d71dfe8f86 [WEB-5188 | WEB-5190] chore: layout and properties icon revamp (#7980) 2025-10-24 19:53:36 +05:30
Anmol Singh BhatiaandGitHub 33b6405695 [WEB-5160] chore: propel banner and archived work item improvements (#7999) 2025-10-24 19:48:28 +05:30
Anmol Singh BhatiaandGitHub 68fd2463f4 [WEB-5230 | WEB-5231] chore: new empty state implementation (#7972) 2025-10-24 17:21:14 +05:30
Vihar KuramaandGitHub a60d74a3c0 [WEB-5235] Fix activity timeline ordering for edited comments #8002 2025-10-24 16:17:51 +05:30
Anmol Singh BhatiaandGitHub 76ffe52cd5 [WEB-5220] fix: intake actions btn ui #7995 2025-10-24 16:05:46 +05:30
b65b1b4828 fix: use issue store was not loading up properly (#8006)
* use issue store was not loading up properly , and hence created data issues for rendering filters options

* Added React.FC for better type suggestions

* chore: observer implementation change

---------

Co-authored-by: shivam-jainn <shivam.clgstash@gmail.com>
2025-10-23 21:45:25 +05:30
sriram veeraghantaandGitHub e5063cd280 fix: get work item activity external endpoint (#8005)
* fix: activity get endpoint fixes

* chore: missing pk added
2025-10-23 21:37:30 +05:30
sriramveeraghanta 9448f642f0 sync: master branch with preview 2025-10-23 20:29:18 +05:30
Akshat Jainandsriramveeraghanta 443f8b793d [INFRA-252] fix: Add missing Redis environment variables in live service Docker Compose 2025-10-23 20:28:39 +05:30
Akshat JainandGitHub 96fa9ab15b [INFRA-252] fix: Add missing Redis environment variables in live service Docker Compose 2025-10-23 19:26:27 +05:30
sriram veeraghantaandGitHub d5bad5aedc release: v1.1.0 #7991 2025-10-23 18:24:42 +05:30
sriram veeraghantaandGitHub 63096ceb8c release: v1.0.0 #7711 2025-09-10 14:53:52 +05:30
sriram veeraghantaandGitHub 9b58b9259e fix: adding proxy command in compose file #7519 2025-07-30 21:03:03 +05:30
sriram veeraghantaandGitHub 1e235600b7 release: v0.28.0 #7488 2025-07-30 16:51:00 +05:30
sriram veeraghantaandGitHub 04b0d7ee9f release: v0.27.1 #7328 2025-07-04 13:31:00 +05:30
sriram veeraghantaandGitHub 5a3f709e72 release: v0.27.0 #7296 2025-07-01 17:40:56 +05:30
sriram veeraghantaandGitHub 5ef33ab798 release: v0.26.1 #7181 2025-06-06 17:55:03 +05:30
sriram veeraghantaandGitHub 27806fbe20 release: v0.26.1 #7179 2025-06-06 17:27:49 +05:30
3437 changed files with 64365 additions and 42229 deletions
+1 -1
View File
@@ -66,4 +66,4 @@ temp/
.react-router/
build/
node_modules/
README.md
README.md
+48
View File
@@ -0,0 +1,48 @@
---
description: Guidelines for bash commands and tooling in the monorepo
applyTo: "**/*.sh"
---
# Bash & Tooling Instructions
This document outlines the standard tools and commands used in this monorepo.
## Package Manager
We use **pnpm** for package management.
- **Do not use `npm` or `yarn`.**
- Lockfile: `pnpm-lock.yaml`
- Workspace configuration: `pnpm-workspace.yaml`
### Common Commands
- Install dependencies: `pnpm install`
- Run a script in a specific package: `pnpm --filter <package_name> run <script>`
- Run a script in all packages: `pnpm -r run <script>`
## Monorepo Tooling
We use **Turbo** for build system orchestration.
- Configuration: `turbo.json`
## Project Structure
- `apps/`: Contains application services (admin, api, live, proxy, space, web).
- `packages/`: Contains shared packages and libraries.
- `deployments/`: Deployment configurations.
## Running Tests
- To run tests in a specific package (e.g., codemods):
```bash
cd packages/codemods
pnpm run test
```
- Or from root:
```bash
pnpm --filter @plane/codemods run test
```
## Docker
- Local development uses `docker-compose-local.yml`.
- Production/Staging uses `docker-compose.yml`.
@@ -0,0 +1,129 @@
---
description: Guidelines for using modern TypeScript features (v5.0-v5.8)
applyTo: "**/*.{ts,tsx,mts,cts}"
---
# TypeScript Coding Guidelines & Modern Features (v5.0 - v5.8)
When writing TypeScript code, prioritize using modern features and best practices introduced in recent versions (up to 5.8).
## Global Themes Across 5.x
1. **Standard decorators are here; legacy decorators are legacy.**
New TC39-compliant decorators landed in 5.0 and were extended in 5.2 (metadata). Old `experimentalDecorators`-style behavior is still supported but should be treated as legacy.
2. **Type system is more precise and less noisy.**
Major work went into narrowing, control flow analysis, error messages, and new helpers like `NoInfer`, inferred predicates, and better `undefined`/`never`/uninitialized checks.
3. **Module / runtime interop has been modernized.**
Options like `--moduleResolution bundler`, `--module nodenext`/`node18`, `--rewriteRelativeImportExtensions`, `--erasableSyntaxOnly`, and `--verbatimModuleSyntax` are about playing nicely with ESM, Node 18+/22+, direct TypeScript execution, and bundlers.
4. **The standard library keeps tracking modern JS.**
Support for new ES features (iterator helpers, `Object.groupBy`/`Map.groupBy`, new Set/ES2024 APIs) shows up as type declarations and sometimes extra checks (regex syntax checking, etc.).
When generating or refactoring code, prefer these newer idioms, and avoid patterns that conflict with updated checks.
## Modern Features to Utilize
### Type System & Inference
- **`const` Type Parameters (5.0)**: Use `const` type parameters for more precise literal inference.
```typescript
declare function names<const T extends string[]>(...names: T): void;
```
- **`@satisfies` Operator (5.0)**: Use `satisfies` to validate types without widening them.
- **Inferred Type Predicates (5.5)**: Allow TypeScript to infer type predicates for functions that filter arrays or check types, reducing the need for explicit `is` return types.
- **`NoInfer` Utility (5.4)**: Use `NoInfer<T>` to block inference for specific type arguments when you want them to be determined by other arguments.
- **Narrowing**:
- **Switch(true) (5.3)**: Utilize narrowing in `switch(true)` blocks.
- **Boolean Comparisons (5.3)**: Rely on narrowing from direct boolean comparisons.
- **Closures (5.4)**: Trust preserved narrowing in closures when variables aren't modified after the check.
- **Constant Indexed Access (5.5)**: Use constant indices to narrow object/array properties.
### Syntax & Control Flow
- **Decorators (5.0)**: Use standard ECMAScript decorators (Stage 3).
- **`using` Declarations (5.2)**: Use `using` for explicit resource management (Disposable pattern) instead of manual cleanup.
```typescript
using resource = new Resource();
```
- **Import Attributes (5.3/5.8)**: Use `with { type: "json" }` for import attributes. Avoid the deprecated `assert` syntax.
- **`switch` Exhaustiveness**: Rely on TypeScript's exhaustiveness checking in switch statements.
### Modules & Imports
- **`verbatimModuleSyntax` (5.0)**: Respect this flag by using `import type` explicitly when importing types to ensure they are erased during compilation.
- **Type-Only Imports with Extensions (5.2)**: You can use `.ts`, `.mts`, `.cts` extensions in `import type` statements.
- **`resolution-mode` (5.3)**: Use `import type { Type } from "mod" with { "resolution-mode": "import" }` if needed for specific module resolution contexts.
- **JSDoc `@import` (5.5)**: Use `@import` tags in JSDoc for cleaner type imports in JS files if working in a mixed codebase.
### Standard Library & Built-ins
- **Iterator Helpers (5.6)**: Use new iterator methods (map, filter, etc.) if targeting modern environments.
- **Set Methods (5.5)**: Utilize new `Set` methods like `union`, `intersection`, etc., when available.
- **`Object.groupBy` / `Map.groupBy` (5.4)**: Use these standard methods for grouping instead of external libraries like Lodash when appropriate.
- **`Promise.withResolvers` (5.7)**: Use `Promise.withResolvers()` for creating promises with exposed resolve/reject functions.
### Configuration & Tooling
- **`--moduleResolution bundler` (5.0)**: Assume this resolution strategy for modern web projects (Vite, Next.js, etc.).
- **`--erasableSyntaxOnly` (5.8)**: Be aware of this flag; avoid TypeScript-specific syntax that cannot be simply erased (like `enum`s or `namespaces`) if the project aims for maximum compatibility with tools like Node.js's `--strip-types`. Prefer `const` objects or unions over `enum`s if requested.
## Specific Coding Patterns
### Arrays & Collections
- Use **Copying Array Methods (5.2)** (`toSorted`, `toSpliced`, `with`) for immutable array operations.
- **TypedArrays (5.7)**: Be aware that TypedArrays are now generic over `ArrayBufferLike`.
### Classes
- **Parameter Decorators (5.0/5.2)**: Use modern standard decorators.
- **`super` Property Access (5.3)**: Avoid accessing instance fields via `super`.
### Error Handling
- **Checks for Never-Initialized Variables (5.7)**: Ensure variables are initialized before use to avoid new errors.
## Deprecations to Avoid
- Avoid `import ... assert` (use `with`).
- Avoid implicit `any` returns in `undefined`-returning functions (though 5.1 makes this easier, explicit is better).
- Avoid `enum`s if the project prefers erasable syntax (5.8).
## Version-Specific Highlights
### TypeScript 5.0
- **Decorators**: Use standard decorators unless `experimentalDecorators` is explicitly enabled.
- **`const` Type Parameters**: Use for literal inference.
- **Enums**: All enums are union enums.
- **Modules**: `--moduleResolution bundler` and `--verbatimModuleSyntax` are key for modern bundlers.
### TypeScript 5.1
- **Returns**: `undefined`-returning functions don't need explicit returns.
- **Getters/Setters**: Can have unrelated types with explicit annotations.
### TypeScript 5.2
- **Resource Management**: `using` declarations for `Symbol.dispose`.
- **Decorator Metadata**: Use `context.metadata` for design-time metadata.
### TypeScript 5.3
- **Import Attributes**: Use `with { type: "json" }`.
- **Switch(true)**: Narrowing works in `switch(true)`.
### TypeScript 5.4
- **Closures**: Narrowing preserved in closures if last assignment is before creation.
- **`NoInfer`**: Block inference for specific arguments.
- **Grouping**: `Object.groupBy` / `Map.groupBy`.
### TypeScript 5.5
- **Inferred Predicates**: Functions checking types often don't need explicit `is` return types.
- **Constant Index Access**: Better narrowing for constant keys.
- **Regex**: Syntax checking for regex literals.
### TypeScript 5.6
- **Truthiness Checks**: Errors on always-truthy/falsy conditions (e.g., `if (/regex/)`).
- **Iterator Helpers**: `.map`, `.filter` on iterators.
### TypeScript 5.7
- **Uninitialized Variables**: Stricter checks for never-initialized variables.
- **Relative Imports**: `--rewriteRelativeImportExtensions` for `.ts` imports in output.
- **ES2024**: Support for `Promise.withResolvers`, `Atomics.waitAsync`.
### TypeScript 5.8
- **Return Checks**: Granular checks for conditional returns.
- **Node Modules**: `--module node18` stable; `require()` of ESM allowed in `nodenext`.
- **Erasable Syntax**: `--erasableSyntaxOnly` forbids enums, namespaces, etc.
When generating code, always prefer the most modern, standard, and type-safe approach available in TypeScript 5.8.
@@ -31,7 +31,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
python-version: "3.12.x"
- name: Install Pylint
run: python -m pip install ruff
- name: Install API Dependencies
@@ -43,11 +43,14 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build Affected
run: pnpm turbo run build --affected
- name: Lint Affected
run: pnpm turbo run check:lint --affected
- name: Check Affected format
run: pnpm turbo run check:format --affected
- name: Build Affected
run: pnpm turbo run build --affected
- name: Check Affected types
run: pnpm turbo run check:types --affected
+10
View File
@@ -102,3 +102,13 @@ dev-editor
storybook-static
CLAUDE.md
build/
.react-router/
AGENTS.md
build/
.react-router/
AGENTS.md
temp/
scripts/
+1
View File
@@ -0,0 +1 @@
pnpm lint-staged
+45 -25
View File
@@ -1,34 +1,54 @@
# Enforce pnpm workspace behavior and allow Turbo's lifecycle hooks if scripts are disabled
# This repo uses pnpm with workspaces.
# ------------------------------
# Core Workspace Behavior
# ------------------------------
# Prefer linking local workspace packages when available
prefer-workspace-packages=true
link-workspace-packages=true
shared-workspace-lockfile=true
# Always prefer using local workspace packages when available
prefer-workspace-packages = true
# Make peer installs smoother across the monorepo
auto-install-peers=true
strict-peer-dependencies=false
# Symlink workspace packages instead of duplicating them
link-workspace-packages = true
# If scripts are disabled (e.g., CI with --ignore-scripts), allowlisted packages can still run their hooks
# Turbo occasionally performs postinstall tasks for optimal performance
# moved to pnpm-workspace.yaml: onlyBuiltDependencies (e.g., allow turbo)
# Use a single lockfile across the whole monorepo
shared-workspace-lockfile = true
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=prettier
public-hoist-pattern[]=typescript
# Ensure packages added from workspace save using workspace: protocol
save-workspace-protocol = true
# Reproducible installs across CI and dev
prefer-frozen-lockfile=true
# Prefer resolving to highest versions in monorepo to reduce duplication
resolution-mode=highest
# ------------------------------
# Dependency Resolution
# ------------------------------
# Speed up native module builds by caching side effects
side-effects-cache=true
# Choose the highest compatible version across the workspace
# → reduces fragmentation & node_modules bloat
resolution-mode = highest
# Speed up local dev by reusing local store when possible
prefer-offline=true
# Automatically install peer dependencies instead of forcing every package to declare them
auto-install-peers = true
# Ensure workspace protocol is used when adding internal deps
save-workspace-protocol=true
# Don't break the install if peers are missing
strict-peer-dependencies = false
# ------------------------------
# Performance Optimizations
# ------------------------------
# Use cached artifacts for native modules (sharp, esbuild, etc.)
side-effects-cache = true
# Prefer local cached packages rather than hitting network
prefer-offline = true
# In CI, refuse to modify lockfile (prevents drift)
prefer-frozen-lockfile = true
# Use isolated linker (best compatibility with Node ecosystem tools)
node-linker = isolated
# Hoist commonly used tools to the root to prevent duplicates and speed up resolution
public-hoist-pattern[] = typescript
public-hoist-pattern[] = eslint
public-hoist-pattern[] = *@plane/*
public-hoist-pattern[] = vite
public-hoist-pattern[] = turbo
+10
View File
@@ -0,0 +1,10 @@
.next/
.react-router/
.turbo/
.vite/
build/
dist/
node_modules/
out/
pnpm-lock.yaml
storybook-static/
+15
View File
@@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"overrides": [
{
"files": ["packages/codemods/**/*"],
"options": {
"printWidth": 80
}
}
],
"plugins": ["@prettier/plugin-oxc"],
"printWidth": 120,
"tabWidth": 2,
"trailingComma": "es5"
}
+1
View File
@@ -0,0 +1 @@
eslint.config.mjs @lifeiscontent
+10 -8
View File
@@ -91,7 +91,7 @@ If you would like to _implement_ it, an issue with your proposal must be submitt
To ensure consistency throughout the source code, please keep these rules in mind as you are working:
- All features or bug fixes must be tested by one or more specs (unit-tests).
- We use [Eslint default rule guide](https://eslint.org/docs/rules/), with minor changes. An automated formatter is available using prettier.
- We lint with [ESLint 9](https://eslint.org/docs/latest/) using the shared `eslint.config.mjs` (type-aware via `typescript-eslint`) and format with [Prettier](https://prettier.io/) using `prettier.config.cjs`.
## Ways to contribute
@@ -187,18 +187,19 @@ Adding a new language involves several steps to ensure it integrates seamlessly
Add the new language to the TLanguage type in the language definitions file:
```ts
// packages/i18n/src/types/language.ts
export type TLanguage = "en" | "fr" | "your-lang";
// packages/i18n/src/types/language.ts
export type TLanguage = "en" | "fr" | "your-lang";
```
1. **Add language configuration**
Include the new language in the list of supported languages:
```ts
// packages/i18n/src/constants/language.ts
export const SUPPORTED_LANGUAGES: ILanguageOption[] = [
{ label: "English", value: "en" },
{ label: "Your Language", value: "your-lang" }
];
// packages/i18n/src/constants/language.ts
export const SUPPORTED_LANGUAGES: ILanguageOption[] = [
{ label: "English", value: "en" },
{ label: "Your Language", value: "your-lang" },
];
```
2. **Create translation files**
@@ -210,6 +211,7 @@ Adding a new language involves several steps to ensure it integrates seamlessly
3. **Update import logic**
Modify the language import logic to include your new language:
```ts
private importLanguageFile(language: TLanguage): Promise<any> {
switch (language) {
+5
View File
@@ -0,0 +1,5 @@
# React Router - https://github.com/remix-run/react-router-templates/blob/dc79b1a065f59f3bfd840d4ef75cc27689b611e6/default/.dockerignore
.react-router/
build/
node_modules/
README.md
+8 -8
View File
@@ -1,12 +1,12 @@
NEXT_PUBLIC_API_BASE_URL="http://localhost:8000"
VITE_API_BASE_URL="http://localhost:8000"
NEXT_PUBLIC_WEB_BASE_URL="http://localhost:3000"
VITE_WEB_BASE_URL="http://localhost:3000"
NEXT_PUBLIC_ADMIN_BASE_URL="http://localhost:3001"
NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
VITE_ADMIN_BASE_URL="http://localhost:3001"
VITE_ADMIN_BASE_PATH="/god-mode"
NEXT_PUBLIC_SPACE_BASE_URL="http://localhost:3002"
NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
VITE_SPACE_BASE_URL="http://localhost:3002"
VITE_SPACE_BASE_PATH="/spaces"
NEXT_PUBLIC_LIVE_BASE_URL="http://localhost:3100"
NEXT_PUBLIC_LIVE_BASE_PATH="/live"
VITE_LIVE_BASE_URL="http://localhost:3100"
VITE_LIVE_BASE_PATH="/live"
-12
View File
@@ -1,12 +0,0 @@
.next/*
out/*
public/*
dist/*
node_modules/*
.turbo/*
.env*
.env
.env.local
.env.development
.env.production
.env.test
-18
View File
@@ -1,18 +0,0 @@
module.exports = {
root: true,
extends: ["@plane/eslint-config/next.js"],
rules: {
"no-duplicate-imports": "off",
"import/no-duplicates": ["error", { "prefer-inline": false }],
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
"@typescript-eslint/no-import-type-side-effects": "error",
"@typescript-eslint/consistent-type-imports": [
"error",
{
prefer: "type-imports",
fixStyle: "separate-type-imports",
disallowTypeAnnotations: false,
},
],
},
};
+9 -5
View File
@@ -1,6 +1,10 @@
.next
.vercel
.tubro
out/
dist/
.next/
.react-router/
.turbo/
.vite/
build/
dist/
node_modules/
out/
pnpm-lock.yaml
storybook-static/
-5
View File
@@ -1,5 +0,0 @@
{
"printWidth": 120,
"tabWidth": 2,
"trailingComma": "es5"
}
+59 -74
View File
@@ -1,103 +1,88 @@
# syntax=docker/dockerfile:1.7
FROM node:22-alpine AS base
# Setup pnpm package manager with corepack and configure global bin directory for caching
WORKDIR /app
ENV TURBO_TELEMETRY_DISABLED=1
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
ENV CI=1
RUN corepack enable pnpm
# =========================================================================== #
# *****************************************************************************
# STAGE 1: Build the project
# *****************************************************************************
FROM base AS builder
RUN apk add --no-cache libc6-compat
WORKDIR /app
ARG TURBO_VERSION=2.5.6
RUN corepack enable pnpm && pnpm add -g turbo@${TURBO_VERSION}
RUN pnpm add -g turbo@2.6.3
COPY . .
# Create a pruned workspace for just the admin app
RUN turbo prune --scope=admin --docker
# *****************************************************************************
# STAGE 2: Install dependencies & build the project
# *****************************************************************************
# =========================================================================== #
FROM base AS installer
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Build in production mode; we still install dev deps explicitly below
ENV NODE_ENV=production
# Public envs required at build time (pick up via process.env)
ARG VITE_API_BASE_URL=""
ENV VITE_API_BASE_URL=$VITE_API_BASE_URL
ARG VITE_API_BASE_PATH="/api"
ENV VITE_API_BASE_PATH=$VITE_API_BASE_PATH
ARG VITE_ADMIN_BASE_URL=""
ENV VITE_ADMIN_BASE_URL=$VITE_ADMIN_BASE_URL
ARG VITE_ADMIN_BASE_PATH="/god-mode"
ENV VITE_ADMIN_BASE_PATH=$VITE_ADMIN_BASE_PATH
ARG VITE_SPACE_BASE_URL=""
ENV VITE_SPACE_BASE_URL=$VITE_SPACE_BASE_URL
ARG VITE_SPACE_BASE_PATH="/spaces"
ENV VITE_SPACE_BASE_PATH=$VITE_SPACE_BASE_PATH
ARG VITE_LIVE_BASE_URL=""
ENV VITE_LIVE_BASE_URL=$VITE_LIVE_BASE_URL
ARG VITE_LIVE_BASE_PATH="/live"
ENV VITE_LIVE_BASE_PATH=$VITE_LIVE_BASE_PATH
ARG VITE_WEB_BASE_URL=""
ENV VITE_WEB_BASE_URL=$VITE_WEB_BASE_URL
ARG VITE_WEB_BASE_PATH=""
ENV VITE_WEB_BASE_PATH=$VITE_WEB_BASE_PATH
ARG VITE_WEBSITE_URL="https://plane.so"
ENV VITE_WEBSITE_URL=$VITE_WEBSITE_URL
ARG VITE_SUPPORT_EMAIL="support@plane.so"
ENV VITE_SUPPORT_EMAIL=$VITE_SUPPORT_EMAIL
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
RUN corepack enable pnpm
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm fetch --store-dir=/pnpm/store
# Copy full directory structure before fetch to ensure all package.json files are available
COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store
ARG NEXT_PUBLIC_API_BASE_URL=""
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ARG NEXT_PUBLIC_ADMIN_BASE_URL=""
ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL
ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH
ARG NEXT_PUBLIC_SPACE_BASE_URL=""
ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL
ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH
ARG NEXT_PUBLIC_WEB_BASE_URL=""
ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL
ENV NEXT_TELEMETRY_DISABLED=1
ENV TURBO_TELEMETRY_DISABLED=1
# Fetch dependencies to cache store, then install offline with dev deps
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store pnpm fetch --store-dir=/pnpm/store
RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store CI=true pnpm install --offline --frozen-lockfile --store-dir=/pnpm/store --prod=false
# Build only the admin package
RUN pnpm turbo run build --filter=admin
# *****************************************************************************
# STAGE 3: Copy the project and start it
# *****************************************************************************
FROM base AS runner
WORKDIR /app
# =========================================================================== #
# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs
FROM nginx:1.29-alpine AS production
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer /app/apps/admin/.next/standalone ./
COPY --from=installer /app/apps/admin/.next/static ./apps/admin/.next/static
COPY --from=installer /app/apps/admin/public ./apps/admin/public
ARG NEXT_PUBLIC_API_BASE_URL=""
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ARG NEXT_PUBLIC_ADMIN_BASE_URL=""
ENV NEXT_PUBLIC_ADMIN_BASE_URL=$NEXT_PUBLIC_ADMIN_BASE_URL
ARG NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
ENV NEXT_PUBLIC_ADMIN_BASE_PATH=$NEXT_PUBLIC_ADMIN_BASE_PATH
ARG NEXT_PUBLIC_SPACE_BASE_URL=""
ENV NEXT_PUBLIC_SPACE_BASE_URL=$NEXT_PUBLIC_SPACE_BASE_URL
ARG NEXT_PUBLIC_SPACE_BASE_PATH="/spaces"
ENV NEXT_PUBLIC_SPACE_BASE_PATH=$NEXT_PUBLIC_SPACE_BASE_PATH
ARG NEXT_PUBLIC_WEB_BASE_URL=""
ENV NEXT_PUBLIC_WEB_BASE_URL=$NEXT_PUBLIC_WEB_BASE_URL
ENV NEXT_TELEMETRY_DISABLED=1
ENV TURBO_TELEMETRY_DISABLED=1
COPY apps/admin/nginx/nginx.conf /etc/nginx/nginx.conf
COPY --from=installer /app/apps/admin/build/client /usr/share/nginx/html/god-mode
EXPOSE 3000
CMD ["node", "apps/admin/server.js"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -fsS http://127.0.0.1:3000/ >/dev/null || exit 1
CMD ["nginx", "-g", "daemon off;"]
+1 -1
View File
@@ -8,7 +8,7 @@ COPY . .
RUN corepack enable pnpm && pnpm add -g turbo
RUN pnpm install
ENV NEXT_PUBLIC_ADMIN_BASE_PATH="/god-mode"
ENV VITE_ADMIN_BASE_PATH="/god-mode"
EXPOSE 3000
+2 -4
View File
@@ -1,5 +1,3 @@
"use client";
import type { FC } from "react";
import { useForm } from "react-hook-form";
import { Lightbulb } from "lucide-react";
import { Button } from "@plane/propel/button";
@@ -17,7 +15,7 @@ type IInstanceAIForm = {
type AIFormValues = Record<TInstanceAIConfigurationKeys, string>;
export const InstanceAIForm: FC<IInstanceAIForm> = (props) => {
export function InstanceAIForm(props: IInstanceAIForm) {
const { config } = props;
// store
const { updateInstanceConfigurations } = useInstance();
@@ -133,4 +131,4 @@ export const InstanceAIForm: FC<IInstanceAIForm> = (props) => {
</div>
</div>
);
};
}
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Artificial Intelligence Settings - God Mode",
};
export default function AILayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
+4 -3
View File
@@ -1,14 +1,13 @@
"use client";
import { observer } from "mobx-react";
import useSWR from "swr";
import { Loader } from "@plane/ui";
// hooks
import { useInstance } from "@/hooks/store";
// components
import type { Route } from "./+types/page";
import { InstanceAIForm } from "./form";
const InstanceAIPage = observer(() => {
const InstanceAIPage = observer(function InstanceAIPage(_props: Route.ComponentProps) {
// store
const { fetchInstanceConfigurations, formattedConfig } = useInstance();
@@ -42,4 +41,6 @@ const InstanceAIPage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "Artificial Intelligence Settings - God Mode" }];
export default InstanceAIPage;
@@ -0,0 +1,207 @@
import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
import { useForm } from "react-hook-form";
// plane internal packages
import { API_BASE_URL } from "@plane/constants";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
import type { IFormattedInstanceConfiguration, TInstanceGiteaAuthenticationConfigurationKeys } from "@plane/types";
import { Button, getButtonStyling } from "@plane/ui";
import { cn } from "@plane/utils";
// components
import { CodeBlock } from "@/components/common/code-block";
import { ConfirmDiscardModal } from "@/components/common/confirm-discard-modal";
import type { TControllerInputFormField } from "@/components/common/controller-input";
import { ControllerInput } from "@/components/common/controller-input";
import type { TCopyField } from "@/components/common/copy-field";
import { CopyField } from "@/components/common/copy-field";
// hooks
import { useInstance } from "@/hooks/store";
type Props = {
config: IFormattedInstanceConfiguration;
};
type GiteaConfigFormValues = Record<TInstanceGiteaAuthenticationConfigurationKeys, string>;
export function InstanceGiteaConfigForm(props: Props) {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
// store hooks
const { updateInstanceConfigurations } = useInstance();
// form data
const {
handleSubmit,
control,
reset,
formState: { errors, isDirty, isSubmitting },
} = useForm<GiteaConfigFormValues>({
defaultValues: {
GITEA_HOST: config["GITEA_HOST"] || "https://gitea.com",
GITEA_CLIENT_ID: config["GITEA_CLIENT_ID"],
GITEA_CLIENT_SECRET: config["GITEA_CLIENT_SECRET"],
},
});
const originURL = !isEmpty(API_BASE_URL) ? API_BASE_URL : typeof window !== "undefined" ? window.location.origin : "";
const GITEA_FORM_FIELDS: TControllerInputFormField[] = [
{
key: "GITEA_HOST",
type: "text",
label: "Gitea Host",
description: (
<>Use the URL of your Gitea instance. For the official Gitea instance, use &quot;https://gitea.com&quot;.</>
),
placeholder: "https://gitea.com",
error: Boolean(errors.GITEA_HOST),
required: true,
},
{
key: "GITEA_CLIENT_ID",
type: "text",
label: "Client ID",
description: (
<>
You will get this from your{" "}
<a
tabIndex={-1}
href="https://gitea.com/user/settings/applications"
target="_blank"
className="text-custom-primary-100 hover:underline"
rel="noreferrer"
>
Gitea OAuth application settings.
</a>
</>
),
placeholder: "70a44354520df8bd9bcd",
error: Boolean(errors.GITEA_CLIENT_ID),
required: true,
},
{
key: "GITEA_CLIENT_SECRET",
type: "password",
label: "Client secret",
description: (
<>
Your client secret is also found in your{" "}
<a
tabIndex={-1}
href="https://gitea.com/user/settings/applications"
target="_blank"
className="text-custom-primary-100 hover:underline"
rel="noreferrer"
>
Gitea OAuth application settings.
</a>
</>
),
placeholder: "9b0050f94ec1b744e32ce79ea4ffacd40d4119cb",
error: Boolean(errors.GITEA_CLIENT_SECRET),
required: true,
},
];
const GITEA_SERVICE_FIELD: TCopyField[] = [
{
key: "Callback_URI",
label: "Callback URI",
url: `${originURL}/auth/gitea/callback/`,
description: (
<>
We will auto-generate this. Paste this into your <CodeBlock darkerShade>Authorized Callback URI</CodeBlock>{" "}
field{" "}
<a
tabIndex={-1}
href={`${control._formValues.GITEA_HOST || "https://gitea.com"}/user/settings/applications`}
target="_blank"
className="text-custom-primary-100 hover:underline"
rel="noreferrer"
>
here.
</a>
</>
),
},
];
const onSubmit = async (formData: GiteaConfigFormValues) => {
const payload: Partial<GiteaConfigFormValues> = { ...formData };
await updateInstanceConfigurations(payload)
.then((response = []) => {
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Done!",
message: "Your Gitea authentication is configured. You should test it now.",
});
reset({
GITEA_HOST: response.find((item) => item.key === "GITEA_HOST")?.value,
GITEA_CLIENT_ID: response.find((item) => item.key === "GITEA_CLIENT_ID")?.value,
GITEA_CLIENT_SECRET: response.find((item) => item.key === "GITEA_CLIENT_SECRET")?.value,
});
})
.catch((err) => console.error(err));
};
const handleGoBack = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
if (isDirty) {
e.preventDefault();
setIsDiscardChangesModalOpen(true);
}
};
return (
<>
<ConfirmDiscardModal
isOpen={isDiscardChangesModalOpen}
onDiscardHref="/authentication"
handleClose={() => setIsDiscardChangesModalOpen(false)}
/>
<div className="flex flex-col gap-8">
<div className="grid grid-cols-2 gap-x-12 gap-y-8 w-full">
<div className="flex flex-col gap-y-4 col-span-2 md:col-span-1 pt-1">
<div className="pt-2.5 text-xl font-medium">Gitea-provided details for Plane</div>
{GITEA_FORM_FIELDS.map((field) => (
<ControllerInput
key={field.key}
control={control}
type={field.type}
name={field.key}
label={field.label}
description={field.description}
placeholder={field.placeholder}
error={field.error}
required={field.required}
/>
))}
<div className="flex flex-col gap-1 pt-4">
<div className="flex items-center gap-4">
<Button variant="primary" onClick={handleSubmit(onSubmit)} loading={isSubmitting} disabled={!isDirty}>
{isSubmitting ? "Saving..." : "Save changes"}
</Button>
<Link
href="/authentication"
className={cn(getButtonStyling("neutral-primary", "md"), "font-medium")}
onClick={handleGoBack}
>
Go back
</Link>
</div>
</div>
</div>
<div className="col-span-2 md:col-span-1">
<div className="flex flex-col gap-y-4 px-6 pt-1.5 pb-4 bg-custom-background-80/60 rounded-lg">
<div className="pt-2 text-xl font-medium">Plane-provided details for Gitea</div>
{GITEA_SERVICE_FIELD.map((field) => (
<CopyField key={field.key} label={field.label} url={field.url} description={field.description} />
))}
</div>
</div>
</div>
</div>
</>
);
}
@@ -0,0 +1,99 @@
import { useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
// plane internal packages
import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
// components
import giteaLogo from "@/app/assets/logos/gitea-logo.svg?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
//local components
import type { Route } from "./+types/page";
import { InstanceGiteaConfigForm } from "./form";
const InstanceGiteaAuthenticationPage = observer(function InstanceGiteaAuthenticationPage() {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
// config
const enableGiteaConfig = formattedConfig?.IS_GITEA_ENABLED ?? "";
useSWR("INSTANCE_CONFIGURATIONS", () => fetchInstanceConfigurations());
const updateConfig = async (key: "IS_GITEA_ENABLED", value: string) => {
setIsSubmitting(true);
const payload = {
[key]: value,
};
const updateConfigPromise = updateInstanceConfigurations(payload);
setPromiseToast(updateConfigPromise, {
loading: "Saving Configuration...",
success: {
title: "Configuration saved",
message: () => `Gitea authentication is now ${value === "1" ? "active" : "disabled"}.`,
},
error: {
title: "Error",
message: () => "Failed to save configuration",
},
});
await updateConfigPromise
.then(() => {
setIsSubmitting(false);
})
.catch((err) => {
console.error(err);
setIsSubmitting(false);
});
};
const isGiteaEnabled = enableGiteaConfig === "1";
return (
<>
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<AuthenticationMethodCard
name="Gitea"
description="Allow members to login or sign up to plane with their Gitea accounts."
icon={<img src={giteaLogo} height={24} width={24} alt="Gitea Logo" />}
config={
<ToggleSwitch
value={isGiteaEnabled}
onChange={() => {
updateConfig("IS_GITEA_ENABLED", isGiteaEnabled ? "0" : "1");
}}
size="sm"
disabled={isSubmitting || !formattedConfig}
/>
}
disabled={isSubmitting || !formattedConfig}
withBorder={false}
/>
</div>
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
{formattedConfig ? (
<InstanceGiteaConfigForm config={formattedConfig} />
) : (
<Loader className="space-y-8">
<Loader.Item height="50px" width="25%" />
<Loader.Item height="50px" />
<Loader.Item height="50px" />
<Loader.Item height="50px" />
<Loader.Item height="50px" width="50%" />
</Loader>
)}
</div>
</div>
</>
);
});
export const meta: Route.MetaFunction = () => [{ title: "Gitea Authentication - God Mode" }];
export default InstanceGiteaAuthenticationPage;
@@ -1,6 +1,3 @@
"use client";
import type { FC } from "react";
import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
@@ -29,7 +26,7 @@ type Props = {
type GithubConfigFormValues = Record<TInstanceGithubAuthenticationConfigurationKeys, string>;
export const InstanceGithubConfigForm: FC<Props> = (props) => {
export function InstanceGithubConfigForm(props: Props) {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
@@ -246,4 +243,4 @@ export const InstanceGithubConfigForm: FC<Props> = (props) => {
</div>
</>
);
};
}
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "GitHub Authentication - God Mode",
};
export default function GitHubAuthenticationLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
@@ -1,8 +1,5 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import Image from "next/image";
import { useTheme } from "next-themes";
import useSWR from "swr";
// plane internal packages
@@ -10,16 +7,19 @@ import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
import { resolveGeneralTheme } from "@plane/utils";
// components
import githubLightModeImage from "@/app/assets/logos/github-black.png?url";
import githubDarkModeImage from "@/app/assets/logos/github-white.png?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
// icons
import githubLightModeImage from "@/public/logos/github-black.png";
import githubDarkModeImage from "@/public/logos/github-white.png";
// local components
import type { Route } from "./+types/page";
import { InstanceGithubConfigForm } from "./form";
const InstanceGithubAuthenticationPage = observer(() => {
const InstanceGithubAuthenticationPage = observer(function InstanceGithubAuthenticationPage(
_props: Route.ComponentProps
) {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
@@ -44,7 +44,7 @@ const InstanceGithubAuthenticationPage = observer(() => {
loading: "Saving Configuration...",
success: {
title: "Configuration saved",
message: () => `GitHub authentication is now ${value ? "active" : "disabled"}.`,
message: () => `GitHub authentication is now ${value === "1" ? "active" : "disabled"}.`,
},
error: {
title: "Error",
@@ -72,7 +72,7 @@ const InstanceGithubAuthenticationPage = observer(() => {
name="GitHub"
description="Allow members to login or sign up to plane with their GitHub accounts."
icon={
<Image
<img
src={resolveGeneralTheme(resolvedTheme) === "dark" ? githubDarkModeImage : githubLightModeImage}
height={24}
width={24}
@@ -111,4 +111,6 @@ const InstanceGithubAuthenticationPage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "GitHub Authentication - God Mode" }];
export default InstanceGithubAuthenticationPage;
@@ -1,4 +1,3 @@
import type { FC } from "react";
import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
@@ -25,7 +24,7 @@ type Props = {
type GitlabConfigFormValues = Record<TInstanceGitlabAuthenticationConfigurationKeys, string>;
export const InstanceGitlabConfigForm: FC<Props> = (props) => {
export function InstanceGitlabConfigForm(props: Props) {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
@@ -209,4 +208,4 @@ export const InstanceGitlabConfigForm: FC<Props> = (props) => {
</div>
</>
);
};
}
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "GitLab Authentication - God Mode",
};
export default function GitlabAuthenticationLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
@@ -1,21 +1,21 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import Image from "next/image";
import useSWR from "swr";
import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
// components
import GitlabLogo from "@/app/assets/logos/gitlab-logo.svg?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
// icons
import GitlabLogo from "@/public/logos/gitlab-logo.svg";
// local components
import type { Route } from "./+types/page";
import { InstanceGitlabConfigForm } from "./form";
const InstanceGitlabAuthenticationPage = observer(() => {
const InstanceGitlabAuthenticationPage = observer(function InstanceGitlabAuthenticationPage(
_props: Route.ComponentProps
) {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
@@ -38,7 +38,7 @@ const InstanceGitlabAuthenticationPage = observer(() => {
loading: "Saving Configuration...",
success: {
title: "Configuration saved",
message: () => `GitLab authentication is now ${value ? "active" : "disabled"}.`,
message: () => `GitLab authentication is now ${value === "1" ? "active" : "disabled"}.`,
},
error: {
title: "Error",
@@ -62,7 +62,7 @@ const InstanceGitlabAuthenticationPage = observer(() => {
<AuthenticationMethodCard
name="GitLab"
description="Allow members to login or sign up to plane with their GitLab accounts."
icon={<Image src={GitlabLogo} height={24} width={24} alt="GitLab Logo" />}
icon={<img src={GitlabLogo} height={24} width={24} alt="GitLab Logo" />}
config={
<ToggleSwitch
value={Boolean(parseInt(enableGitlabConfig))}
@@ -99,4 +99,6 @@ const InstanceGitlabAuthenticationPage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "GitLab Authentication - God Mode" }];
export default InstanceGitlabAuthenticationPage;
@@ -1,5 +1,3 @@
"use client";
import type { FC } from "react";
import { useState } from "react";
import { isEmpty } from "lodash-es";
import Link from "next/link";
@@ -27,7 +25,7 @@ type Props = {
type GoogleConfigFormValues = Record<TInstanceGoogleAuthenticationConfigurationKeys, string>;
export const InstanceGoogleConfigForm: FC<Props> = (props) => {
export function InstanceGoogleConfigForm(props: Props) {
const { config } = props;
// states
const [isDiscardChangesModalOpen, setIsDiscardChangesModalOpen] = useState(false);
@@ -232,4 +230,4 @@ export const InstanceGoogleConfigForm: FC<Props> = (props) => {
</div>
</>
);
};
}
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Google Authentication - God Mode",
};
export default function GoogleAuthenticationLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
@@ -1,21 +1,21 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import Image from "next/image";
import useSWR from "swr";
import { setPromiseToast } from "@plane/propel/toast";
import { Loader, ToggleSwitch } from "@plane/ui";
// components
import GoogleLogo from "@/app/assets/logos/google-logo.svg?url";
import { AuthenticationMethodCard } from "@/components/authentication/authentication-method-card";
// hooks
import { useInstance } from "@/hooks/store";
// icons
import GoogleLogo from "@/public/logos/google-logo.svg";
// local components
import type { Route } from "./+types/page";
import { InstanceGoogleConfigForm } from "./form";
const InstanceGoogleAuthenticationPage = observer(() => {
const InstanceGoogleAuthenticationPage = observer(function InstanceGoogleAuthenticationPage(
_props: Route.ComponentProps
) {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
// state
@@ -38,7 +38,7 @@ const InstanceGoogleAuthenticationPage = observer(() => {
loading: "Saving Configuration...",
success: {
title: "Configuration saved",
message: () => `Google authentication is now ${value ? "active" : "disabled"}.`,
message: () => `Google authentication is now ${value === "1" ? "active" : "disabled"}.`,
},
error: {
title: "Error",
@@ -63,7 +63,7 @@ const InstanceGoogleAuthenticationPage = observer(() => {
name="Google"
description="Allow members to login or sign up to plane with their Google
accounts."
icon={<Image src={GoogleLogo} height={24} width={24} alt="Google Logo" />}
icon={<img src={GoogleLogo} height={24} width={24} alt="Google Logo" />}
config={
<ToggleSwitch
value={Boolean(parseInt(enableGoogleConfig))}
@@ -100,4 +100,6 @@ const InstanceGoogleAuthenticationPage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "Google Authentication - God Mode" }];
export default InstanceGoogleAuthenticationPage;
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Authentication Settings - Plane Web",
};
export default function AuthenticationLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
@@ -1,5 +1,3 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -12,8 +10,9 @@ import { cn } from "@plane/utils";
import { useInstance } from "@/hooks/store";
// plane admin components
import { AuthenticationModes } from "@/plane-admin/components/authentication";
import type { Route } from "./+types/page";
const InstanceAuthenticationPage = observer(() => {
const InstanceAuthenticationPage = observer(function InstanceAuthenticationPage(_props: Route.ComponentProps) {
// store
const { fetchInstanceConfigurations, formattedConfig, updateInstanceConfigurations } = useInstance();
@@ -111,4 +110,6 @@ const InstanceAuthenticationPage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "Authentication Settings - Plane Web" }];
export default InstanceAuthenticationPage;
@@ -1,7 +1,4 @@
"use client";
import type { FC } from "react";
import React, { useMemo, useState } from "react";
import { useMemo, useState } from "react";
import { useForm } from "react-hook-form";
// types
import { Button } from "@plane/propel/button";
@@ -31,7 +28,7 @@ const EMAIL_SECURITY_OPTIONS: { [key in TEmailSecurityKeys]: string } = {
NONE: "No email security",
};
export const InstanceEmailForm: FC<IInstanceEmailForm> = (props) => {
export function InstanceEmailForm(props: IInstanceEmailForm) {
const { config } = props;
// states
const [isSendTestEmailModalOpen, setIsSendTestEmailModalOpen] = useState(false);
@@ -166,7 +163,6 @@ export const InstanceEmailForm: FC<IInstanceEmailForm> = (props) => {
label={EMAIL_SECURITY_OPTIONS[emailSecurityKey]}
onChange={handleEmailSecurityChange}
buttonClassName="rounded-md border-custom-border-200"
optionsClassName="w-full"
input
>
{Object.entries(EMAIL_SECURITY_OPTIONS).map(([key, value]) => (
@@ -225,4 +221,4 @@ export const InstanceEmailForm: FC<IInstanceEmailForm> = (props) => {
</div>
</div>
);
};
}
@@ -1,14 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
interface EmailLayoutProps {
children: ReactNode;
}
export const metadata: Metadata = {
title: "Email Settings - God Mode",
};
export default function EmailLayout({ children }: EmailLayoutProps) {
return <>{children}</>;
}
@@ -1,5 +1,3 @@
"use client";
import { useEffect, useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -8,9 +6,10 @@ import { Loader, ToggleSwitch } from "@plane/ui";
// hooks
import { useInstance } from "@/hooks/store";
// components
import type { Route } from "./+types/page";
import { InstanceEmailForm } from "./email-config-form";
const InstanceEmailPage: React.FC = observer(() => {
const InstanceEmailPage = observer(function InstanceEmailPage(_props: Route.ComponentProps) {
// store
const { fetchInstanceConfigurations, formattedConfig, disableEmail } = useInstance();
@@ -91,4 +90,6 @@ const InstanceEmailPage: React.FC = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "Email Settings - God Mode" }];
export default InstanceEmailPage;
@@ -1,5 +1,4 @@
import type { FC } from "react";
import React, { useEffect, useState } from "react";
import { useEffect, useState, Fragment } from "react";
import { Dialog, Transition } from "@headlessui/react";
// plane imports
import { Button } from "@plane/propel/button";
@@ -20,7 +19,7 @@ enum ESendEmailSteps {
const instanceService = new InstanceService();
export const SendTestEmailModal: FC<Props> = (props) => {
export function SendTestEmailModal(props: Props) {
const { isOpen, handleClose } = props;
// state
@@ -62,10 +61,10 @@ export const SendTestEmailModal: FC<Props> = (props) => {
};
return (
<Transition.Root show={isOpen} as={React.Fragment}>
<Transition.Root show={isOpen} as={Fragment}>
<Dialog as="div" className="relative z-20" onClose={handleClose}>
<Transition.Child
as={React.Fragment}
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
@@ -78,7 +77,7 @@ export const SendTestEmailModal: FC<Props> = (props) => {
<div className="fixed inset-0 z-20 overflow-y-auto">
<div className="my-10 flex justify-center p-4 text-center sm:p-0 md:my-20">
<Transition.Child
as={React.Fragment}
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
@@ -134,4 +133,4 @@ export const SendTestEmailModal: FC<Props> = (props) => {
</Dialog>
</Transition.Root>
);
};
}
@@ -1,5 +1,3 @@
"use client";
import type { FC } from "react";
import { observer } from "mobx-react";
import { Controller, useForm } from "react-hook-form";
import { Telescope } from "lucide-react";
@@ -20,7 +18,7 @@ export interface IGeneralConfigurationForm {
instanceAdmins: IInstanceAdmin[];
}
export const GeneralConfigurationForm: FC<IGeneralConfigurationForm> = observer((props) => {
export const GeneralConfigurationForm = observer(function GeneralConfigurationForm(props: IGeneralConfigurationForm) {
const { instance, instanceAdmins } = props;
// hooks
const { instanceConfigurations, updateInstanceInfo, updateInstanceConfigurations } = useInstance();
@@ -1,6 +1,3 @@
"use client";
import type { FC } from "react";
import { useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
@@ -14,7 +11,7 @@ type TIntercomConfig = {
isTelemetryEnabled: boolean;
};
export const IntercomConfig: FC<TIntercomConfig> = observer((props) => {
export const IntercomConfig = observer(function IntercomConfig(props: TIntercomConfig) {
const { isTelemetryEnabled } = props;
// hooks
const { instanceConfigurations, updateInstanceConfigurations, fetchInstanceConfigurations } = useInstance();
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "General Settings - God Mode",
};
export default function GeneralLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
@@ -1,8 +1,8 @@
"use client";
import { observer } from "mobx-react";
// hooks
import { useInstance } from "@/hooks/store";
// components
import type { Route } from "./+types/page";
import { GeneralConfigurationForm } from "./form";
function GeneralPage() {
@@ -28,4 +28,6 @@ function GeneralPage() {
);
}
export const meta: Route.MetaFunction = () => [{ title: "General Settings - God Mode" }];
export default observer(GeneralPage);
+4 -5
View File
@@ -1,6 +1,3 @@
"use client";
import type { FC } from "react";
import { observer } from "mobx-react";
import { usePathname } from "next/navigation";
import { Menu, Settings } from "lucide-react";
@@ -11,7 +8,7 @@ import { BreadcrumbLink } from "@/components/common/breadcrumb-link";
// hooks
import { useTheme } from "@/hooks/store";
export const HamburgerToggle: FC = observer(() => {
export const HamburgerToggle = observer(function HamburgerToggle() {
const { isSidebarCollapsed, toggleSidebar } = useTheme();
return (
<div
@@ -23,7 +20,7 @@ export const HamburgerToggle: FC = observer(() => {
);
});
export const AdminHeader: FC = observer(() => {
export const AdminHeader = observer(function AdminHeader() {
const pathName = usePathname();
const getHeaderTitle = (pathName: string) => {
@@ -44,6 +41,8 @@ export const AdminHeader: FC = observer(() => {
return "GitHub";
case "gitlab":
return "GitLab";
case "gitea":
return "Gitea";
case "workspace":
return "Workspace";
case "create":
@@ -1,5 +1,3 @@
"use client";
import type { FC } from "react";
import { useForm } from "react-hook-form";
import { Button } from "@plane/propel/button";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
@@ -15,7 +13,7 @@ type IInstanceImageConfigForm = {
type ImageConfigFormValues = Record<TInstanceImageConfigurationKeys, string>;
export const InstanceImageConfigForm: FC<IInstanceImageConfigForm> = (props) => {
export function InstanceImageConfigForm(props: IInstanceImageConfigForm) {
const { config } = props;
// store hooks
const { updateInstanceConfigurations } = useInstance();
@@ -78,4 +76,4 @@ export const InstanceImageConfigForm: FC<IInstanceImageConfigForm> = (props) =>
</div>
</div>
);
};
}
@@ -1,14 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
interface ImageLayoutProps {
children: ReactNode;
}
export const metadata: Metadata = {
title: "Images Settings - God Mode",
};
export default function ImageLayout({ children }: ImageLayoutProps) {
return <>{children}</>;
}
@@ -1,14 +1,13 @@
"use client";
import { observer } from "mobx-react";
import useSWR from "swr";
import { Loader } from "@plane/ui";
// hooks
import { useInstance } from "@/hooks/store";
// local
import type { Route } from "./+types/page";
import { InstanceImageConfigForm } from "./form";
const InstanceImagePage = observer(() => {
const InstanceImagePage = observer(function InstanceImagePage(_props: Route.ComponentProps) {
// store
const { formattedConfig, fetchInstanceConfigurations } = useInstance();
@@ -38,4 +37,6 @@ const InstanceImagePage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "Images Settings - God Mode" }];
export default InstanceImagePage;
+10 -16
View File
@@ -1,34 +1,26 @@
"use client";
import type { FC, ReactNode } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/navigation";
import { Outlet } from "react-router";
// components
import { LogoSpinner } from "@/components/common/logo-spinner";
import { NewUserPopup } from "@/components/new-user-popup";
// hooks
import { useUser } from "@/hooks/store";
// local components
import type { Route } from "./+types/layout";
import { AdminHeader } from "./header";
import { AdminSidebar } from "./sidebar";
type TAdminLayout = {
children: ReactNode;
};
const AdminLayout: FC<TAdminLayout> = (props) => {
const { children } = props;
function AdminLayout(_props: Route.ComponentProps) {
// router
const router = useRouter();
const { replace } = useRouter();
// store hooks
const { isUserLoggedIn } = useUser();
useEffect(() => {
if (isUserLoggedIn === false) {
router.push("/");
}
}, [router, isUserLoggedIn]);
if (isUserLoggedIn === false) replace("/");
}, [replace, isUserLoggedIn]);
if (isUserLoggedIn === undefined) {
return (
@@ -44,7 +36,9 @@ const AdminLayout: FC<TAdminLayout> = (props) => {
<AdminSidebar />
<main className="relative flex h-full w-full flex-col overflow-hidden bg-custom-background-100">
<AdminHeader />
<div className="h-full w-full overflow-hidden">{children}</div>
<div className="h-full w-full overflow-hidden">
<Outlet />
</div>
</main>
<NewUserPopup />
</div>
@@ -52,6 +46,6 @@ const AdminLayout: FC<TAdminLayout> = (props) => {
}
return <></>;
};
}
export default observer(AdminLayout);
@@ -1,5 +1,3 @@
"use client";
import { Fragment, useEffect, useState } from "react";
import { observer } from "mobx-react";
import { useTheme as useNextTheme } from "next-themes";
@@ -16,7 +14,7 @@ import { useTheme, useUser } from "@/hooks/store";
// service initialization
const authService = new AuthService();
export const AdminSidebarDropdown = observer(() => {
export const AdminSidebarDropdown = observer(function AdminSidebarDropdown() {
// store hooks
const { isSidebarCollapsed } = useTheme();
const { currentUser, signOut } = useUser();
@@ -1,6 +1,3 @@
"use client";
import type { FC } from "react";
import { useState, useRef } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
@@ -14,7 +11,7 @@ import { cn } from "@plane/utils";
// hooks
import { useTheme } from "@/hooks/store";
// assets
// eslint-disable-next-line import/order
import packageJson from "package.json";
const helpOptions = [
@@ -35,7 +32,7 @@ const helpOptions = [
},
];
export const AdminSidebarHelpSection: FC = observer(() => {
export const AdminSidebarHelpSection = observer(function AdminSidebarHelpSection() {
// states
const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false);
// store
@@ -1,5 +1,3 @@
"use client";
import { observer } from "mobx-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
@@ -50,7 +48,7 @@ const INSTANCE_ADMIN_LINKS = [
},
];
export const AdminSidebarMenu = observer(() => {
export const AdminSidebarMenu = observer(function AdminSidebarMenu() {
// store hooks
const { isSidebarCollapsed, toggleSidebar } = useTheme();
// router
+1 -4
View File
@@ -1,6 +1,3 @@
"use client";
import type { FC } from "react";
import { useEffect, useRef } from "react";
import { observer } from "mobx-react";
// plane helpers
@@ -12,7 +9,7 @@ import { AdminSidebarDropdown } from "./sidebar-dropdown";
import { AdminSidebarHelpSection } from "./sidebar-help-section";
import { AdminSidebarMenu } from "./sidebar-menu";
export const AdminSidebar: FC = observer(() => {
export const AdminSidebar = observer(function AdminSidebar() {
// store
const { isSidebarCollapsed, toggleSidebar } = useTheme();
@@ -15,7 +15,7 @@ import { useWorkspace } from "@/hooks/store";
const instanceWorkspaceService = new InstanceWorkspaceService();
export const WorkspaceCreateForm = () => {
export function WorkspaceCreateForm() {
// router
const router = useRouter();
// states
@@ -177,7 +177,6 @@ export const WorkspaceCreateForm = () => {
}
buttonClassName="!border-[0.5px] !border-custom-border-200 !shadow-none"
input
optionsClassName="w-full"
>
{ORGANIZATION_SIZE.map((item) => (
<CustomSelect.Option key={item} value={item}>
@@ -209,4 +208,4 @@ export const WorkspaceCreateForm = () => {
</div>
</div>
);
};
}
@@ -1,21 +1,24 @@
"use client";
import { observer } from "mobx-react";
// components
import type { Route } from "./+types/page";
import { WorkspaceCreateForm } from "./form";
const WorkspaceCreatePage = observer(() => (
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">Create a new workspace on this instance.</div>
<div className="text-sm font-normal text-custom-text-300">
You will need to invite users from Workspace Settings after you create this workspace.
const WorkspaceCreatePage = observer(function WorkspaceCreatePage(_props: Route.ComponentProps) {
return (
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">Create a new workspace on this instance.</div>
<div className="text-sm font-normal text-custom-text-300">
You will need to invite users from Workspace Settings after you create this workspace.
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
<WorkspaceCreateForm />
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
<WorkspaceCreateForm />
</div>
</div>
));
);
});
export const meta: Route.MetaFunction = () => [{ title: "Create Workspace - God Mode" }];
export default WorkspaceCreatePage;
@@ -1,10 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "Workspace Management - God Mode",
};
export default function WorkspaceManagementLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
@@ -1,5 +1,3 @@
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
@@ -16,8 +14,9 @@ import { cn } from "@plane/utils";
import { WorkspaceListItem } from "@/components/workspace/list-item";
// hooks
import { useInstance, useWorkspace } from "@/hooks/store";
import type { Route } from "./+types/page";
const WorkspaceManagementPage = observer(() => {
const WorkspaceManagementPage = observer(function WorkspaceManagementPage(_props: Route.ComponentProps) {
// states
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
// store
@@ -167,4 +166,6 @@ const WorkspaceManagementPage = observer(() => {
);
});
export const meta: Route.MetaFunction = () => [{ title: "Workspace Management - God Mode" }];
export default WorkspaceManagementPage;
+6 -5
View File
@@ -1,14 +1,15 @@
import type { FC } from "react";
import { Info, X } from "lucide-react";
import { Info } from "lucide-react";
// plane constants
import type { TAdminAuthErrorInfo } from "@plane/constants";
// icons
import { CloseIcon } from "@plane/propel/icons";
type TAuthBanner = {
bannerData: TAdminAuthErrorInfo | undefined;
handleBannerData?: (bannerData: TAdminAuthErrorInfo | undefined) => void;
};
export const AuthBanner: FC<TAuthBanner> = (props) => {
export function AuthBanner(props: TAuthBanner) {
const { bannerData, handleBannerData } = props;
if (!bannerData) return <></>;
@@ -22,8 +23,8 @@ export const AuthBanner: FC<TAuthBanner> = (props) => {
className="relative ml-auto w-6 h-6 rounded-sm flex justify-center items-center transition-all cursor-pointer hover:bg-custom-primary-100/20 text-custom-primary-100/80"
onClick={() => handleBannerData && handleBannerData(undefined)}
>
<X className="w-4 h-4 flex-shrink-0" />
<CloseIcon className="w-4 h-4 flex-shrink-0" />
</div>
</div>
);
};
}
+9 -9
View File
@@ -1,12 +1,12 @@
"use client";
import Link from "next/link";
import { PlaneLockup } from "@plane/propel/icons";
export const AuthHeader = () => (
<div className="flex items-center justify-between gap-6 w-full flex-shrink-0 sticky top-0">
<Link href="/">
<PlaneLockup height={20} width={95} className="text-custom-text-100" />
</Link>
</div>
);
export function AuthHeader() {
return (
<div className="flex items-center justify-between gap-6 w-full flex-shrink-0 sticky top-0">
<Link href="/">
<PlaneLockup height={20} width={95} className="text-custom-text-100" />
</Link>
</div>
);
}
+10 -15
View File
@@ -1,5 +1,3 @@
import type { ReactNode } from "react";
import Image from "next/image";
import Link from "next/link";
import { KeyRound, Mails } from "lucide-react";
// plane packages
@@ -8,16 +6,16 @@ import { SUPPORT_EMAIL, EAdminAuthErrorCodes } from "@plane/constants";
import type { TGetBaseAuthenticationModeProps, TInstanceAuthenticationModes } from "@plane/types";
import { resolveGeneralTheme } from "@plane/utils";
// components
import githubLightModeImage from "@/app/assets/logos/github-black.png?url";
import githubDarkModeImage from "@/app/assets/logos/github-white.png?url";
import GitlabLogo from "@/app/assets/logos/gitlab-logo.svg?url";
import GoogleLogo from "@/app/assets/logos/google-logo.svg?url";
import { EmailCodesConfiguration } from "@/components/authentication/email-config-switch";
import { GithubConfiguration } from "@/components/authentication/github-config";
import { GitlabConfiguration } from "@/components/authentication/gitlab-config";
import { GoogleConfiguration } from "@/components/authentication/google-config";
import { PasswordLoginConfiguration } from "@/components/authentication/password-config-switch";
// images
import githubLightModeImage from "@/public/logos/github-black.png";
import githubDarkModeImage from "@/public/logos/github-white.png";
import GitlabLogo from "@/public/logos/gitlab-logo.svg";
import GoogleLogo from "@/public/logos/google-logo.svg";
export enum EErrorAlertType {
BANNER_ALERT = "BANNER_ALERT",
@@ -28,7 +26,7 @@ export enum EErrorAlertType {
}
const errorCodeMessages: {
[key in EAdminAuthErrorCodes]: { title: string; message: (email?: string | undefined) => ReactNode };
[key in EAdminAuthErrorCodes]: { title: string; message: (email?: string) => React.ReactNode };
} = {
// admin
[EAdminAuthErrorCodes.ADMIN_ALREADY_EXIST]: {
@@ -81,14 +79,11 @@ const errorCodeMessages: {
},
[EAdminAuthErrorCodes.ADMIN_USER_DEACTIVATED]: {
title: `User account deactivated`,
message: () => `User account deactivated. Please contact ${!!SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
message: () => `User account deactivated. Please contact ${SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
},
};
export const authErrorHandler = (
errorCode: EAdminAuthErrorCodes,
email?: string | undefined
): TAdminAuthErrorInfo | undefined => {
export const authErrorHandler = (errorCode: EAdminAuthErrorCodes, email?: string): TAdminAuthErrorInfo | undefined => {
const bannerAlertErrorCodes = [
EAdminAuthErrorCodes.ADMIN_ALREADY_EXIST,
EAdminAuthErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
@@ -136,7 +131,7 @@ export const getBaseAuthenticationModes: (props: TGetBaseAuthenticationModeProps
key: "google",
name: "Google",
description: "Allow members to log in or sign up for Plane with their Google accounts.",
icon: <Image src={GoogleLogo} height={20} width={20} alt="Google Logo" />,
icon: <img src={GoogleLogo} height={20} width={20} alt="Google Logo" />,
config: <GoogleConfiguration disabled={disabled} updateConfig={updateConfig} />,
},
{
@@ -144,7 +139,7 @@ export const getBaseAuthenticationModes: (props: TGetBaseAuthenticationModeProps
name: "GitHub",
description: "Allow members to log in or sign up for Plane with their GitHub accounts.",
icon: (
<Image
<img
src={resolveGeneralTheme(resolvedTheme) === "dark" ? githubDarkModeImage : githubLightModeImage}
height={20}
width={20}
@@ -157,7 +152,7 @@ export const getBaseAuthenticationModes: (props: TGetBaseAuthenticationModeProps
key: "gitlab",
name: "GitLab",
description: "Allow members to log in or sign up to plane with their GitLab accounts.",
icon: <Image src={GitlabLogo} height={20} width={20} alt="GitLab Logo" />,
icon: <img src={GitlabLogo} height={20} width={20} alt="GitLab Logo" />,
config: <GitlabConfiguration disabled={disabled} updateConfig={updateConfig} />,
},
];
+19 -3
View File
@@ -1,9 +1,25 @@
"use client";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/navigation";
import { Outlet } from "react-router";
// hooks
import { useUser } from "@/hooks/store/use-user";
function RootLayout() {
// router
const { replace } = useRouter();
// store hooks
const { isUserLoggedIn } = useUser();
useEffect(() => {
if (isUserLoggedIn === true) replace("/general");
}, [replace, isUserLoggedIn]);
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<div className="relative z-10 flex flex-col items-center w-screen h-screen overflow-hidden overflow-y-auto pt-6 pb-10 px-8">
{children}
<Outlet />
</div>
);
}
export default observer(RootLayout);
+8 -4
View File
@@ -1,5 +1,3 @@
"use client";
import { observer } from "mobx-react";
// components
import { LogoSpinner } from "@/components/common/logo-spinner";
@@ -8,9 +6,10 @@ import { InstanceSetupForm } from "@/components/instance/setup-form";
// hooks
import { useInstance } from "@/hooks/store";
// components
import type { Route } from "./+types/page";
import { InstanceSignInForm } from "./sign-in-form";
const HomePage = () => {
function HomePage() {
// store hooks
const { instance, error } = useInstance();
@@ -35,6 +34,11 @@ const HomePage = () => {
// if instance is fetched and setup is done, show sign in form
return <InstanceSignInForm />;
};
}
export default observer(HomePage);
export const meta: Route.MetaFunction = () => [
{ title: "Admin Instance Setup & Sign-In" },
{ name: "description", content: "Configure your Plane instance or sign in to the admin portal." },
];
+2 -5
View File
@@ -1,6 +1,3 @@
"use client";
import type { FC } from "react";
import { useEffect, useMemo, useState } from "react";
import { useSearchParams } from "next/navigation";
import { Eye, EyeOff } from "lucide-react";
@@ -46,7 +43,7 @@ const defaultFromData: TFormData = {
password: "",
};
export const InstanceSignInForm: FC = () => {
export function InstanceSignInForm() {
// search params
const searchParams = useSearchParams();
const emailParam = searchParams.get("email") || undefined;
@@ -193,4 +190,4 @@ export const InstanceSignInForm: FC = () => {
</div>
</>
);
};
}
+1 -6
View File
@@ -1,14 +1,9 @@
import type { FC, ReactNode } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
// hooks
import { useInstance } from "@/hooks/store";
type InstanceProviderProps = {
children: ReactNode;
};
export const InstanceProvider: FC<InstanceProviderProps> = observer((props) => {
export const InstanceProvider = observer(function InstanceProvider(props: React.PropsWithChildren) {
const { children } = props;
// store hooks
const { fetchInstanceInfo } = useInstance();
+3 -6
View File
@@ -1,6 +1,3 @@
"use client";
import type { ReactNode } from "react";
import { createContext } from "react";
// plane admin store
import { RootStore } from "@/plane-admin/store/root.store";
@@ -24,12 +21,12 @@ function initializeStore(initialData = {}) {
}
export type StoreProviderProps = {
children: ReactNode;
children: React.ReactNode;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
initialState?: any;
};
export const StoreProvider = ({ children, initialState = {} }: StoreProviderProps) => {
export function StoreProvider({ children, initialState = {} }: StoreProviderProps) {
const store = initializeStore(initialState);
return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
};
}
+2 -4
View File
@@ -1,10 +1,8 @@
"use client";
import { useTheme } from "next-themes";
import { Toast } from "@plane/propel/toast";
import { resolveGeneralTheme } from "@plane/utils";
export const ToastWithTheme = () => {
export function ToastWithTheme() {
const { resolvedTheme } = useTheme();
return <Toast theme={resolveGeneralTheme(resolvedTheme)} />;
};
}
+1 -8
View File
@@ -1,17 +1,10 @@
"use client";
import type { FC, ReactNode } from "react";
import { useEffect } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
// hooks
import { useInstance, useTheme, useUser } from "@/hooks/store";
interface IUserProvider {
children: ReactNode;
}
export const UserProvider: FC<IUserProvider> = observer(({ children }) => {
export const UserProvider = observer(function UserProvider({ children }: React.PropsWithChildren) {
// hooks
const { isSidebarCollapsed, toggleSidebar } = useTheme();
const { currentUser, fetchCurrentUser } = useUser();

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before

Width:  |  Height:  |  Size: 466 B

After

Width:  |  Height:  |  Size: 466 B

Before

Width:  |  Height:  |  Size: 761 B

After

Width:  |  Height:  |  Size: 761 B

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Before

Width:  |  Height:  |  Size: 954 KiB

After

Width:  |  Height:  |  Size: 954 KiB

Before

Width:  |  Height:  |  Size: 418 KiB

After

Width:  |  Height:  |  Size: 418 KiB

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 640 640" width="32" height="32"><path d="m395.9 484.2-126.9-61c-12.5-6-17.9-21.2-11.8-33.8l61-126.9c6-12.5 21.2-17.9 33.8-11.8 17.2 8.3 27.1 13 27.1 13l-.1-109.2 16.7-.1.1 117.1s57.4 24.2 83.1 40.1c3.7 2.3 10.2 6.8 12.9 14.4 2.1 6.1 2 13.1-1 19.3l-61 126.9c-6.2 12.7-21.4 18.1-33.9 12" style="fill:#fff"/><path d="M622.7 149.8c-4.1-4.1-9.6-4-9.6-4s-117.2 6.6-177.9 8c-13.3.3-26.5.6-39.6.7v117.2c-5.5-2.6-11.1-5.3-16.6-7.9 0-36.4-.1-109.2-.1-109.2-29 .4-89.2-2.2-89.2-2.2s-141.4-7.1-156.8-8.5c-9.8-.6-22.5-2.1-39 1.5-8.7 1.8-33.5 7.4-53.8 26.9C-4.9 212.4 6.6 276.2 8 285.8c1.7 11.7 6.9 44.2 31.7 72.5 45.8 56.1 144.4 54.8 144.4 54.8s12.1 28.9 30.6 55.5c25 33.1 50.7 58.9 75.7 62 63 0 188.9-.1 188.9-.1s12 .1 28.3-10.3c14-8.5 26.5-23.4 26.5-23.4S547 483 565 451.5c5.5-9.7 10.1-19.1 14.1-28 0 0 55.2-117.1 55.2-231.1-1.1-34.5-9.6-40.6-11.6-42.6M125.6 353.9c-25.9-8.5-36.9-18.7-36.9-18.7S69.6 321.8 60 295.4c-16.5-44.2-1.4-71.2-1.4-71.2s8.4-22.5 38.5-30c13.8-3.7 31-3.1 31-3.1s7.1 59.4 15.7 94.2c7.2 29.2 24.8 77.7 24.8 77.7s-26.1-3.1-43-9.1m300.3 107.6s-6.1 14.5-19.6 15.4c-5.8.4-10.3-1.2-10.3-1.2s-.3-.1-5.3-2.1l-112.9-55s-10.9-5.7-12.8-15.6c-2.2-8.1 2.7-18.1 2.7-18.1L322 273s4.8-9.7 12.2-13c.6-.3 2.3-1 4.5-1.5 8.1-2.1 18 2.8 18 2.8L467.4 315s12.6 5.7 15.3 16.2c1.9 7.4-.5 14-1.8 17.2-6.3 15.4-55 113.1-55 113.1" style="fill:#609926"/><path d="M326.8 380.1c-8.2.1-15.4 5.8-17.3 13.8s2 16.3 9.1 20c7.7 4 17.5 1.8 22.7-5.4 5.1-7.1 4.3-16.9-1.8-23.1l24-49.1c1.5.1 3.7.2 6.2-.5 4.1-.9 7.1-3.6 7.1-3.6 4.2 1.8 8.6 3.8 13.2 6.1 4.8 2.4 9.3 4.9 13.4 7.3.9.5 1.8 1.1 2.8 1.9 1.6 1.3 3.4 3.1 4.7 5.5 1.9 5.5-1.9 14.9-1.9 14.9-2.3 7.6-18.4 40.6-18.4 40.6-8.1-.2-15.3 5-17.7 12.5-2.6 8.1 1.1 17.3 8.9 21.3s17.4 1.7 22.5-5.3c5-6.8 4.6-16.3-1.1-22.6 1.9-3.7 3.7-7.4 5.6-11.3 5-10.4 13.5-30.4 13.5-30.4.9-1.7 5.7-10.3 2.7-21.3-2.5-11.4-12.6-16.7-12.6-16.7-12.2-7.9-29.2-15.2-29.2-15.2s0-4.1-1.1-7.1c-1.1-3.1-2.8-5.1-3.9-6.3 4.7-9.7 9.4-19.3 14.1-29-4.1-2-8.1-4-12.2-6.1-4.8 9.8-9.7 19.7-14.5 29.5-6.7-.1-12.9 3.5-16.1 9.4-3.4 6.3-2.7 14.1 1.9 19.8z" style="fill:#609926"/></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Before

Width:  |  Height:  |  Size: 742 B

After

Width:  |  Height:  |  Size: 742 B

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 702 B

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

+35
View File
@@ -0,0 +1,35 @@
/**
* Ensures that a URL has a trailing slash while preserving query parameters and fragments
* @param url - The URL to process
* @returns The URL with a trailing slash added to the pathname (if not already present)
*/
export function ensureTrailingSlash(url: string): string {
try {
const fallbackBaseUrl =
typeof window !== "undefined" && window.location.origin ? window.location.origin : "http://dummy.com";
// Handle relative URLs by creating a URL object with a fallback base URL
const urlObj = new URL(url, fallbackBaseUrl);
// Don't modify root path
if (urlObj.pathname === "/") {
return url;
}
// Add trailing slash if it doesn't exist
if (!urlObj.pathname.endsWith("/")) {
urlObj.pathname += "/";
}
// For relative URLs, return just the path + search + hash
if (url.startsWith("/")) {
return urlObj.pathname + urlObj.search + urlObj.hash;
}
// For absolute URLs, return the full URL
return urlObj.toString();
} catch (error) {
// If URL parsing fails, return the original URL
console.warn("Failed to parse URL for trailing slash enforcement:", url, error);
return url;
}
}
+14
View File
@@ -0,0 +1,14 @@
import React from "react";
// Minimal shim so code using next/image compiles under React Router + Vite
// without changing call sites. It just renders a native img.
type NextImageProps = React.ImgHTMLAttributes<HTMLImageElement> & {
src: string;
};
function Image({ src, alt = "", ...rest }: NextImageProps) {
return <img src={src} alt={alt} {...rest} />;
}
export default Image;
+17
View File
@@ -0,0 +1,17 @@
import React from "react";
import { Link as RRLink } from "react-router";
import { ensureTrailingSlash } from "./helper";
type NextLinkProps = React.ComponentProps<"a"> & {
href: string;
replace?: boolean;
prefetch?: boolean; // next.js prop, ignored
scroll?: boolean; // next.js prop, ignored
shallow?: boolean; // next.js prop, ignored
};
function Link({ href, replace, prefetch: _prefetch, scroll: _scroll, shallow: _shallow, ...rest }: NextLinkProps) {
return <RRLink to={ensureTrailingSlash(href)} replace={replace} {...rest} />;
}
export default Link;
+32
View File
@@ -0,0 +1,32 @@
import { useMemo } from "react";
import { useLocation, useNavigate, useSearchParams as useSearchParamsRR } from "react-router";
import { ensureTrailingSlash } from "./helper";
export function useRouter() {
const navigate = useNavigate();
return useMemo(
() => ({
push: (to: string) => navigate(ensureTrailingSlash(to)),
replace: (to: string) => navigate(ensureTrailingSlash(to), { replace: true }),
back: () => navigate(-1),
forward: () => navigate(1),
refresh: () => {
location.reload();
},
prefetch: async (_to: string) => {
// no-op in this shim
},
}),
[navigate]
);
}
export function usePathname(): string {
const { pathname } = useLocation();
return pathname;
}
export function useSearchParams(): URLSearchParams {
const [searchParams] = useSearchParamsRR();
return searchParams;
}
+36
View File
@@ -0,0 +1,36 @@
import React from "react";
import { Link } from "react-router";
// ui
import { Button } from "@plane/propel/button";
// images
import Image404 from "@/app/assets/images/404.svg?url";
function PageNotFound() {
return (
<div className={`h-screen w-full overflow-hidden bg-custom-background-100`}>
<div className="grid h-full place-items-center p-4">
<div className="space-y-8 text-center">
<div className="relative mx-auto h-60 w-60 lg:h-80 lg:w-80">
<img src={Image404} alt="404 - Page not found" className="h-full w-full object-contain" />
</div>
<div className="space-y-2">
<h3 className="text-lg font-semibold">Oops! Something went wrong.</h3>
<p className="text-sm text-custom-text-200">
Sorry, the page you are looking for cannot be found. It may have been removed, had its name changed, or is
temporarily unavailable.
</p>
</div>
<Link to="/general/">
<span className="flex justify-center py-4">
<Button variant="neutral-primary" size="md">
Go to general settings
</Button>
</span>
</Link>
</div>
</div>
</div>
);
}
export default PageNotFound;
+33
View File
@@ -0,0 +1,33 @@
import * as Sentry from "@sentry/react-router";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import { HydratedRouter } from "react-router/dom";
Sentry.init({
dsn: process.env.VITE_SENTRY_DSN,
environment: process.env.VITE_SENTRY_ENVIRONMENT,
sendDefaultPii: process.env.VITE_SENTRY_SEND_DEFAULT_PII ? process.env.VITE_SENTRY_SEND_DEFAULT_PII === "1" : false,
release: process.env.VITE_APP_VERSION,
tracesSampleRate: process.env.VITE_SENTRY_TRACES_SAMPLE_RATE
? parseFloat(process.env.VITE_SENTRY_TRACES_SAMPLE_RATE)
: 0.1,
profilesSampleRate: process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE
? parseFloat(process.env.VITE_SENTRY_PROFILES_SAMPLE_RATE)
: 0.1,
replaysSessionSampleRate: process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE
? parseFloat(process.env.VITE_SENTRY_REPLAYS_SESSION_SAMPLE_RATE)
: 0.1,
replaysOnErrorSampleRate: process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE
? parseFloat(process.env.VITE_SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE)
: 1.0,
integrations: [],
});
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<HydratedRouter />
</StrictMode>
);
});
-9
View File
@@ -1,9 +0,0 @@
"use client";
export default function RootErrorPage() {
return (
<div>
<p>Something went wrong.</p>
</div>
);
}
-39
View File
@@ -1,39 +0,0 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
// plane imports
import { ADMIN_BASE_PATH } from "@plane/constants";
// styles
import "@/styles/globals.css";
export const metadata: Metadata = {
title: "Plane | Simple, extensible, open-source project management tool.",
description:
"Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.",
openGraph: {
title: "Plane | Simple, extensible, open-source project management tool.",
description:
"Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.",
url: "https://plane.so/",
},
keywords:
"software development, customer feedback, software, accelerate, code management, release management, project management, work items tracking, agile, scrum, kanban, collaboration",
twitter: {
site: "@planepowers",
},
};
export default function RootLayout({ children }: { children: ReactNode }) {
const ASSET_PREFIX = ADMIN_BASE_PATH;
return (
<html lang="en">
<head>
<link rel="apple-touch-icon" sizes="180x180" href={`${ASSET_PREFIX}/favicon/apple-touch-icon.png`} />
<link rel="icon" type="image/png" sizes="32x32" href={`${ASSET_PREFIX}/favicon/favicon-32x32.png`} />
<link rel="icon" type="image/png" sizes="16x16" href={`${ASSET_PREFIX}/favicon/favicon-16x16.png`} />
<link rel="manifest" href={`${ASSET_PREFIX}/site.webmanifest.json`} />
<link rel="shortcut icon" href={`${ASSET_PREFIX}/favicon/favicon.ico`} />
</head>
<body className={`antialiased`}>{children}</body>
</html>
);
}
@@ -1,25 +1,24 @@
"use client";
import { ThemeProvider } from "next-themes";
import { SWRConfig } from "swr";
// providers
import { InstanceProvider } from "./instance.provider";
import { StoreProvider } from "./store.provider";
import { ToastWithTheme } from "./toast";
import { UserProvider } from "./user.provider";
import { AppProgressBar } from "@/lib/b-progress";
import { InstanceProvider } from "./(all)/instance.provider";
import { StoreProvider } from "./(all)/store.provider";
import { ToastWithTheme } from "./(all)/toast";
import { UserProvider } from "./(all)/user.provider";
const DEFAULT_SWR_CONFIG = {
refreshWhenHidden: false,
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnMount: true,
refreshInterval: 600000,
refreshInterval: 600_000,
errorRetryCount: 3,
};
export default function InstanceLayout({ children }: { children: React.ReactNode }) {
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider themes={["light", "dark"]} defaultTheme="system" enableSystem>
<AppProgressBar />
<ToastWithTheme />
<SWRConfig value={DEFAULT_SWR_CONFIG}>
<StoreProvider>
+80
View File
@@ -0,0 +1,80 @@
import type { ReactNode } from "react";
import * as Sentry from "@sentry/react-router";
import { Links, Meta, Outlet, Scripts } from "react-router";
import type { LinksFunction } from "react-router";
import appleTouchIcon from "@/app/assets/favicon/apple-touch-icon.png?url";
import favicon16 from "@/app/assets/favicon/favicon-16x16.png?url";
import favicon32 from "@/app/assets/favicon/favicon-32x32.png?url";
import faviconIco from "@/app/assets/favicon/favicon.ico?url";
import { LogoSpinner } from "@/components/common/logo-spinner";
import globalStyles from "@/styles/globals.css?url";
import type { Route } from "./+types/root";
import { AppProviders } from "./providers";
const APP_TITLE = "Plane | Simple, extensible, open-source project management tool.";
const APP_DESCRIPTION =
"Open-source project management tool to manage work items, sprints, and product roadmaps with peace of mind.";
export const links: LinksFunction = () => [
{ rel: "apple-touch-icon", sizes: "180x180", href: appleTouchIcon },
{ rel: "icon", type: "image/png", sizes: "32x32", href: favicon32 },
{ rel: "icon", type: "image/png", sizes: "16x16", href: favicon16 },
{ rel: "shortcut icon", href: faviconIco },
{ rel: "manifest", href: `/site.webmanifest.json` },
{ rel: "stylesheet", href: globalStyles },
];
export function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body className="antialiased" suppressHydrationWarning>
<AppProviders>{children}</AppProviders>
<Scripts />
</body>
</html>
);
}
export const meta: Route.MetaFunction = () => [
{ title: APP_TITLE },
{ name: "description", content: APP_DESCRIPTION },
{ property: "og:title", content: APP_TITLE },
{ property: "og:description", content: APP_DESCRIPTION },
{ property: "og:url", content: "https://plane.so/" },
{
name: "keywords",
content:
"software development, customer feedback, software, accelerate, code management, release management, project management, work items tracking, agile, scrum, kanban, collaboration",
},
{ name: "twitter:site", content: "@planepowers" },
];
export default function Root() {
return <Outlet />;
}
export function HydrateFallback() {
return (
<div className="relative flex h-screen w-full items-center justify-center">
<LogoSpinner />
</div>
);
}
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
if (error) {
Sentry.captureException(error);
}
return (
<div>
<p>Something went wrong.</p>
</div>
);
}
+21
View File
@@ -0,0 +1,21 @@
import { index, layout, route } from "@react-router/dev/routes";
import type { RouteConfig } from "@react-router/dev/routes";
export default [
layout("./(all)/(home)/layout.tsx", [index("./(all)/(home)/page.tsx")]),
layout("./(all)/(dashboard)/layout.tsx", [
route("general", "./(all)/(dashboard)/general/page.tsx"),
route("workspace", "./(all)/(dashboard)/workspace/page.tsx"),
route("workspace/create", "./(all)/(dashboard)/workspace/create/page.tsx"),
route("email", "./(all)/(dashboard)/email/page.tsx"),
route("authentication", "./(all)/(dashboard)/authentication/page.tsx"),
route("authentication/github", "./(all)/(dashboard)/authentication/github/page.tsx"),
route("authentication/gitlab", "./(all)/(dashboard)/authentication/gitlab/page.tsx"),
route("authentication/google", "./(all)/(dashboard)/authentication/google/page.tsx"),
route("authentication/gitea", "./(all)/(dashboard)/authentication/gitea/page.tsx"),
route("ai", "./(all)/(dashboard)/ai/page.tsx"),
route("image", "./(all)/(dashboard)/image/page.tsx"),
]),
// Catch-all route for 404 handling - must be last
route("*", "./components/404.tsx"),
] satisfies RouteConfig;
+12
View File
@@ -0,0 +1,12 @@
declare module "next/link" {
type Props = React.ComponentProps<"a"> & {
href: string;
replace?: boolean;
prefetch?: boolean;
scroll?: boolean;
shallow?: boolean;
};
const Link: React.FC<Props>;
export default Link;
}
+13
View File
@@ -0,0 +1,13 @@
declare module "next/navigation" {
export function useRouter(): {
push: (to: string) => void;
replace: (to: string) => void;
back: () => void;
forward: () => void;
refresh: () => void;
prefetch: (to: string) => Promise<void> | void;
};
export function usePathname(): string;
export function useSearchParams(): URLSearchParams;
}
+5
View File
@@ -0,0 +1,5 @@
declare module "virtual:react-router/server-build" {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const build: any;
export default build;
}

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