[WEB-1907] feat: Favorites Enhancements#5262
Conversation
…re/user-favorites
WalkthroughThe recent changes establish a comprehensive management system for user favorites across the application, enhancing workspace functionality. New serializers, API endpoints, and a dedicated state store streamline the creation, retrieval, and organization of favorite items such as projects and pages. Enhanced UI components facilitate user interaction, making it easier to manage favorites. This update significantly enriches the user experience, ensuring that favorites are both accessible and manageable. Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 9
Outside diff range, codebase verification and nitpick comments (7)
web/core/services/favourite/favourite.service.ts (2)
13-19: Consider removing the console log statement.The console log statement is useful for debugging but should be removed in production code to avoid cluttering the console.
- console.log("addFavourite", data);
22-28: Consider removing the console log statement.The console log statement is useful for debugging but should be removed in production code to avoid cluttering the console.
- console.log("updateFavourite", data);web/core/components/workspace/sidebar/favourites/new-fav-folder.tsx (1)
37-64: Handle form submission errors gracefully.The
handleAddNewFolderfunction should handle form submission errors gracefully by providing user-friendly error messages.- Object.keys(err.data).map((key) => { + Object.keys(err.data).forEach((key) => {web/core/components/workspace/sidebar/favourites/favourite-item.tsx (1)
61-75: EnsuregetLinkfunction handles all cases.The
getLinkfunction does not handle the "folder" case forfavourite.entity_type. Please add a case for "folder" to ensure all possible values are covered.
- Current handled cases: "project", "cycle", "module", "view", "page"
- Missing case: "folder"
Analysis chain
Ensure
getLinkfunction handles all cases.Verify that the
getLinkfunction handles all possible values offavourite.entity_typeand returns the correct link.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the `getLink` function handles all cases. # Test: Search for all possible values of `favourite.entity_type` and ensure they are handled in `getLink`. rg --type js 'entity_type'Length of output: 26
Script:
#!/bin/bash # Description: Verify the `getLink` function handles all cases by searching for all possible values of `favourite.entity_type`. # Search for all occurrences of `entity_type` in the codebase to identify all possible values. rg --type js --type ts 'entity_type'Length of output: 934
web/core/store/pages/page.ts (1)
75-76: Issue withrootStoreInitializationThe
rootStoreproperty is declared in thePageclass but is not initialized in the constructor. This could lead to potential issues ifrootStoreis expected to be used within the class.
- File:
web/core/store/pages/page.ts- Lines: 75-76
Ensure that
rootStoreis properly initialized in the constructor.Analysis chain
Verify the initialization of
rootStore.The constructor now initializes the
rootStoreproperty. Ensure this initialization is consistent with the rest of the class.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the initialization of `rootStore` in the codebase. # Test: Search for the `Page` class constructor. Expect: Consistent initialization. rg --type typescript -A 10 $'constructor('Length of output: 118
Script:
#!/bin/bash # Description: Verify the initialization of `rootStore` in the codebase. # Test: Search for the `Page` class constructor. Expect: Consistent initialization. rg --type typescript -A 10 'constructor\('Length of output: 79
Script:
#!/bin/bash # Description: Verify the initialization of `rootStore` in the codebase. # Find all TypeScript files and search for the `Page` class constructor to verify the initialization of `rootStore`. fd --extension ts --exec rg 'constructor\(' -A 10Length of output: 50549
Script:
#!/bin/bash # Description: Verify the initialization of `rootStore` in the Page class. # Find the Page class definition and its constructor to verify the initialization of `rootStore`. rg 'class Page' -A 20 --type tsLength of output: 1307
Script:
#!/bin/bash # Description: Verify the initialization of `rootStore` in the Page class. # Find the Page class definition and its constructor to verify the initialization of `rootStore`. rg 'class Page' -A 50 --type tsLength of output: 3305
web/core/store/cycle.store.ts (2)
582-582: Incomplete Refactoring: UpdateremoveCycleFromFavoritestoremoveFavouriteEntityThe refactoring to use
this.rootStore.favourite.removeFavouriteEntityis incomplete. The old methodremoveCycleFromFavoritesis still present in multiple files and needs to be updated toremoveFavouriteEntitywith the new parameters.Please update the following instances:
web/core/store/cycle.store.tsweb/core/services/cycle.service.tsweb/core/components/cycles/list/cycle-list-item-action.tsxweb/core/components/cycles/board/cycles-board-card.tsxweb/core/components/cycles/active-cycle/upcoming-cycles-list-item.tsxAnalysis chain
LGTM! But verify the function usage in the codebase.
The refactoring to use
this.rootStore.favourite.removeFavouriteEntityis approved.However, ensure that all function calls to
removeCycleFromFavoriteshave been updated toremoveFavouriteEntitywith the new parameters.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all function calls to `removeCycleFromFavorites` have been updated to `removeFavouriteEntity`. # Test: Search for the old function usage. Expect: No occurrences of `removeCycleFromFavorites`. rg --type ts -A 5 $'removeCycleFromFavorites' # Test: Search for the new function usage. Expect: Only occurrences of `removeFavouriteEntity` with the new parameters. rg --type ts -A 5 $'removeFavouriteEntity'Length of output: 8969
555-559: Refactoring Incomplete: UpdateaddCycleToFavoritestoaddFavouriteThe old method
addCycleToFavoritesis still present in the codebase. Please update all instances ofaddCycleToFavoritestoaddFavouriteto ensure consistency.
- Files to update:
web/core/store/cycle.store.tsweb/core/services/cycle.service.tsweb/core/components/cycles/list/cycle-list-item-action.tsxweb/core/components/cycles/board/cycles-board-card.tsxweb/core/components/cycles/active-cycle/upcoming-cycles-list-item.tsxAnalysis chain
LGTM! But verify the function usage in the codebase.
The refactoring to use
this.rootStore.favourite.addFavouriteis approved.However, ensure that all function calls to
addCycleToFavoriteshave been updated toaddFavouritewith the new parameters.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all function calls to `addCycleToFavorites` have been updated to `addFavourite`. # Test: Search for the old function usage. Expect: No occurrences of `addCycleToFavorites`. rg --type ts -A 5 $'addCycleToFavorites' # Test: Search for the new function usage. Expect: Only occurrences of `addFavourite` with the new parameters. rg --type ts -A 5 $'addFavourite'Length of output: 11390
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (29)
- apiserver/plane/app/serializers/init.py (1 hunks)
- apiserver/plane/app/serializers/favorite.py (1 hunks)
- apiserver/plane/app/urls/workspace.py (2 hunks)
- apiserver/plane/app/views/init.py (1 hunks)
- apiserver/plane/app/views/workspace/favorite.py (1 hunks)
- apiserver/plane/db/models/favorite.py (1 hunks)
- packages/types/src/favourite/favourite.d.ts (1 hunks)
- packages/types/src/favourite/index.d.ts (1 hunks)
- packages/types/src/index.d.ts (1 hunks)
- packages/ui/src/icons/favourite-folder-icon.tsx (1 hunks)
- packages/ui/src/icons/index.ts (1 hunks)
- web/app/[workspaceSlug]/(projects)/sidebar.tsx (3 hunks)
- web/core/components/workspace/sidebar/favourites/favourite-folder.tsx (1 hunks)
- web/core/components/workspace/sidebar/favourites/favourite-item.tsx (1 hunks)
- web/core/components/workspace/sidebar/favourites/favourites-menu.tsx (1 hunks)
- web/core/components/workspace/sidebar/favourites/new-fav-folder.tsx (1 hunks)
- web/core/components/workspace/sidebar/projects-list.tsx (5 hunks)
- web/core/constants/event-tracker.ts (1 hunks)
- web/core/hooks/store/use-favourite.ts (1 hunks)
- web/core/layouts/auth-layout/workspace-wrapper.tsx (3 hunks)
- web/core/services/favourite/favourite.service.ts (1 hunks)
- web/core/services/favourite/index.ts (1 hunks)
- web/core/store/cycle.store.ts (2 hunks)
- web/core/store/favourite.store.ts (1 hunks)
- web/core/store/module.store.ts (2 hunks)
- web/core/store/pages/page.ts (5 hunks)
- web/core/store/project-view.store.ts (2 hunks)
- web/core/store/project/project.store.ts (2 hunks)
- web/core/store/root.store.ts (3 hunks)
Files skipped from review due to trivial changes (4)
- packages/types/src/favourite/index.d.ts
- packages/types/src/index.d.ts
- packages/ui/src/icons/index.ts
- web/core/services/favourite/index.ts
Additional context used
Ruff
apiserver/plane/app/serializers/__init__.py
125-125:
.favorite.UserFavoriteSerializerimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
apiserver/plane/app/views/__init__.py
44-44:
.workspace.favorite.WorkspaceFavoriteEndpointimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
45-45:
.workspace.favorite.WorkspaceFavoriteGroupEndpointimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
GitHub Check: Codacy Static Code Analysis
apiserver/plane/app/serializers/__init__.py
[notice] 125-125: apiserver/plane/app/serializers/init.py#L125
'.favorite.UserFavoriteSerializer' imported but unused (F401)
Additional comments not posted (92)
packages/types/src/favourite/favourite.d.ts (10)
2-2: LGTM!The
idproperty is correctly typed as a string.
3-3: LGTM!The
nameproperty is correctly typed as a string.
4-4: LGTM!The
entity_typeproperty is correctly typed as a string.
5-7: LGTM!The
entity_dataproperty is correctly typed as an object with anameproperty of type string.
8-8: LGTM!The
is_folderproperty is correctly typed as a boolean.
9-9: LGTM!The
sort_orderproperty is correctly typed as a number.
10-10: LGTM!The
parentproperty is correctly typed as a string or null.
11-11: LGTM!The
entity_identifierproperty is correctly typed as an optional string or null.
12-12: LGTM!The
childrenproperty is correctly typed as an array ofIFavourite.
13-13: LGTM!The
project_idproperty is correctly typed as a string or null.web/core/hooks/store/use-favourite.ts (9)
1-1: LGTM!The
useContexthook is correctly imported from React.
2-2: LGTM!The comment is helpful for understanding the purpose of the import.
3-3: LGTM!The
StoreContextis correctly imported from@/lib/store-context.
4-4: LGTM!The
IFavouriteStoreis correctly imported from@/store/favourite.store.
5-5: LGTM!The empty line improves readability.
6-6: LGTM!The
useFavouritehook is correctly defined to returnIFavouriteStore.
7-7: LGTM!The
contextis correctly assigned the value fromuseContext(StoreContext).
8-8: LGTM!The error handling ensures that the hook is used within a
StoreProvider.
9-9: LGTM!The
favouriteproperty of thecontextis correctly returned.packages/ui/src/icons/favourite-folder-icon.tsx (13)
1-1: LGTM!React is correctly imported.
2-2: LGTM!The empty line improves readability.
3-3: LGTM!The
ISvgIconstype is correctly imported from./type.
4-4: LGTM!The empty line improves readability.
5-5: LGTM!The
FavouriteFolderIconcomponent is correctly defined as a React functional component.
6-6: LGTM!The
classNameprop is correctly defined with a default value of"text-current".
7-7: LGTM!The
colorprop is correctly defined with a default value of"#a3a3a3".
8-8: LGTM!The rest props are correctly spread into the component.
9-19: LGTM!The opening tag of the SVG element is correctly defined with various attributes.
20-26: LGTM!The first path element is correctly defined with various attributes.
27-34: LGTM!The second path element is correctly defined with various attributes.
35-35: LGTM!The closing tag of the SVG element is correctly defined.
36-36: LGTM!The closing tag of the component is correctly defined.
apiserver/plane/db/models/favorite.py (1)
42-49: LGTM! The changes enhance robustness.The conditional check ensures that the appropriate workspace is used based on the availability of
self.project, preventing potential errors during the aggregation process.web/core/services/favourite/favourite.service.ts (5)
13-19: LGTM! The method handles API calls correctly.The method sends a POST request to add a favorite item and handles the response and errors appropriately.
22-28: LGTM! The method handles API calls correctly.The method sends a PATCH request to update a favorite item and handles the response and errors appropriately.
31-37: LGTM! The method handles API calls correctly.The method sends a DELETE request to remove a favorite item and handles the response and errors appropriately.
39-48: LGTM! The method handles API calls correctly.The method sends a GET request to retrieve all favorite items and handles the response and errors appropriately.
51-56: LGTM! The method handles API calls correctly.The method sends a GET request to retrieve grouped favorite items and handles the response and errors appropriately.
web/app/[workspaceSlug]/(projects)/sidebar.tsx (2)
13-13: LGTM! The import statement is correct.The
SidebarFavouritesMenucomponent is correctly imported.
81-86: LGTM! The component integration is seamless.The
SidebarFavouritesMenucomponent is seamlessly integrated into theAppSidebarcomponent, enhancing the sidebar's functionality.apiserver/plane/app/serializers/favorite.py (7)
14-19: LGTM!The
ProjectFavoriteLiteSerializercorrectly defines the fields for theProjectmodel.
21-33: LGTM!The
PageFavoriteLiteSerializercorrectly defines the fields for thePagemodel and includes a custom methodget_project_idthat retrieves the first related project.
35-39: LGTM!The
CycleFavoriteLiteSerializercorrectly defines the fields for theCyclemodel.
42-46: LGTM!The
ModuleFavoriteLiteSerializercorrectly defines the fields for theModulemodel.
49-53: LGTM!The
ViewFavoriteSerializercorrectly defines the fields for theIssueViewmodel.
56-66: LGTM!The
get_entity_model_and_serializerfunction correctly maps entity types to their respective models and serializers.
69-101: LGTM!The
UserFavoriteSerializercorrectly defines the fields for theUserFavoritemodel and includes a custom methodget_entity_datathat retrieves and serializes the related entity data.web/core/components/workspace/sidebar/favourites/new-fav-folder.tsx (5)
1-20: LGTM!The imports and type definitions are correctly defined and complete.
21-35: LGTM!The
NewFavouriteFoldercomponent correctly initializes props and form handling.
66-80: LGTM!The
handleRenameFolderfunction correctly handles the renaming of favorite folders.
82-88: LGTM!The
useEffecthook correctly sets the focus on the form input and handles outside click detection.
89-101: LGTM!The JSX correctly renders the form and handles form submission.
web/core/components/workspace/sidebar/favourites/favourite-item.tsx (4)
23-26: VerifyuseAppThemeandusePlatformOShooks.Ensure that the
useAppThemeandusePlatformOShooks return the expected values and are used correctly within the component.Verification successful
Verified
useAppThemeandusePlatformOShooks.The
useAppThemeandusePlatformOShooks are correctly implemented and imported in thefavourite-item.tsxfile. Their usage within the component is appropriate and consistent with their definitions.
useAppThemeis defined inweb/core/hooks/store/use-app-theme.ts.usePlatformOSis defined inweb/core/hooks/use-platform-os.tsx.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation and usage of `useAppTheme` and `usePlatformOS` hooks. # Test: Search for the implementation of `useAppTheme` and `usePlatformOS`. Expect: Correct implementation and usage. rg --type js 'useAppTheme' rg --type js 'usePlatformOS'Length of output: 55
Script:
#!/bin/bash # Description: Verify the implementation and usage of `useAppTheme` and `usePlatformOS` hooks. # Test: Search for the implementation of `useAppTheme` and `usePlatformOS` in TypeScript files. rg --type ts 'useAppTheme' rg --type ts 'usePlatformOS' # Test: Check if `useAppTheme` and `usePlatformOS` are imported in `favourite-item.tsx`. rg 'useAppTheme' web/core/components/workspace/sidebar/favourites/favourite-item.tsx rg 'usePlatformOS' web/core/components/workspace/sidebar/favourites/favourite-item.tsxLength of output: 23970
78-98: EnsureuseEffectdependencies are correct.The
useEffecthook has a dependency onelementRef.currentandisDragging. Ensure these dependencies are correct and necessary.Verification successful
The
useEffectdependencies are correct and necessary.
elementRef.currentis used to get the DOM element for the draggable functionality.isDraggingis used to manage the dragging state.Both dependencies are essential for the correct functioning of the
useEffecthook.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the `useEffect` dependencies. # Test: Search for the usage of `elementRef.current` and `isDragging` within the `useEffect` hook. rg --type js 'useEffect'Length of output: 24
Script:
#!/bin/bash # Search for the definition and usage of `elementRef` in `favourite-item.tsx` rg 'elementRef' web/core/components/workspace/sidebar/favourites/favourite-item.tsx # Search for the definition and usage of `isDragging` in `favourite-item.tsx` rg 'isDragging' web/core/components/workspace/sidebar/favourites/favourite-item.tsxLength of output: 526
3-20: Ensure all imports are necessary.Review the imports to ensure they are all necessary and used within the file. Unused imports can lead to unnecessary bloat.
Verification successful
Let's verify the usage of each import within the file
web/core/components/workspace/sidebar/favourites/favourite-item.tsx.
All imports are necessary and used within the file.
The verification confirms that each import in
web/core/components/workspace/sidebar/favourites/favourite-item.tsxis utilized in the code.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all imports are used in the file. # Test: Search for the usage of each import. Expect: All imports should have usage within the file. rg --type js 'import'Length of output: 1145
Script:
#!/bin/bash # Description: Verify the usage of each import in the target file. # Define the file to check TARGET_FILE="web/core/components/workspace/sidebar/favourites/favourite-item.tsx" # List of imported items to check for usage IMPORTS=( "React" "useEffect" "useRef" "useState" "combine" "draggable" "observer" "Link" "useParams" "Briefcase" "FileText" "Layers" "IFavourite" "ContrastIcon" "DiceIcon" "DragHandle" "FavouriteFolderIcon" "LayersIcon" "Tooltip" "SidebarNavItem" "cn" "useAppTheme" "usePlatformOS" ) # Search for the usage of each import in the target file for item in "${IMPORTS[@]}"; do echo "Searching for usage of: $item" rg "$item" "$TARGET_FILE" doneLength of output: 7636
100-139: Ensure proper handling offavourite.entity_data.Verify that
favourite.entity_datais correctly handled and does not cause any runtime errors.web/core/components/workspace/sidebar/favourites/favourites-menu.tsx (4)
3-21: Ensure all imports are necessary.Review the imports to ensure they are all necessary and used within the file. Unused imports can lead to unnecessary bloat.
Verification successful
All imports are necessary and used within the file.
- The imports
useEffect,useRef,useState,observer,ChevronRight,FolderPlus,Disclosure,Transition,Tooltip,cn,useAppTheme,useFavourite,useLocalStorage,usePlatformOS,FavouriteFolder,FavouriteItem, andNewFavouriteFolderare all utilized within thefavourites-menu.tsxfile.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all imports are used in the file. # Test: Search for the usage of each import. Expect: All imports should have usage within the file. rg --type js 'import'Length of output: 1145
Script:
#!/bin/bash # Description: Verify the usage of each import in the `favourites-menu.tsx` file. # Define the file path file_path="web/core/components/workspace/sidebar/favourites/favourites-menu.tsx" # List of imports to verify imports=( "useEffect" "useRef" "useState" "observer" "ChevronRight" "FolderPlus" "Disclosure" "Transition" "Tooltip" "cn" "useAppTheme" "useFavourite" "useLocalStorage" "usePlatformOS" "FavouriteFolder" "FavouriteItem" "NewFavouriteFolder" ) # Search for the usage of each import in the file for import in "${imports[@]}"; do echo "Searching for usage of $import in $file_path" rg "$import" "$file_path" doneLength of output: 8777
40-63: EnsureuseEffectdependencies are correct.The
useEffecthooks have dependencies onsidebarCollapsedandcontainerRef. Ensure these dependencies are correct and necessary.Verification successful
The
useEffectdependencies are correct and necessary.
- The
sidebarCollapseddependency is used to toggle the favourite menu when the sidebar is collapsed.- The
containerRefdependency is used to handle scroll events and update the scroll state.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the `useEffect` dependencies. # Test: Search for the usage of `sidebarCollapsed` and `containerRef` within the `useEffect` hooks. rg --type js 'useEffect'Length of output: 24
Script:
#!/bin/bash # Description: Verify the `useEffect` dependencies in the favourites-menu.tsx file. # Test: Search for the usage of `sidebarCollapsed` and `containerRef` within the `useEffect` hooks in the specified file. rg 'useEffect' web/core/components/workspace/sidebar/favourites/favourites-menu.tsx -A 10 | rg 'sidebarCollapsed|containerRef'Length of output: 372
64-137: Ensure proper handling offavouriteMapandfavouriteIds.Verify that
favouriteMapandfavouriteIdsare correctly handled and do not cause any runtime errors.Verification successful
Handling of
favouriteMapandfavouriteIdsis correct.The variables
favouriteMapandfavouriteIdsare properly defined and manipulated infavourite.store.tsand used correctly infavourites-menu.tsx.
web/core/store/favourite.store.ts: Definitions and manipulations offavouriteMapandfavouriteIds.web/core/components/workspace/sidebar/favourites/favourites-menu.tsx: Usage offavouriteMapandfavouriteIds.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the handling of `favouriteMap` and `favouriteIds`. # Test: Search for the usage of `favouriteMap` and `favouriteIds` and ensure they are correctly handled. rg --type js 'favouriteMap' rg --type js 'favouriteIds'Length of output: 55
Script:
#!/bin/bash # Description: Verify the handling of `favouriteMap` and `favouriteIds` in TypeScript files. # Test: Search for the usage of `favouriteMap` and `favouriteIds` in TypeScript files. rg --type tsx 'favouriteMap' rg --type tsx 'favouriteIds' rg --type ts 'favouriteMap' rg --type ts 'favouriteIds'Length of output: 4226
22-26: VerifyuseAppTheme,useFavourite,useLocalStorage, andusePlatformOShooks.Ensure that the
useAppTheme,useFavourite,useLocalStorage, andusePlatformOShooks return the expected values and are used correctly within the component.Verification successful
Hooks
useAppTheme,useFavourite,useLocalStorage, andusePlatformOSare correctly implemented and used.The
useAppTheme,useFavourite,useLocalStorage, andusePlatformOShooks are correctly implemented and used within theSidebarFavouritesMenucomponent.
useAppTheme: Manages the sidebar's collapsed state.useFavourite: Manages favorite items.useLocalStorage: Manages local storage state.usePlatformOS: Determines the platform OS.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation and usage of `useAppTheme`, `useFavourite`, `useLocalStorage`, and `usePlatformOS` hooks. # Test: Search for the implementation of `useAppTheme`, `useFavourite`, `useLocalStorage`, and `usePlatformOS`. Expect: Correct implementation and usage. rg --type js 'useAppTheme' rg --type js 'useFavourite' rg --type js 'useLocalStorage' rg --type js 'usePlatformOS'Length of output: 114
Script:
#!/bin/bash # Description: Verify the implementation of `useAppTheme`, `useFavourite`, `useLocalStorage`, and `usePlatformOS` hooks. # Test: Search for the implementation of `useAppTheme`, `useFavourite`, `useLocalStorage`, and `usePlatformOS`. Expect: Correct implementation. ast-grep --lang javascript --pattern 'function useAppTheme() { $$$ }' ast-grep --lang javascript --pattern 'function useFavourite() { $$$ }' ast-grep --lang javascript --pattern 'function useLocalStorage() { $$$ }' ast-grep --lang javascript --pattern 'function usePlatformOS() { $$$ }'Length of output: 294
Script:
#!/bin/bash # Description: Verify the usage of `useAppTheme`, `useFavourite`, `useLocalStorage`, and `usePlatformOS` hooks. # Test: Search for the usage of `useAppTheme`, `useFavourite`, `useLocalStorage`, and `usePlatformOS` within the codebase. Expect: Correct usage. rg 'useAppTheme' rg 'useFavourite' rg 'useLocalStorage' rg 'usePlatformOS'Length of output: 29520
apiserver/plane/app/urls/workspace.py (2)
242-256: Ensure new URL patterns are correct.Verify that the new URL patterns for managing user favorites are correctly defined and integrated within the existing URL patterns.
Verification successful
The new URL patterns for managing user favorites are correctly defined and integrated.
The
WorkspaceFavoriteEndpointandWorkspaceFavoriteGroupEndpointclasses are properly defined and imported, ensuring the functionality of the new URL patterns.
WorkspaceFavoriteEndpointis defined inapiserver/plane/app/views/workspace/favorite.py.WorkspaceFavoriteGroupEndpointis defined inapiserver/plane/app/views/workspace/favorite.py.- Both classes are imported in
apiserver/plane/app/urls/workspace.py.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the new URL patterns for managing user favorites. # Test: Search for the new URL patterns and ensure they are correctly defined. rg --type py 'user-favorites'Length of output: 578
Script:
#!/bin/bash # Description: Verify the definitions and imports of the views used in the new URL patterns. # Search for the definition of WorkspaceFavoriteEndpoint rg --type py 'class WorkspaceFavoriteEndpoint' # Search for the definition of WorkspaceFavoriteGroupEndpoint rg --type py 'class WorkspaceFavoriteGroupEndpoint' # Search for the import statements of WorkspaceFavoriteEndpoint and WorkspaceFavoriteGroupEndpoint rg --type py 'WorkspaceFavoriteEndpoint' rg --type py 'WorkspaceFavoriteGroupEndpoint'Length of output: 1115
Line range hint
1-29:
Ensure all imports are necessary.Review the imports to ensure they are all necessary and used within the file. Unused imports can lead to unnecessary bloat.
Verification successful
All imports are necessary.
The verification shows that all the imported entities in
apiserver/plane/app/urls/workspace.pyare used within the file.
- UserWorkspaceInvitationsViewSet
- WorkSpaceViewSet
- WorkspaceJoinEndpoint
- WorkSpaceMemberViewSet
- WorkspaceInvitationsViewset
- WorkspaceMemberUserEndpoint
- WorkspaceMemberUserViewsEndpoint
- WorkSpaceAvailabilityCheckEndpoint
- TeamMemberViewSet
- UserLastProjectWithWorkspaceEndpoint
- WorkspaceThemeViewSet
- WorkspaceUserProfileStatsEndpoint
- WorkspaceUserActivityEndpoint
- WorkspaceUserProfileEndpoint
- WorkspaceUserProfileIssuesEndpoint
- WorkspaceLabelsEndpoint
- WorkspaceProjectMemberEndpoint
- WorkspaceUserPropertiesEndpoint
- WorkspaceStatesEndpoint
- WorkspaceEstimatesEndpoint
- ExportWorkspaceUserActivityEndpoint
- WorkspaceModulesEndpoint
- WorkspaceCyclesEndpoint
- WorkspaceFavoriteEndpoint
- WorkspaceFavoriteGroupEndpoint
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all imports are used in the file. # Test: Search for the usage of each import. Expect: All imports should have usage within the file. rg --type py 'import'Length of output: 233335
Script:
#!/bin/bash # Description: Verify the usage of each import in the target file. # List of imported entities to check for usage. imports=( "UserWorkspaceInvitationsViewSet" "WorkSpaceViewSet" "WorkspaceJoinEndpoint" "WorkSpaceMemberViewSet" "WorkspaceInvitationsViewset" "WorkspaceMemberUserEndpoint" "WorkspaceMemberUserViewsEndpoint" "WorkSpaceAvailabilityCheckEndpoint" "TeamMemberViewSet" "UserLastProjectWithWorkspaceEndpoint" "WorkspaceThemeViewSet" "WorkspaceUserProfileStatsEndpoint" "WorkspaceUserActivityEndpoint" "WorkspaceUserProfileEndpoint" "WorkspaceUserProfileIssuesEndpoint" "WorkspaceLabelsEndpoint" "WorkspaceProjectMemberEndpoint" "WorkspaceUserPropertiesEndpoint" "WorkspaceStatesEndpoint" "WorkspaceEstimatesEndpoint" "ExportWorkspaceUserActivityEndpoint" "WorkspaceModulesEndpoint" "WorkspaceCyclesEndpoint" "WorkspaceFavoriteEndpoint" "WorkspaceFavoriteGroupEndpoint" ) # File to check. file="apiserver/plane/app/urls/workspace.py" # Check usage of each import in the file. for import in "${imports[@]}"; do echo "Checking usage of $import in $file" rg "$import" "$file" || echo "$import is not used in $file" doneLength of output: 10353
web/core/layouts/auth-layout/workspace-wrapper.tsx (2)
15-15: LGTM!The import statement for
useFavouriteis correct.
35-35: LGTM!The usage of
fetchFavouritewithin theuseSWRhook is correct and follows the existing pattern for fetching data.Also applies to: 73-78
web/core/constants/event-tracker.ts (1)
233-233: LGTM!The addition of the
FAVOURITE_ADDEDconstant is correct and enhances event tracking capabilities.web/core/store/favourite.store.ts (9)
1-27: LGTM!The imports and
IFavouriteStoreinterface declaration are correct.
29-56: LGTM!The constructor and observables setup in the
FavouriteStoreclass are correct and follow MobX patterns.
64-78: LGTM!The
addFavouritemethod implementation is correct and follows best practices for error handling and state updates.
87-98: LGTM!The
updateFavouritemethod implementation is correct and follows best practices for error handling and state updates.
107-137: LGTM!The
moveFavouritemethod implementation is correct and follows best practices for error handling and state updates.
145-163: LGTM!The
deleteFavouritemethod implementation is correct and follows best practices for error handling and state updates.
171-182: LGTM!The
removeFavouriteEntitymethod implementation is correct and follows best practices for error handling and state updates.
189-209: LGTM!The
getGroupedFavouritesmethod implementation is correct and follows best practices for error handling and state updates.
217-233: LGTM!The
fetchFavouritemethod implementation is correct and follows best practices for error handling and state updates.web/core/components/workspace/sidebar/projects-list.tsx (5)
8-8: Import statement looks good.The import statement for
Briefcase,ChevronRight, andPlusfromlucide-reactis correct and necessary for the component's functionality.
30-30: State initialization looks good.The state
isAllProjectsListOpenis correctly initialized based on the value stored in local storage, ensuring consistency with previous user preferences.
43-43: Hook usage looks good.The hook
useProjectis correctly used to retrieve project-related data, which is necessary for the component's functionality.
126-128: Function simplification looks good.The
toggleListDisclosurefunction has been correctly simplified to handle only the "all" projects list, reducing complexity.
137-138: Component usage looks good.The
CreateProjectModalcomponent is correctly used with thesetToFavoriteprop set tofalse, aligning with the removal of favorite projects handling.web/core/components/workspace/sidebar/favourites/favourite-folder.tsx (5)
1-23: Import statements look good.The import statements include necessary dependencies and components for the
FavouriteFoldercomponent.
28-30: Component definition looks good.The
FavouriteFoldercomponent is correctly defined with propsisLastChildandfavourite, which are appropriately typed.
45-45: Conditional function call looks good.The conditional call to
getGroupedFavouritesensures that the favorites are grouped correctly iffavourite.childrenis not present.
47-67: Function implementation looks good.The
handleRemoveFromFavoritesfunction correctly handles the removal of a favorite item and provides user feedback through toast notifications.
69-89: Function implementation looks good.The
handleOnDropfunction correctly handles the dropping of a favorite item and provides user feedback through toast notifications.web/core/store/project-view.store.ts (2)
361-364: Method change looks good.The
addViewToFavoritesmethod now correctly usesrootStore.favourite.addFavourite, aligning with the new centralized management of favorites.
388-388: Method change looks good.The
removeViewFromFavoritesmethod now correctly usesrootStore.favourite.removeFavouriteEntity, aligning with the new centralized management of favorites.web/core/store/project/project.store.ts (2)
282-286: Ensure the new favorite management logic is consistent.The function now uses
this.rootStore.favourite.addFavouritewith specific parameters. Verify thataddFavouritecorrectly handles the provided parameters.Verification successful
The new favorite management logic is consistent and correctly implemented.
The function
addFavouriteinfavourite.service.tsandfavourite.store.tscorrectly handles the provided parameters and integrates well within the store and service layers. The new implementation inproject.store.tsis consistent with other uses ofaddFavourite.
web/core/services/favourite/favourite.service.tsweb/core/store/favourite.store.tsScripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation of `addFavourite` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type typescript -A 10 $'addFavourite'Length of output: 76
Script:
#!/bin/bash # Description: Verify the implementation of `addFavourite` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type ts -A 10 $'addFavourite'Length of output: 9876
307-308: Ensure the new favorite removal logic is consistent.The function now uses
this.rootStore.favourite.removeFavouriteEntitywith specific parameters. Verify thatremoveFavouriteEntitycorrectly handles the provided parameters.Verification successful
The new favorite removal logic is consistent.
The function
removeFavouriteEntitycorrectly handles the provided parametersworkspaceSlugandentityId, ensuring the removal of the favorite entity from the store.
web/core/store/favourite.store.ts(implementation ofremoveFavouriteEntity)Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation of `removeFavouriteEntity` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type typescript -A 10 $'removeFavouriteEntity'Length of output: 85
Script:
#!/bin/bash # Description: Verify the implementation of `removeFavouriteEntity` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type ts -A 10 $'removeFavouriteEntity'Length of output: 5553
web/core/store/pages/page.ts (2)
482-492: Ensure the new favorite management logic is consistent.The function now uses
this.rootStore.favourite.addFavouritewith specific parameters. Verify thataddFavouritecorrectly handles the provided parameters.Verification successful
The new favorite management logic is consistent and correctly implemented.
The
addFavouritefunction infavourite.store.tscorrectly handles the provided parameters and updates the store accordingly.
web/core/store/favourite.store.ts: Implementation ofaddFavouriteScripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation of `addFavourite` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type typescript -A 10 $'addFavourite'Length of output: 76
Script:
#!/bin/bash # Description: Verify the implementation of `addFavourite` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg -A 10 'addFavourite'Length of output: 9866
508-508: Ensure the new favorite removal logic is consistent.The function now uses
this.rootStore.favourite.removeFavouriteEntitywith specific parameters. Verify thatremoveFavouriteEntitycorrectly handles the provided parameters.Verification successful
The new favorite removal logic is consistent and correctly handles the provided parameters.
The function
removeFavouriteEntityinfavourite.store.tsretrieves the favorite ID, deletes the favorite, and removes the entity from the map, with appropriate error handling.
web/core/store/favourite.store.tsScripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation of `removeFavouriteEntity` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type typescript -A 10 $'removeFavouriteEntity'Length of output: 85
Script:
#!/bin/bash # Description: Verify the implementation of `removeFavouriteEntity` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --glob '*.ts' -A 10 'removeFavouriteEntity'Length of output: 5557
web/core/store/module.store.ts (2)
489-492: Ensure the new favorite management logic is consistent.The function now uses
this.rootStore.favourite.addFavouritewith specific parameters. Verify thataddFavouritecorrectly handles the provided parameters.Verification successful
Ensure the new favorite management logic is consistent.
The function
addModuleToFavoritesnow usesthis.rootStore.favourite.addFavouritewith specific parameters. TheaddFavouritefunction infavourite.service.tsandfavourite.store.tscorrectly handles these parameters and integrates with the store and service layers, ensuring proper functionality.
web/core/services/favourite/favourite.service.tsweb/core/store/favourite.store.tsScripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation of `addFavourite` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type typescript -A 10 $'addFavourite'Length of output: 76
Script:
#!/bin/bash # Description: Verify the implementation of `addFavourite` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg 'addFavourite' -t ts -A 10Length of output: 9872
516-516: Ensure the new favorite removal logic is consistent.The function now uses
this.rootStore.favourite.removeFavouriteEntitywith specific parameters. Verify thatremoveFavouriteEntitycorrectly handles the provided parameters.Verification successful
Ensure the new favorite removal logic is consistent.
The function
removeFavouriteEntitycorrectly handles the provided parametersworkspaceSlugandentityId. The implementation deletes the favorite entity from theentityMapand handles errors appropriately.
web/core/store/favourite.store.ts:removeFavouriteEntityimplementationScripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the implementation of `removeFavouriteEntity` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg --type typescript -A 10 $'removeFavouriteEntity'Length of output: 85
Script:
#!/bin/bash # Description: Verify the implementation of `removeFavouriteEntity` in the codebase. # Test: Search for the function definition. Expect: Correct handling of parameters. rg 'removeFavouriteEntity' -g '*.ts' -A 10Length of output: 5553
|
|
||
| from .dashboard import DashboardSerializer, WidgetSerializer | ||
|
|
||
| from .favorite import UserFavoriteSerializer |
There was a problem hiding this comment.
Address the unused import.
The UserFavoriteSerializer is imported but not used in this file. If it is meant to be re-exported, consider adding it to __all__.
+ __all__ = [
+ ... # other serializers
+ 'UserFavoriteSerializer',
+ ]Committable suggestion was skipped due to low confidence.
Tools
Ruff
125-125:
.favorite.UserFavoriteSerializerimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
GitHub Check: Codacy Static Code Analysis
[notice] 125-125: apiserver/plane/app/serializers/init.py#L125
'.favorite.UserFavoriteSerializer' imported but unused (F401)
| def delete(self, request, slug, favorite_id): | ||
| favorite = UserFavorite.objects.get( | ||
| user=request.user, workspace__slug=slug, pk=favorite_id | ||
| ) | ||
| favorite.delete() | ||
| return Response(status=status.HTTP_204_NO_CONTENT) |
There was a problem hiding this comment.
Add error handling for UserFavorite.objects.get.
The UserFavorite.objects.get call can raise a DoesNotExist exception. Add error handling to manage this scenario.
- favorite = UserFavorite.objects.get(
- user=request.user, workspace__slug=slug, pk=favorite_id
- )
+ try:
+ favorite = UserFavorite.objects.get(
+ user=request.user, workspace__slug=slug, pk=favorite_id
+ )
+ except UserFavorite.DoesNotExist:
+ return Response({"detail": "Favorite not found."}, status=status.HTTP_404_NOT_FOUND)Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def delete(self, request, slug, favorite_id): | |
| favorite = UserFavorite.objects.get( | |
| user=request.user, workspace__slug=slug, pk=favorite_id | |
| ) | |
| favorite.delete() | |
| return Response(status=status.HTTP_204_NO_CONTENT) | |
| def delete(self, request, slug, favorite_id): | |
| try: | |
| favorite = UserFavorite.objects.get( | |
| user=request.user, workspace__slug=slug, pk=favorite_id | |
| ) | |
| except UserFavorite.DoesNotExist: | |
| return Response({"detail": "Favorite not found."}, status=status.HTTP_404_NOT_FOUND) | |
| favorite.delete() | |
| return Response(status=status.HTTP_204_NO_CONTENT) |
| def get(self, request, slug, favorite_id): | ||
| favorites = UserFavorite.objects.filter( | ||
| user=request.user, | ||
| workspace__slug=slug, | ||
| parent_id=favorite_id, | ||
| ).filter( | ||
| Q(project__isnull=True) | ||
| | ( | ||
| Q(project__isnull=False) | ||
| & Q(project__project_projectmember__member=request.user) | ||
| & Q(project__project_projectmember__is_active=True) | ||
| ) | ||
| ) | ||
| serializer = UserFavoriteSerializer(favorites, many=True) | ||
| return Response(serializer.data, status=status.HTTP_200_OK) |
There was a problem hiding this comment.
Simplify filter conditions in the get method.
The nested filter conditions can be simplified for better readability and performance.
favorites = UserFavorite.objects.filter(
user=request.user,
workspace__slug=slug,
parent_id=favorite_id,
).filter(
Q(project__isnull=True) |
Q(
project__isnull=False,
project__project_projectmember__member=request.user,
project__project_projectmember__is_active=True
)
)Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def get(self, request, slug, favorite_id): | |
| favorites = UserFavorite.objects.filter( | |
| user=request.user, | |
| workspace__slug=slug, | |
| parent_id=favorite_id, | |
| ).filter( | |
| Q(project__isnull=True) | |
| | ( | |
| Q(project__isnull=False) | |
| & Q(project__project_projectmember__member=request.user) | |
| & Q(project__project_projectmember__is_active=True) | |
| ) | |
| ) | |
| serializer = UserFavoriteSerializer(favorites, many=True) | |
| return Response(serializer.data, status=status.HTTP_200_OK) | |
| def get(self, request, slug, favorite_id): | |
| favorites = UserFavorite.objects.filter( | |
| user=request.user, | |
| workspace__slug=slug, | |
| parent_id=favorite_id, | |
| ).filter( | |
| Q(project__isnull=True) | | |
| Q( | |
| project__isnull=False, | |
| project__project_projectmember__member=request.user, | |
| project__project_projectmember__is_active=True | |
| ) | |
| ) | |
| serializer = UserFavoriteSerializer(favorites, many=True) | |
| return Response(serializer.data, status=status.HTTP_200_OK) |
| def get(self, request, slug): | ||
| # the second filter is to check if the user is a member of the project | ||
| favorites = UserFavorite.objects.filter( | ||
| user=request.user, | ||
| workspace__slug=slug, | ||
| parent__isnull=True, | ||
| ).filter( | ||
| Q(project__isnull=True) | ||
| | ( | ||
| Q(project__isnull=False) | ||
| & Q(project__project_projectmember__member=request.user) | ||
| & Q(project__project_projectmember__is_active=True) | ||
| ) | ||
| ) | ||
| serializer = UserFavoriteSerializer(favorites, many=True) | ||
| return Response(serializer.data, status=status.HTTP_200_OK) |
There was a problem hiding this comment.
Simplify filter conditions in the get method.
The nested filter conditions can be simplified for better readability and performance.
favorites = UserFavorite.objects.filter(
user=request.user,
workspace__slug=slug,
parent__isnull=True,
).filter(
Q(project__isnull=True) |
Q(
project__isnull=False,
project__project_projectmember__member=request.user,
project__project_projectmember__is_active=True
)
)Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def get(self, request, slug): | |
| # the second filter is to check if the user is a member of the project | |
| favorites = UserFavorite.objects.filter( | |
| user=request.user, | |
| workspace__slug=slug, | |
| parent__isnull=True, | |
| ).filter( | |
| Q(project__isnull=True) | |
| | ( | |
| Q(project__isnull=False) | |
| & Q(project__project_projectmember__member=request.user) | |
| & Q(project__project_projectmember__is_active=True) | |
| ) | |
| ) | |
| serializer = UserFavoriteSerializer(favorites, many=True) | |
| return Response(serializer.data, status=status.HTTP_200_OK) | |
| def get(self, request, slug): | |
| # the second filter is to check if the user is a member of the project | |
| favorites = UserFavorite.objects.filter( | |
| user=request.user, | |
| workspace__slug=slug, | |
| parent__isnull=True, | |
| ).filter( | |
| Q(project__isnull=True) | | |
| Q( | |
| project__isnull=False, | |
| project__project_projectmember__member=request.user, | |
| project__project_projectmember__is_active=True | |
| ) | |
| ) | |
| serializer = UserFavoriteSerializer(favorites, many=True) | |
| return Response(serializer.data, status=status.HTTP_200_OK) |
| def post(self, request, slug): | ||
| workspace = Workspace.objects.get(slug=slug) | ||
| serializer = UserFavoriteSerializer(data=request.data) | ||
| if serializer.is_valid(): | ||
| serializer.save( | ||
| user_id=request.user.id, | ||
| workspace=workspace, | ||
| project_id=request.data.get("project_id", None), | ||
| ) | ||
| return Response(serializer.data, status=status.HTTP_200_OK) | ||
| return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
There was a problem hiding this comment.
Add error handling for Workspace.objects.get.
The Workspace.objects.get call can raise a DoesNotExist exception. Add error handling to manage this scenario.
- workspace = Workspace.objects.get(slug=slug)
+ try:
+ workspace = Workspace.objects.get(slug=slug)
+ except Workspace.DoesNotExist:
+ return Response({"detail": "Workspace not found."}, status=status.HTTP_404_NOT_FOUND)Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def post(self, request, slug): | |
| workspace = Workspace.objects.get(slug=slug) | |
| serializer = UserFavoriteSerializer(data=request.data) | |
| if serializer.is_valid(): | |
| serializer.save( | |
| user_id=request.user.id, | |
| workspace=workspace, | |
| project_id=request.data.get("project_id", None), | |
| ) | |
| return Response(serializer.data, status=status.HTTP_200_OK) | |
| return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) | |
| def post(self, request, slug): | |
| try: | |
| workspace = Workspace.objects.get(slug=slug) | |
| except Workspace.DoesNotExist: | |
| return Response({"detail": "Workspace not found."}, status=status.HTTP_404_NOT_FOUND) | |
| serializer = UserFavoriteSerializer(data=request.data) | |
| if serializer.is_valid(): | |
| serializer.save( | |
| user_id=request.user.id, | |
| workspace=workspace, | |
| project_id=request.data.get("project_id", None), | |
| ) | |
| return Response(serializer.data, status=status.HTTP_200_OK) | |
| return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
| def patch(self, request, slug, favorite_id): | ||
| favorite = UserFavorite.objects.get( | ||
| user=request.user, workspace__slug=slug, pk=favorite_id | ||
| ) | ||
| serializer = UserFavoriteSerializer( | ||
| favorite, data=request.data, partial=True | ||
| ) | ||
| if serializer.is_valid(): | ||
| serializer.save() | ||
| return Response(serializer.data, status=status.HTTP_200_OK) | ||
| return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
There was a problem hiding this comment.
Add error handling for UserFavorite.objects.get.
The UserFavorite.objects.get call can raise a DoesNotExist exception. Add error handling to manage this scenario.
- favorite = UserFavorite.objects.get(
- user=request.user, workspace__slug=slug, pk=favorite_id
- )
+ try:
+ favorite = UserFavorite.objects.get(
+ user=request.user, workspace__slug=slug, pk=favorite_id
+ )
+ except UserFavorite.DoesNotExist:
+ return Response({"detail": "Favorite not found."}, status=status.HTTP_404_NOT_FOUND)Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def patch(self, request, slug, favorite_id): | |
| favorite = UserFavorite.objects.get( | |
| user=request.user, workspace__slug=slug, pk=favorite_id | |
| ) | |
| serializer = UserFavoriteSerializer( | |
| favorite, data=request.data, partial=True | |
| ) | |
| if serializer.is_valid(): | |
| serializer.save() | |
| return Response(serializer.data, status=status.HTTP_200_OK) | |
| return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) | |
| def patch(self, request, slug, favorite_id): | |
| try: | |
| favorite = UserFavorite.objects.get( | |
| user=request.user, workspace__slug=slug, pk=favorite_id | |
| ) | |
| except UserFavorite.DoesNotExist: | |
| return Response({"detail": "Favorite not found."}, status=status.HTTP_404_NOT_FOUND) | |
| serializer = UserFavoriteSerializer( | |
| favorite, data=request.data, partial=True | |
| ) | |
| if serializer.is_valid(): | |
| serializer.save() | |
| return Response(serializer.data, status=status.HTTP_200_OK) | |
| return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
| WorkspaceFavoriteEndpoint, | ||
| WorkspaceFavoriteGroupEndpoint, |
There was a problem hiding this comment.
Remove unused imports for WorkspaceFavoriteEndpoint and WorkspaceFavoriteGroupEndpoint.
The static analysis tool indicates that these imports are unused. Consider removing them to clean up the code.
- WorkspaceFavoriteEndpoint,
- WorkspaceFavoriteGroupEndpoint,Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| WorkspaceFavoriteEndpoint, | |
| WorkspaceFavoriteGroupEndpoint, |
Tools
Ruff
44-44:
.workspace.favorite.WorkspaceFavoriteEndpointimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
45-45:
.workspace.favorite.WorkspaceFavoriteGroupEndpointimported but unused; consider removing, adding to__all__, or using a redundant alias(F401)
web/core/components/workspace/sidebar/favourites/favourite-item.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (3)
- web/core/components/workspace/sidebar/favourites/favourite-folder.tsx (1 hunks)
- web/core/components/workspace/sidebar/favourites/favourite-item.tsx (1 hunks)
- web/core/components/workspace/sidebar/favourites/favourites-menu.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (3)
- web/core/components/workspace/sidebar/favourites/favourite-folder.tsx
- web/core/components/workspace/sidebar/favourites/favourite-item.tsx
- web/core/components/workspace/sidebar/favourites/favourites-menu.tsx
There was a problem hiding this comment.
Actionable comments posted: 18
Outside diff range, codebase verification and nitpick comments (11)
packages/types/src/favorite/favorite.d.ts (1)
1-14: Consider adding documentation comments for each property.Adding documentation comments can improve code readability and maintainability by providing context for each property.
+ /** + * Represents a favorite item. + */ export type IFavorite = { + /** + * Unique identifier for the favorite item. + */ id: string; + /** + * Name of the favorite item. + */ name: string; + /** + * Type of the entity (e.g., Cycle, Module, View, Page). + */ entity_type: string; + /** + * Additional data related to the entity. + */ entity_data: { + /** + * Name of the entity. + */ name: string; }; + /** + * Indicates if the item is a folder. + */ is_folder: boolean; + /** + * Sort order for the item. + */ sort_order: number; + /** + * Parent item ID, or null if there is no parent. + */ parent: string | null; + /** + * Optional identifier for the entity. + */ entity_identifier?: string | null; + /** + * List of child favorite items. + */ children: IFavorite[]; + /** + * Project ID associated with the favorite item, or null if not applicable. + */ project_id: string | null; };web/core/hooks/store/use-favorite.ts (1)
6-9: Improve error message clarity.The error message in the thrown error could be more specific to improve debugging.
- if (context === undefined) throw new Error("useFavorites must be used within StoreProvider"); + if (context === undefined) throw new Error("useFavorite must be used within a StoreProvider context");packages/ui/src/icons/favorite-folder-icon.tsx (1)
5-31: Consider adding PropTypes for better type checking.Using PropTypes can help catch type-related bugs during development.
import * as React from "react"; import PropTypes from "prop-types"; export const FavoriteFolderIcon: React.FC<ISvgIcons> = ({ className = "text-current", color = "#a3a3a3", ...rest }) => ( <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" stroke={color} className={`${className} stroke-2`} {...rest} > <path d="M7.33325 13.3334H2.66659C2.31296 13.3334 1.97382 13.1929 1.72378 12.9429C1.47373 12.6928 1.33325 12.3537 1.33325 12.0001V3.3334C1.33325 2.97978 1.47373 2.64064 1.72378 2.39059C1.97382 2.14054 2.31296 2.00006 2.66659 2.00006H5.26659C5.48958 1.99788 5.70955 2.05166 5.90638 2.15648C6.10322 2.2613 6.27061 2.41381 6.39325 2.60006L6.93325 3.40006C7.05466 3.58442 7.21994 3.73574 7.41425 3.84047C7.60857 3.94519 7.82585 4.00003 8.04658 4.00006H13.3333C13.6869 4.00006 14.026 4.14054 14.2761 4.39059C14.5261 4.64064 14.6666 4.97978 14.6666 5.3334V6.3334" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" /> <path d="M12.1373 8L13.0038 9.75535L14.9414 10.0386L13.5394 11.4041L13.8702 13.3333L12.1373 12.422L10.4044 13.3333L10.7353 11.4041L9.33325 10.0386L11.2709 9.75535L12.1373 8Z" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" fill="none" /> </svg> ); FavoriteFolderIcon.propTypes = { className: PropTypes.string, color: PropTypes.string, };web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (1)
1-6: Consider organizing imports for better readability.Group imports by their source (external libraries, internal modules, etc.) and sort them alphabetically.
web/core/store/root.store.ts (1)
56-56: Ensure thefavoritestore is reset on sign out.The
favoritestore is not currently being reset in theresetOnSignOutmethod. Please ensure that it is included in the reset process to maintain consistency and avoid potential issues.
web/core/store/root.store.tsAnalysis chain
Ensure the
favoritestore is reset on sign out.Verify that the
favoritestore is correctly reset in theresetOnSignOutmethod.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that the `favorite` store is correctly reset on sign out. # Test: Search for `resetOnSignOut` method. Expect: Correct reset of the `favorite` store. rg --type ts -A 5 $'resetOnSignOut'Length of output: 1569
Script:
#!/bin/bash # Description: Verify that the `favorite` store is correctly reset on sign out. # Test: Search for references to `favorite` in the context of reset or sign out. rg --type ts -A 5 'favorite'Length of output: 113410
web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (2)
1-2: Remove unnecessary "use client" directive.The
"use client"directive is not necessary in this context as this file is already a client component.- "use client";
3-7: Optimize the imports.Consider grouping similar imports together for better readability.
import React, { useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ChevronRight, FolderPlus } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react";web/core/components/workspace/sidebar/favorites/favorite-item.tsx (3)
1-2: Remove unnecessary "use client" directive.The
"use client"directive is not necessary in this context as this file is already a client component.- "use client";
3-9: Optimize the imports.Consider grouping similar imports together for better readability.
import React, { useEffect, useRef, useState } from "react"; import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { draggable } from "@atlaskit/pragmatic-drag-and-drop/element/adapter"; import { observer } from "mobx-react"; import Link from "next/link"; import { useParams } from "next/navigation"; import { Briefcase, FileText, Layers, MoreHorizontal, Star } from "lucide-react";
87-107: Ensure proper cleanup of drag-and-drop listeners.The
useEffecthook inweb/core/components/workspace/sidebar/favorites/favorite-item.tsxdoes not include any cleanup logic for the drag-and-drop listeners. To avoid potential memory leaks, ensure that the listeners are properly removed when the component is unmounted or dependencies change.
- File:
web/core/components/workspace/sidebar/favorites/favorite-item.tsx- Lines: 87-107
Analysis chain
Ensure proper cleanup of drag-and-drop listeners.
Ensure that the drag-and-drop listeners are properly cleaned up to avoid memory leaks.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that the drag-and-drop listeners are properly cleaned up. # Test: Search for the cleanup logic in the useEffect hook. Expect: Proper cleanup logic. rg --type js 'return combine(draggable'Length of output: 131
Script:
#!/bin/bash # Description: Verify that the drag-and-drop listeners are properly cleaned up. # Test: Search for the cleanup logic in the useEffect hook. Expect: Proper cleanup logic. rg --type js 'return combine\(draggable'Length of output: 42
Script:
#!/bin/bash # Description: Verify that the drag-and-drop listeners are properly cleaned up. # Test: Search for the useEffect hook and inspect for cleanup logic. rg --type js 'useEffect\(\(\) => \{[^}]*return combine\(draggable'Length of output: 68
Script:
#!/bin/bash # Description: Verify that the drag-and-drop listeners are properly cleaned up. # Test: Search for all useEffect hooks in the file and inspect for cleanup logic. rg --type js 'useEffect' web/core/components/workspace/sidebar/favorites/favorite-item.tsx -A 20Length of output: 1581
web/core/store/favorite.store.ts (1)
1-3: Optimize lodash imports.Consider importing only the specific lodash methods used to reduce bundle size.
- import { uniqBy } from "lodash"; - import set from "lodash/set"; + import uniqBy from "lodash/uniqBy"; + import set from "lodash/set";
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (22)
- packages/types/src/favorite/favorite.d.ts (1 hunks)
- packages/types/src/favorite/index.d.ts (1 hunks)
- packages/types/src/index.d.ts (1 hunks)
- packages/ui/src/icons/favorite-folder-icon.tsx (1 hunks)
- packages/ui/src/icons/index.ts (1 hunks)
- web/app/[workspaceSlug]/(projects)/sidebar.tsx (3 hunks)
- web/core/components/workspace/sidebar/favorites/favorite-folder.tsx (1 hunks)
- web/core/components/workspace/sidebar/favorites/favorite-item.tsx (1 hunks)
- web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (1 hunks)
- web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (1 hunks)
- web/core/constants/event-tracker.ts (1 hunks)
- web/core/hooks/store/use-favorite.ts (1 hunks)
- web/core/layouts/auth-layout/workspace-wrapper.tsx (3 hunks)
- web/core/services/favorite/favorite.service.ts (1 hunks)
- web/core/services/favorite/index.ts (1 hunks)
- web/core/store/cycle.store.ts (2 hunks)
- web/core/store/favorite.store.ts (1 hunks)
- web/core/store/module.store.ts (2 hunks)
- web/core/store/pages/page.ts (5 hunks)
- web/core/store/project-view.store.ts (2 hunks)
- web/core/store/project/project.store.ts (2 hunks)
- web/core/store/root.store.ts (3 hunks)
Files skipped from review due to trivial changes (2)
- packages/types/src/favorite/index.d.ts
- web/core/services/favorite/index.ts
Files skipped from review as they are similar to previous changes (10)
- packages/types/src/index.d.ts
- packages/ui/src/icons/index.ts
- web/app/[workspaceSlug]/(projects)/sidebar.tsx
- web/core/constants/event-tracker.ts
- web/core/layouts/auth-layout/workspace-wrapper.tsx
- web/core/store/cycle.store.ts
- web/core/store/module.store.ts
- web/core/store/pages/page.ts
- web/core/store/project-view.store.ts
- web/core/store/project/project.store.ts
Additional comments not posted (14)
web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (1)
21-24: EnsureuseParamsreturns the expected values.Verify that
useParamscorrectly returnsworkspaceSlugto avoid potential issues.Verification successful
Ensure
useParamsreturns the expected values.The
useParamsfunction is used to extractworkspaceSluginweb/core/components/workspace/sidebar/favorites/new-fav-folder.tsx. This usage is consistent with howuseParamsis expected to work when imported from "next/navigation".
web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx:useParamsis used to extractworkspaceSlug.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that `useParams` returns the expected values. # Test: Search for `useParams` usage. Expect: Correct usage and handling of returned values. rg --type tsx -A 5 $'useParams'Length of output: 58
Script:
#!/bin/bash # Description: Verify that `useParams` returns the expected values. # Test: Search for `useParams` usage. Expect: Correct usage and handling of returned values. rg --type typescript -A 5 'useParams'Length of output: 72
Script:
#!/bin/bash # Description: Verify that `useParams` returns the expected values. # Test: Search for `useParams` usage. Expect: Correct usage and handling of returned values. rg --type ts -A 5 'useParams' rg --type tsx -A 5 'useParams'Length of output: 341548
Script:
#!/bin/bash # Description: Verify that `useParams` returns the expected values in `new-fav-folder.tsx`. # Test: Search for `useParams` usage in `new-fav-folder.tsx`. rg 'useParams' -A 5 web/core/components/workspace/sidebar/favorites/new-fav-folder.tsxLength of output: 551
web/core/store/root.store.ts (2)
9-9: Consider using American English spelling for consistency.The British English spelling
favouriteis used instead of the American English spellingfavorite. This might cause inconsistency in the codebase. Consider renamingFavouriteStoreandIFavouriteStoretoFavoriteStoreandIFavoriteStore, respectively.
83-83: Ensure proper initialization of the newfavoritestore.Verify that the
FavoriteStoreis correctly initialized and integrated with other stores.Verification successful
Initialization and integration of
FavoriteStoreverified.The
FavoriteStoreis correctly imported, initialized in the constructor, and used within the codebase.
root.store.ts: Initialization ofFavoriteStore.favorite.store.ts: Implementation ofFavoriteStore.use-favorite.ts: Usage ofFavoriteStore.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that the `FavoriteStore` is correctly initialized. # Test: Search for `FavoriteStore` initialization. Expect: Correct initialization and integration. rg --type ts -A 5 $'FavoriteStore'Length of output: 2575
web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (2)
87-167: Ensure accessibility and usability.Ensure that the component is accessible and usable, especially for keyboard and screen reader users.
62-64: EnsuretoggleFavoriteMenuis defined.Ensure that
toggleFavoriteMenuis defined and notundefinedwhen used in theuseEffecthook.Verification successful
toggleFavoriteMenuis defined and notundefined.The
toggleFavoriteMenuis defined via destructuring fromuseLocalStorage<boolean>("is_favorite_menu_open", false)and is used multiple times within the same file.
web/core/components/workspace/sidebar/favorites/favorites-menu.tsxScripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that `toggleFavoriteMenu` is defined and not `undefined`. # Test: Search for the definition of `toggleFavoriteMenu`. Expect: It should be defined. rg --type js 'const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage'Length of output: 246
Script:
#!/bin/bash # Description: Verify that `toggleFavoriteMenu` is defined and not `undefined`. # Test: Search for the definition of `toggleFavoriteMenu`. Expect: It should be defined. rg --type js 'const \{ setValue: toggleFavoriteMenu, storedValue \} = useLocalStorage'Length of output: 88
Script:
#!/bin/bash # Description: Verify that `toggleFavoriteMenu` is defined and not `undefined`. # Test: Search for any definition or assignment of `toggleFavoriteMenu`. Expect: It should be defined. rg --type js 'toggleFavoriteMenu'Length of output: 33
Script:
#!/bin/bash # Description: Verify that `toggleFavoriteMenu` is defined and not `undefined`. # Test: Search for any function definitions or imports related to `toggleFavoriteMenu`. Expect: It should be defined. rg --type js 'toggleFavoriteMenu'Length of output: 33
Script:
#!/bin/bash # Description: Verify that `toggleFavoriteMenu` is defined and not `undefined`. # Test: Search for any occurrences of `toggleFavoriteMenu` in the codebase, including function definitions, variable assignments, and imports. rg 'toggleFavoriteMenu'Length of output: 896
web/core/components/workspace/sidebar/favorites/favorite-item.tsx (1)
110-176: Ensure accessibility and usability.Ensure that the component is accessible and usable, especially for keyboard and screen reader users.
web/core/store/favorite.store.ts (1)
145-163: Improve error handling indeleteFavorite.The error handling in the
deleteFavoritemethod could be improved by logging the error for debugging purposes.catch (error) { console.error("Failed to delete favorite:", error); throw error; }Likely invalid or redundant comment.
web/core/components/workspace/sidebar/favorites/favorite-folder.tsx (7)
31-39: Initialize state and refs correctly.Ensure that state variables and refs are initialized correctly and used appropriately within the component.
50-70: Handle errors and update state correctly inhandleOnDrop.The
handleOnDropfunction handles the drop event, updates the favorite item, and sets toast messages for success and error cases. Ensure that the error handling is robust.
72-103: ImplementuseEffecthook correctly.The
useEffecthook sets up the drag-and-drop functionality and cleans up resources when the component unmounts. Ensure that the dependencies are correctly listed.
105-105: UseuseOutsideClickDetectorhook correctly.The
useOutsideClickDetectorhook is used to detect clicks outside theactionSectionRefelement and deactivate the menu. Ensure that the hook is implemented correctly.
107-245: Implement render logic correctly.The render logic includes conditional rendering for renaming folders and displaying favorite items. Ensure that the logic handles all edge cases and renders UI elements correctly.
1-23: Ensure all imported modules are used.Verify that all imported modules and components are utilized within the file to avoid unused imports.
Verification successful
All imported modules and components are used within the file.
No unused imports were found in
web/core/components/workspace/sidebar/favorites/favorite-folder.tsx.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the usage of imported modules and components. # Test: Search for the usage of each imported module and component. Expect: All imports are used. rg --type tsx -A 5 $'useEffect|useRef|useState|combine|dropTargetForElements|useParams|PenSquare|Star|MoreHorizontal|ChevronRight|Disclosure|Transition|IFavorite|CustomMenu|Tooltip|DropIndicator|setToast|TOAST_TYPE|FavoriteFolderIcon|cn|useAppTheme|useFavorite|useOutsideClickDetector|usePlatformOS|FavoriteItem|NewFavoriteFolder'Length of output: 359
Script:
#!/bin/bash # Description: Verify the usage of imported modules and components within the specific file. # Test: Search for the usage of each imported module and component in the specified file. Expect: All imports are used. rg 'useEffect|useRef|useState|combine|dropTargetForElements|useParams|PenSquare|Star|MoreHorizontal|ChevronRight|Disclosure|Transition|IFavorite|CustomMenu|Tooltip|DropIndicator|setToast|TOAST_TYPE|FavoriteFolderIcon|cn|useAppTheme|useFavorite|useOutsideClickDetector|usePlatformOS|FavoriteItem|NewFavoriteFolder' web/core/components/workspace/sidebar/favorites/favorite-folder.tsxLength of output: 4375
25-29: Ensure all props are used.Verify that all props defined in the
Propstype are utilized within theFavoriteFoldercomponent.Verification successful
Let's re-run the verification script with the correct file type for TypeScript files.
All props are used correctly.
The
isLastChild,favorite, andhandleRemoveFromFavoritesprops defined in thePropstype are utilized within theFavoriteFoldercomponent.
isLastChildis used on lines 25, 26, 27, 28, 29.favoriteis used on lines 25, 26, 27, 28, 29.handleRemoveFromFavoritesis used on lines 25, 26, 27, 28, 29.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the usage of props in the FavoriteFolder component. # Test: Search for the usage of each prop. Expect: All props are used. rg --type tsx -A 5 $'isLastChild|favorite|handleRemoveFromFavorites'Length of output: 97
Script:
#!/bin/bash # Description: Verify the usage of props in the FavoriteFolder component. # Test: Search for the usage of each prop. Expect: All props are used. rg --type-add 'tsx:*.{ts,tsx}' --type tsx -A 5 'isLastChild|favorite|handleRemoveFromFavorites'Length of output: 141331
| const handleRemoveFromFavorites = (favorite: IFavorite) => { | ||
| deleteFavorite(workspaceSlug.toString(), favorite.id) | ||
| .then(() => { | ||
| setToast({ | ||
| type: TOAST_TYPE.SUCCESS, | ||
| title: "Success!", | ||
| message: "Favorite removed successfully.", | ||
| }); | ||
| }) | ||
| .catch((err) => { | ||
| Object.keys(err.data).map((key) => { | ||
| setToast({ | ||
| type: TOAST_TYPE.ERROR, | ||
| title: "Error!", | ||
| message: err.data[key], | ||
| }); | ||
| }); | ||
| }); | ||
| }; |
There was a problem hiding this comment.
Improve error handling in handleRemoveFromFavorites.
The error handling in the handleRemoveFromFavorites function could be improved by logging the error for debugging purposes.
.catch((err) => {
console.error("Failed to remove favorite:", err);
Object.keys(err.data).map((key) => {
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: err.data[key],
});
});
});Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const handleRemoveFromFavorites = (favorite: IFavorite) => { | |
| deleteFavorite(workspaceSlug.toString(), favorite.id) | |
| .then(() => { | |
| setToast({ | |
| type: TOAST_TYPE.SUCCESS, | |
| title: "Success!", | |
| message: "Favorite removed successfully.", | |
| }); | |
| }) | |
| .catch((err) => { | |
| Object.keys(err.data).map((key) => { | |
| setToast({ | |
| type: TOAST_TYPE.ERROR, | |
| title: "Error!", | |
| message: err.data[key], | |
| }); | |
| }); | |
| }); | |
| }; | |
| const handleRemoveFromFavorites = (favorite: IFavorite) => { | |
| deleteFavorite(workspaceSlug.toString(), favorite.id) | |
| .then(() => { | |
| setToast({ | |
| type: TOAST_TYPE.SUCCESS, | |
| title: "Success!", | |
| message: "Favorite removed successfully.", | |
| }); | |
| }) | |
| .catch((err) => { | |
| console.error("Failed to remove favorite:", err); | |
| Object.keys(err.data).map((key) => { | |
| setToast({ | |
| type: TOAST_TYPE.ERROR, | |
| title: "Error!", | |
| message: err.data[key], | |
| }); | |
| }); | |
| }); | |
| }; |
| /** | ||
| * Implementing scroll animation styles based on the scroll length of the container | ||
| */ | ||
| useEffect(() => { | ||
| const handleScroll = () => { | ||
| if (containerRef.current) { | ||
| const scrollTop = containerRef.current.scrollTop; | ||
| setIsScrolled(scrollTop > 0); | ||
| } | ||
| }; | ||
| const currentContainerRef = containerRef.current; | ||
| if (currentContainerRef) { | ||
| currentContainerRef.addEventListener("scroll", handleScroll); | ||
| } | ||
| return () => { | ||
| if (currentContainerRef) { | ||
| currentContainerRef.removeEventListener("scroll", handleScroll); | ||
| } | ||
| }; | ||
| }, [containerRef]); |
There was a problem hiding this comment.
Consider debouncing the scroll event listener.
To improve performance, consider debouncing the scroll event listener to reduce the frequency of state updates.
useEffect(() => {
const handleScroll = () => {
if (containerRef.current) {
const scrollTop = containerRef.current.scrollTop;
setIsScrolled(scrollTop > 0);
}
};
const debouncedHandleScroll = debounce(handleScroll, 100);
const currentContainerRef = containerRef.current;
if (currentContainerRef) {
currentContainerRef.addEventListener("scroll", debouncedHandleScroll);
}
return () => {
if (currentContainerRef) {
currentContainerRef.removeEventListener("scroll", debouncedHandleScroll);
}
};
}, [containerRef]);Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * Implementing scroll animation styles based on the scroll length of the container | |
| */ | |
| useEffect(() => { | |
| const handleScroll = () => { | |
| if (containerRef.current) { | |
| const scrollTop = containerRef.current.scrollTop; | |
| setIsScrolled(scrollTop > 0); | |
| } | |
| }; | |
| const currentContainerRef = containerRef.current; | |
| if (currentContainerRef) { | |
| currentContainerRef.addEventListener("scroll", handleScroll); | |
| } | |
| return () => { | |
| if (currentContainerRef) { | |
| currentContainerRef.removeEventListener("scroll", handleScroll); | |
| } | |
| }; | |
| }, [containerRef]); | |
| /** | |
| * Implementing scroll animation styles based on the scroll length of the container | |
| */ | |
| useEffect(() => { | |
| const handleScroll = () => { | |
| if (containerRef.current) { | |
| const scrollTop = containerRef.current.scrollTop; | |
| setIsScrolled(scrollTop > 0); | |
| } | |
| }; | |
| const debouncedHandleScroll = debounce(handleScroll, 100); | |
| const currentContainerRef = containerRef.current; | |
| if (currentContainerRef) { | |
| currentContainerRef.addEventListener("scroll", debouncedHandleScroll); | |
| } | |
| return () => { | |
| if (currentContainerRef) { | |
| currentContainerRef.removeEventListener("scroll", debouncedHandleScroll); | |
| } | |
| }; | |
| }, [containerRef]); |
| async updateFavorite(workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>): Promise<IFavorite> { | ||
| console.log("updateFavorite", data); |
There was a problem hiding this comment.
Avoid logging sensitive data in production.
Logging data in production can lead to potential security issues. Ensure this logging is disabled or removed in production environments.
- console.log("updateFavorite", data);Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async updateFavorite(workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>): Promise<IFavorite> { | |
| console.log("updateFavorite", data); | |
| async updateFavorite(workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>): Promise<IFavorite> { |
| return this.post(`/api/workspaces/${workspaceSlug}/user-favorites/`, data) | ||
| .then((response) => response?.data) | ||
| .catch((error) => { | ||
| throw error?.response; | ||
| }); |
There was a problem hiding this comment.
Ensure proper error handling.
The method throws the error response directly. Consider providing more context or a user-friendly message.
- throw error?.response;
+ throw new Error(error?.response?.data?.message || "Failed to add favorite");Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return this.post(`/api/workspaces/${workspaceSlug}/user-favorites/`, data) | |
| .then((response) => response?.data) | |
| .catch((error) => { | |
| throw error?.response; | |
| }); | |
| return this.post(`/api/workspaces/${workspaceSlug}/user-favorites/`, data) | |
| .then((response) => response?.data) | |
| .catch((error) => { | |
| throw new Error(error?.response?.data?.message || "Failed to add favorite"); | |
| }); |
| addFavorite = async (workspaceSlug: string, data: Partial<IFavorite>) => { | ||
| try { | ||
| data = { ...data, parent: null, is_folder: data.entity_type === "folder" }; | ||
| const response = await this.favoriteService.addFavorite(workspaceSlug, data); | ||
| runInAction(() => { | ||
| set(this.favoriteMap, [response.id], response); | ||
| response.entity_identifier && set(this.entityMap, [response.entity_identifier], response); | ||
| this.favoriteIds = [response.id, ...this.favoriteIds]; | ||
| }); | ||
| return response; | ||
| } catch (error) { | ||
| console.log("Failed to create favorite from favorite store"); | ||
| throw error; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Improve error handling in addFavorite.
The error handling in the addFavorite method could be improved by logging the error for debugging purposes.
catch (error) {
console.error("Failed to create favorite:", error);
throw error;
}Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| addFavorite = async (workspaceSlug: string, data: Partial<IFavorite>) => { | |
| try { | |
| data = { ...data, parent: null, is_folder: data.entity_type === "folder" }; | |
| const response = await this.favoriteService.addFavorite(workspaceSlug, data); | |
| runInAction(() => { | |
| set(this.favoriteMap, [response.id], response); | |
| response.entity_identifier && set(this.entityMap, [response.entity_identifier], response); | |
| this.favoriteIds = [response.id, ...this.favoriteIds]; | |
| }); | |
| return response; | |
| } catch (error) { | |
| console.log("Failed to create favorite from favorite store"); | |
| throw error; | |
| } | |
| }; | |
| try { | |
| data = { ...data, parent: null, is_folder: data.entity_type === "folder" }; | |
| const response = await this.favoriteService.addFavorite(workspaceSlug, data); | |
| runInAction(() => { | |
| set(this.favoriteMap, [response.id], response); | |
| response.entity_identifier && set(this.entityMap, [response.entity_identifier], response); | |
| this.favoriteIds = [response.id, ...this.favoriteIds]; | |
| }); | |
| return response; | |
| } catch (error) { | |
| console.error("Failed to create favorite:", error); | |
| throw error; | |
| } |
| updateFavorite = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => { | ||
| try { | ||
| const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data); | ||
| runInAction(() => { | ||
| set(this.favoriteMap, [response.id], response); | ||
| }); | ||
| return response; | ||
| } catch (error) { | ||
| console.log("Failed to update favorite from favorite store"); | ||
| throw error; | ||
| } |
There was a problem hiding this comment.
Improve error handling in updateFavorite.
The error handling in the updateFavorite method could be improved by logging the error for debugging purposes.
catch (error) {
console.error("Failed to update favorite:", error);
throw error;
}Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| updateFavorite = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => { | |
| try { | |
| const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data); | |
| runInAction(() => { | |
| set(this.favoriteMap, [response.id], response); | |
| }); | |
| return response; | |
| } catch (error) { | |
| console.log("Failed to update favorite from favorite store"); | |
| throw error; | |
| } | |
| updateFavorite = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => { | |
| try { | |
| const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data); | |
| runInAction(() => { | |
| set(this.favoriteMap, [response.id], response); | |
| }); | |
| return response; | |
| } catch (error) { | |
| console.error("Failed to update favorite:", error); | |
| throw error; | |
| } |
| getGroupedFavorites = async (workspaceSlug: string, favoriteId: string) => { | ||
| try { | ||
| const response = await this.favoriteService.getGroupedFavorites(workspaceSlug, favoriteId); | ||
| runInAction(() => { | ||
| // add children to the favorite | ||
| set(this.favoriteMap, [favoriteId], { ...this.favoriteMap[favoriteId], children: response }); | ||
| // add the favorites to the map | ||
| response.forEach((favorite) => { | ||
| set(this.favoriteMap, [favorite.id], favorite); | ||
| this.favoriteIds.push(favorite.id); | ||
| this.favoriteIds = uniqBy(this.favoriteIds, (id) => id); | ||
| favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); | ||
| }); | ||
| }); | ||
|
|
||
| return response; | ||
| } catch (error) { | ||
| console.log("Failed to get grouped favorites from favorite store"); | ||
| throw error; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Improve error handling in getGroupedFavorites.
The error handling in the getGroupedFavorites method could be improved by logging the error for debugging purposes.
catch (error) {
console.error("Failed to get grouped favorites:", error);
throw error;
}Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| getGroupedFavorites = async (workspaceSlug: string, favoriteId: string) => { | |
| try { | |
| const response = await this.favoriteService.getGroupedFavorites(workspaceSlug, favoriteId); | |
| runInAction(() => { | |
| // add children to the favorite | |
| set(this.favoriteMap, [favoriteId], { ...this.favoriteMap[favoriteId], children: response }); | |
| // add the favorites to the map | |
| response.forEach((favorite) => { | |
| set(this.favoriteMap, [favorite.id], favorite); | |
| this.favoriteIds.push(favorite.id); | |
| this.favoriteIds = uniqBy(this.favoriteIds, (id) => id); | |
| favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); | |
| }); | |
| }); | |
| return response; | |
| } catch (error) { | |
| console.log("Failed to get grouped favorites from favorite store"); | |
| throw error; | |
| } | |
| }; | |
| getGroupedFavorites = async (workspaceSlug: string, favoriteId: string) => { | |
| try { | |
| const response = await this.favoriteService.getGroupedFavorites(workspaceSlug, favoriteId); | |
| runInAction(() => { | |
| // add children to the favorite | |
| set(this.favoriteMap, [favoriteId], { ...this.favoriteMap[favoriteId], children: response }); | |
| // add the favorites to the map | |
| response.forEach((favorite) => { | |
| set(this.favoriteMap, [favorite.id], favorite); | |
| this.favoriteIds.push(favorite.id); | |
| this.favoriteIds = uniqBy(this.favoriteIds, (id) => id); | |
| favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); | |
| }); | |
| }); | |
| return response; | |
| } catch (error) { | |
| console.error("Failed to get grouped favorites:", error); | |
| throw error; | |
| } | |
| }; |
| fetchFavorite = async (workspaceSlug: string) => { | ||
| try { | ||
| const favorites = await this.favoriteService.getFavorites(workspaceSlug); | ||
| runInAction(() => { | ||
| favorites.forEach((favorite) => { | ||
| set(this.favoriteMap, [favorite.id], favorite); | ||
| this.favoriteIds.push(favorite.id); | ||
| favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); | ||
| }); | ||
| }); | ||
| return favorites; | ||
| } catch (error) { | ||
| console.log("Failed to fetch favorites from workspace store"); | ||
| throw error; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Improve error handling in fetchFavorite.
The error handling in the fetchFavorite method could be improved by logging the error for debugging purposes.
catch (error) {
console.error("Failed to fetch favorites:", error);
throw error;
}Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fetchFavorite = async (workspaceSlug: string) => { | |
| try { | |
| const favorites = await this.favoriteService.getFavorites(workspaceSlug); | |
| runInAction(() => { | |
| favorites.forEach((favorite) => { | |
| set(this.favoriteMap, [favorite.id], favorite); | |
| this.favoriteIds.push(favorite.id); | |
| favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); | |
| }); | |
| }); | |
| return favorites; | |
| } catch (error) { | |
| console.log("Failed to fetch favorites from workspace store"); | |
| throw error; | |
| } | |
| }; | |
| fetchFavorite = async (workspaceSlug: string) => { | |
| try { | |
| const favorites = await this.favoriteService.getFavorites(workspaceSlug); | |
| runInAction(() => { | |
| favorites.forEach((favorite) => { | |
| set(this.favoriteMap, [favorite.id], favorite); | |
| this.favoriteIds.push(favorite.id); | |
| favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); | |
| }); | |
| }); | |
| return favorites; | |
| } catch (error) { | |
| console.error("Failed to fetch favorites:", error); | |
| throw error; | |
| } | |
| }; |
| moveFavorite = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => { | ||
| try { | ||
| const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data); | ||
| runInAction(() => { | ||
| // add the favorite to the new parent | ||
| if (!data.parent) return; | ||
| set(this.favoriteMap, [data.parent], { | ||
| ...this.favoriteMap[data.parent], | ||
| children: [response, ...this.favoriteMap[data.parent].children], | ||
| }); | ||
|
|
||
| // remove the favorite from the old parent | ||
| const oldParent = this.favoriteMap[favoriteId].parent; | ||
| if (oldParent) { | ||
| set(this.favoriteMap, [oldParent], { | ||
| ...this.favoriteMap[oldParent], | ||
| children: this.favoriteMap[oldParent].children.filter((child) => child.id !== favoriteId), | ||
| }); | ||
| } | ||
|
|
||
| // add parent of the favorite | ||
| set(this.favoriteMap, [favoriteId], { | ||
| ...this.favoriteMap[favoriteId], | ||
| parent: data.parent, | ||
| }); | ||
| }); | ||
| } catch (error) { | ||
| console.log("Failed to move favorite from favorite store"); | ||
| throw error; | ||
| } | ||
| }; |
There was a problem hiding this comment.
Improve error handling in moveFavorite.
The error handling in the moveFavorite method could be improved by logging the error for debugging purposes.
catch (error) {
console.error("Failed to move favorite:", error);
throw error;
}Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| moveFavorite = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => { | |
| try { | |
| const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data); | |
| runInAction(() => { | |
| // add the favorite to the new parent | |
| if (!data.parent) return; | |
| set(this.favoriteMap, [data.parent], { | |
| ...this.favoriteMap[data.parent], | |
| children: [response, ...this.favoriteMap[data.parent].children], | |
| }); | |
| // remove the favorite from the old parent | |
| const oldParent = this.favoriteMap[favoriteId].parent; | |
| if (oldParent) { | |
| set(this.favoriteMap, [oldParent], { | |
| ...this.favoriteMap[oldParent], | |
| children: this.favoriteMap[oldParent].children.filter((child) => child.id !== favoriteId), | |
| }); | |
| } | |
| // add parent of the favorite | |
| set(this.favoriteMap, [favoriteId], { | |
| ...this.favoriteMap[favoriteId], | |
| parent: data.parent, | |
| }); | |
| }); | |
| } catch (error) { | |
| console.log("Failed to move favorite from favorite store"); | |
| throw error; | |
| } | |
| }; | |
| moveFavorite = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => { | |
| try { | |
| const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data); | |
| runInAction(() => { | |
| // add the favorite to the new parent | |
| if (!data.parent) return; | |
| set(this.favoriteMap, [data.parent], { | |
| ...this.favoriteMap[data.parent], | |
| children: [response, ...this.favoriteMap[data.parent].children], | |
| }); | |
| // remove the favorite from the old parent | |
| const oldParent = this.favoriteMap[favoriteId].parent; | |
| if (oldParent) { | |
| set(this.favoriteMap, [oldParent], { | |
| ...this.favoriteMap[oldParent], | |
| children: this.favoriteMap[oldParent].children.filter((child) => child.id !== favoriteId), | |
| }); | |
| } | |
| // add parent of the favorite | |
| set(this.favoriteMap, [favoriteId], { | |
| ...this.favoriteMap[favoriteId], | |
| parent: data.parent, | |
| }); | |
| }); | |
| } catch (error) { | |
| console.error("Failed to move favorite:", error); | |
| throw error; | |
| } | |
| }; |
web/core/components/workspace/sidebar/favorites/favorites-menu.tsx
Outdated
Show resolved
Hide resolved
web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| async addFavorite(workspaceSlug: string, data: Partial<IFavorite>): Promise<IFavorite> { | ||
| console.log("addFavorite", data); |
There was a problem hiding this comment.
please remove console.logs
web/core/store/favorite.store.ts
Outdated
| }); | ||
| }); | ||
| } catch (error) { | ||
| console.log("Failed to move favorite from favorite store"); |
There was a problem hiding this comment.
please change to console.error
| * @param data | ||
| * @returns Promise<IFavorite> | ||
| */ | ||
| addFavorite = async (workspaceSlug: string, data: Partial<IFavorite>) => { |
There was a problem hiding this comment.
Can you make this optimistic?
There was a problem hiding this comment.
Actionable comments posted: 0
Outside diff range, codebase verification and nitpick comments (1)
web/core/store/project-view.store.ts (1)
361-365: Inconsistency Found: UpdateaddViewToFavoritesinview.service.tsThe
addViewToFavoritesfunction inweb/core/services/view.service.tsstill uses the old implementation. Please update it to match the new structure as seen inproject-view.store.ts.
web/core/services/view.service.tsAnalysis chain
LGTM! But verify the function usage in the codebase.
The code changes are approved.
However, ensure that all function calls to
addViewToFavoritesmatch the new implementation.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all function calls to `addViewToFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --type typescript -A 5 $'addViewToFavorites'Length of output: 81
Script:
#!/bin/bash # Description: Verify all function calls to `addViewToFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --glob '*.ts' -A 5 $'addViewToFavorites'Length of output: 1749
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (15)
- apiserver/plane/app/views/cycle/base.py (1 hunks)
- apiserver/plane/app/views/module/base.py (1 hunks)
- apiserver/plane/app/views/page/base.py (1 hunks)
- apiserver/plane/app/views/project/base.py (1 hunks)
- apiserver/plane/app/views/view/base.py (1 hunks)
- apiserver/plane/app/views/workspace/favorite.py (1 hunks)
- web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (1 hunks)
- web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx (1 hunks)
- web/core/services/favorite/favorite.service.ts (1 hunks)
- web/core/store/cycle.store.ts (2 hunks)
- web/core/store/favorite.store.ts (1 hunks)
- web/core/store/module.store.ts (2 hunks)
- web/core/store/pages/page.ts (5 hunks)
- web/core/store/project-view.store.ts (2 hunks)
- web/core/store/project/project.store.ts (2 hunks)
Files skipped from review as they are similar to previous changes (7)
- apiserver/plane/app/views/workspace/favorite.py
- web/core/components/workspace/sidebar/favorites/favorites-menu.tsx
- web/core/components/workspace/sidebar/favorites/new-fav-folder.tsx
- web/core/services/favorite/favorite.service.ts
- web/core/store/favorite.store.ts
- web/core/store/module.store.ts
- web/core/store/pages/page.ts
Additional comments not posted (10)
web/core/store/project-view.store.ts (1)
389-389: LGTM! But verify the function usage in the codebase.The code changes are approved.
However, ensure that all function calls to
removeViewFromFavoritesmatch the new implementation.Verification successful
LGTM! The new implementation of
removeViewFromFavoritesis correctly used, and the old implementation is not present in the codebase.
- The code changes are approved.
- No further action is required as the old implementation is not used elsewhere.
Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all function calls to `removeViewFromFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --type typescript -A 5 $'removeViewFromFavorites'Length of output: 86
Script:
#!/bin/bash # Description: Verify all function calls to `removeViewFromFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --glob '*.ts' -A 5 'removeViewFromFavorites'Length of output: 1908
Script:
#!/bin/bash # Description: Verify if `removeViewFromFavorites` in `view.service.ts` is used elsewhere in the codebase. # Test: Search for the function usage. Expect: No occurrences of the old implementation. rg --glob '*.ts' -A 5 'viewService.removeViewFromFavorites'Length of output: 59
web/core/store/project/project.store.ts (2)
282-287: LGTM! But verify the function usage in the codebase.The code changes are approved.
However, ensure that all function calls to
addProjectToFavoritesmatch the new implementation.Verification successful
LGTM! But verify the function usage in the codebase.
The code changes are approved, and the new implementation of
addProjectToFavoritesis correctly used in the codebase. However, there is an older implementation inweb/core/services/project/project.service.tsthat should be reviewed and potentially removed if it is no longer needed.
web/core/services/project/project.service.ts: Review and remove the old implementation ofaddProjectToFavoritesif it is no longer in use.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all function calls to `addProjectToFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --type typescript -A 5 $'addProjectToFavorites'Length of output: 84
Script:
#!/bin/bash # Description: Verify all function calls to `addProjectToFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --glob '*.ts' -A 5 $'addProjectToFavorites'Length of output: 2221
308-309: LGTM! But verify the function usage in the codebase.The code changes are approved.
However, ensure that all function calls to
removeProjectFromFavoritesmatch the new implementation.Verification successful
Let's re-run the search for the function usage with the corrected file extension.
Let's check if the old method in
web/core/services/project/project.service.tsis still being used elsewhere in the codebase.
LGTM! But verify the function usage in the codebase.
The code changes are approved.
All function calls to
removeProjectFromFavoritesmatch the new implementation. The old method inproject.service.tsis no longer in use.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify all function calls to `removeProjectFromFavorites` match the new implementation. # Test: Search for the function usage. Expect: Only occurrences of the new implementation. rg --type typescript -A 5 $'removeProjectFromFavorites'Length of output: 89
Script:
#!/bin/bash # Description: Verify all function calls to `removeProjectFromFavorites` match the new implementation. # Test: Search for the function usage in TypeScript files. Expect: Only occurrences of the new implementation. rg --glob '*.ts' -A 5 $'removeProjectFromFavorites'Length of output: 2278
Script:
#!/bin/bash # Description: Verify if the old method `removeProjectFromFavorites` in `project.service.ts` is still being used elsewhere in the codebase. # Test: Search for the usage of the old method in the codebase. Expect: No occurrences of the old implementation. rg --glob '*.ts' -A 5 $'projectService.removeProjectFromFavorites'Length of output: 65
apiserver/plane/app/views/view/base.py (1)
477-477: LGTM! But verify the deletion behavior in the codebase.The code changes are approved.
However, ensure that the
soft=Falseargument aligns with the intended deletion behavior.Verification successful
LGTM! The deletion behavior with
soft=Falseis consistent with the intended hard delete functionality.
- The
deletemethod inapiserver/plane/db/mixins.pysupports asoftparameter, and settingsoft=Falseperforms a hard delete.Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the deletion behavior of `view_favorite` with `soft=False`. # Test: Search for the `delete` method usage with `soft=False`. Expect: Consistent usage across the codebase. rg --type python -A 5 $'delete(soft=False)'Length of output: 75
Script:
#!/bin/bash # Description: Verify the deletion behavior of `view_favorite` with `soft=False`. # Test: Search for the `delete` method usage with `soft=False`. Expect: Consistent usage across the codebase. rg 'delete(soft=False)' --glob '*.py' -A 5Length of output: 44
Script:
#!/bin/bash # Description: Inspect the `delete` method definition to understand the `soft=False` argument. # Search for the `delete` method definition in Python files. rg 'def delete' --glob '*.py' -A 10Length of output: 34249
apiserver/plane/app/views/page/base.py (1)
404-404: Verify the impact of usingsoft=Falsein the delete method.The
soft=Falseparameter ensures a hard delete. Verify that this change aligns with the intended behavior and does not impact data retention policies or recovery options.web/core/store/cycle.store.ts (2)
555-560: Verify the parameters passed toaddFavorite.Ensure that the parameters
entity_type,entity_identifier, andproject_idare correct and align with the intended behavior of adding a cycle to favorites.
583-583: Verify the parameters passed toremoveFavoriteEntity.Ensure that the parameters
workspaceSlugandcycleIdare correct and align with the intended behavior of removing a cycle from favorites.apiserver/plane/app/views/project/base.py (1)
602-602: Verify the impact of usingsoft=Falsein the delete method.The
soft=Falseparameter ensures a hard delete. Verify that this change aligns with the intended behavior and does not impact data retention policies or recovery options.apiserver/plane/app/views/module/base.py (1)
843-843: Verify the necessity of hard delete.The change to
soft=Falsein thedeletemethod call alters the deletion behavior from a soft delete to a hard delete. Ensure this change aligns with the application's data integrity and user experience requirements.apiserver/plane/app/views/cycle/base.py (1)
1157-1157: Verify the necessity of hard delete.The change to
soft=Falsein thedeletemethod call alters the deletion behavior from a soft delete to a hard delete. Ensure this change aligns with the application's data integrity and user experience requirements.
…lane into chore/user-favorites
There was a problem hiding this comment.
Actionable comments posted: 0
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (1)
- web/core/components/workspace/sidebar/favorites/favorite-folder.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- web/core/components/workspace/sidebar/favorites/favorite-folder.tsx
Implementation
[WEB-1907]
Summary by CodeRabbit
Summary by CodeRabbit
New Features
FavoriteFoldercomponent for interactive management of favorite items.Bug Fixes
Documentation
Chores