-
Notifications
You must be signed in to change notification settings - Fork 3
Config refactor #369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Config refactor #369
Conversation
Reviewer's GuideThis PR overhauls the plugin configuration and navigation architecture by refactoring the IUIConfig type, removing per-module metadata arrays, and introducing a unified settingsNavigation/subGroup API; it simplifies routing and widget hooks to operate at the plugin level, standardizes path enums, updates module-federation exposes, and adds new settings navigation/layout components for frontline and operation plugins. Class diagram for updated IUIConfig structureclassDiagram
class IUIConfig {
+string name
+string path
+bool hasFloatingWidget
+func settingsNavigation()
+NavigationGroup navigationGroup
+RelationWidget[] relationWidgets
}
class NavigationGroup {
+string name
+React.ElementType icon
+func content()
+func subGroup()
}
class RelationWidget {
+string name
+React.ElementType icon
}
IUIConfig "1" o-- "1" NavigationGroup
IUIConfig "0..*" o-- "*" RelationWidget
Class diagram for updated FrontlinePaths and OperationPaths enumsclassDiagram
class FrontlinePaths {
+Frontline
+InboxAll
+Inbox
+Integrations
+IntegrationDetail
+IntegrationConfig
+ErxesMessengerPreview
+Channels
}
class OperationPaths {
+Operation
+OperationAll
+TeamList
+TeamDetail
+TeamMembers
+TeamStatus
}
FrontlinePaths <|-- OperationPaths
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
WalkthroughRefactors plugin architecture to be plugin-centric (removing per-module configs), updates UIConfig type and navigation structures, adjusts routing to relative paths, adds settings navigation/rendering for plugins (frontline, operation), changes module federation exposes, simplifies several core hooks, and removes legacy inbox/settings files while adding new settings modules and layouts. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant App as Core App Router
participant Plugins as Plugins Registry
participant UI as RenderPluginsComponent
participant Settings as SettingsSidebar
User->>App: Navigate to app
App->>Plugins: Fetch plugins (CONFIGs)
Plugins-->>App: { name, path, settingsNavigation, navigationGroup.subGroup, hasFloatingWidget }
App->>App: Build routes per-plugin (not per-module)
App->>UI: Mount remote module via {pluginName, moduleName, remoteModuleName}
UI-->>App: Render plugin UI
User->>Settings: Open Settings
Settings->>Plugins: Get settingsNavigation providers
Plugins-->>Settings: settingsNavigation components
Settings-->>User: Render plugin settings menus and routes
sequenceDiagram
autonumber
participant Host as Module Federation Host
participant Frontline as frontline_ui
participant Operation as operation_ui
Host->>Frontline: Load exposes ./frontline, ./frontlineSettings
Host->>Operation: Load exposes ./operationSettings
Note over Frontline,Operation: Exposes renamed/added to align with plugin-level settings routes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60–90 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- There are several console.log debug statements left in RenderPluginsComponent, getPluginsSettingsRoutes, and pages like IntegrationSettingsPage—please remove them before merging.
- The stubbed out return of an empty array in useFavorites() effectively disables the favorites feature—either restore the original mapping logic or add a clear TODO explaining why it’s temporarily removed.
- The create-plugin script still emits a modules array in the generated CONFIG, but IUIConfig no longer defines modules—please update the template to align with the new config schema.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- There are several console.log debug statements left in RenderPluginsComponent, getPluginsSettingsRoutes, and pages like IntegrationSettingsPage—please remove them before merging.
- The stubbed out return of an empty array in useFavorites() effectively disables the favorites feature—either restore the original mapping logic or add a clear TODO explaining why it’s temporarily removed.
- The create-plugin script still emits a modules array in the generated CONFIG, but IUIConfig no longer defines modules—please update the template to align with the new config schema.
## Individual Comments
### Comment 1
<location> `frontend/core-ui/src/modules/navigation/hooks/useFavorites.tsx:30-31` </location>
<code_context>
}
export function useFavorites(): FavoriteModule[] {
- const modules = usePluginsModules();
const currentUser = useAtomValue(currentUserState);
</code_context>
<issue_to_address>
**issue (bug_risk):** useFavorites now always returns an empty array.
This change will hide all favorite modules. If this is intentional or temporary, please clarify with a TODO or plan to restore the original logic.
</issue_to_address>
### Comment 2
<location> `frontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsx:13` </location>
<code_context>
const plugins = Object.values(pluginsMetaData);
- return plugins.flatMap((plugin) =>
- plugin.modules
- .filter((module) => module.hasFloatingWidget)
- .map((module) => ({
- ...module,
- pluginName: plugin.name,
- })),
- );
+ return plugins.filter((plugin) => plugin.hasFloatingWidget);
};
</code_context>
<issue_to_address>
**issue (bug_risk):** Floating widgets now filter plugins instead of modules.
This change may prevent floating widgets defined in modules from being included, potentially breaking existing functionality if widgets are meant to be module-specific.
</issue_to_address>
### Comment 3
<location> `frontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsx:39` </location>
<code_context>
}
if (activePlugin && navigationGroups[activePlugin]) {
+ const subGroups = navigationGroups[activePlugin].subGroups;
return (
<>
</code_context>
<issue_to_address>
**issue (bug_risk):** subGroups is referenced but navigationGroup now uses subGroup.
This mismatch between 'subGroups' and 'subGroup' may cause runtime errors. Please ensure consistency by either normalizing to an array or updating all references to match the new property name.
</issue_to_address>
### Comment 4
<location> `frontend/core-ui/src/modules/navigation/hooks/usePluginsModules.tsx:64-67` </location>
<code_context>
? [...existingGroup.contents, newContent]
: existingGroup.contents;
- const newSubGroup = plugin.navigationGroup?.subGroups;
+ const newSubGroup = plugin.navigationGroup?.subGroup;
const updatedSubGroups = newSubGroup
? [...existingGroup.subGroups, newSubGroup]
</code_context>
<issue_to_address>
**suggestion:** subGroups replaced with subGroup in navigationGroup.
Ensure subGroup is consistently treated as an array to avoid issues when handling multiple subgroups.
```suggestion
const newSubGroup = plugin.navigationGroup?.subGroup
? Array.isArray(plugin.navigationGroup.subGroup)
? plugin.navigationGroup.subGroup
: [plugin.navigationGroup.subGroup]
: [];
const updatedSubGroups = newSubGroup.length > 0
? [...existingGroup.subGroups, ...newSubGroup]
: existingGroup.subGroups;
```
</issue_to_address>
### Comment 5
<location> `frontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsx:39` </location>
<code_context>
const subGroups = navigationGroups[activePlugin].subGroups;
</code_context>
<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/TypeScript/Default-Rules/use-object-destructuring))
```suggestion
const {subGroups} = navigationGroups[activePlugin];
```
<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.
From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
|
||
| const favorites = data?.getFavoritesByCurrentUser ?? []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): useFavorites now always returns an empty array.
This change will hide all favorite modules. If this is intentional or temporary, please clarify with a TODO or plan to restore the original logic.
|
|
||
| const plugins = Object.values(pluginsMetaData); | ||
|
|
||
| return plugins.flatMap((plugin) => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Floating widgets now filter plugins instead of modules.
This change may prevent floating widgets defined in modules from being included, potentially breaking existing functionality if widgets are meant to be module-specific.
| const newSubGroup = plugin.navigationGroup?.subGroups; | ||
| const newSubGroup = plugin.navigationGroup?.subGroup; | ||
| const updatedSubGroups = newSubGroup | ||
| ? [...existingGroup.subGroups, newSubGroup] | ||
| : existingGroup.subGroups; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: subGroups replaced with subGroup in navigationGroup.
Ensure subGroup is consistently treated as an array to avoid issues when handling multiple subgroups.
| const newSubGroup = plugin.navigationGroup?.subGroups; | |
| const newSubGroup = plugin.navigationGroup?.subGroup; | |
| const updatedSubGroups = newSubGroup | |
| ? [...existingGroup.subGroups, newSubGroup] | |
| : existingGroup.subGroups; | |
| const newSubGroup = plugin.navigationGroup?.subGroup | |
| ? Array.isArray(plugin.navigationGroup.subGroup) | |
| ? plugin.navigationGroup.subGroup | |
| : [plugin.navigationGroup.subGroup] | |
| : []; | |
| const updatedSubGroups = newSubGroup.length > 0 | |
| ? [...existingGroup.subGroups, ...newSubGroup] | |
| : existingGroup.subGroups; |
| } | ||
|
|
||
| if (activePlugin && navigationGroups[activePlugin]) { | ||
| const subGroups = navigationGroups[activePlugin].subGroups; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (code-quality): Prefer object destructuring when accessing and using properties. (use-object-destructuring)
| const subGroups = navigationGroups[activePlugin].subGroups; | |
| const {subGroups} = navigationGroups[activePlugin]; |
Explanation
Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.From the Airbnb Javascript Style Guide
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Changes requested ❌
Reviewed everything up to 9130e7e in 2 minutes and 6 seconds. Click for details.
- Reviewed
1085lines of code in34files - Skipped
1files when reviewing. - Skipped posting
12draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. .cursor/mcp.json:1
- Draft comment:
Ensure removal of default MCP server config is intentional. - Reason this comment was not posted:
Comment looked like it was already resolved.
2. frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx:11
- Draft comment:
Mapping changed from iterating over plugin.modules to plugins directly. Confirm that plugin objects now represent modules as expected. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% The comment is asking for confirmation about the data structure change, which violates the rule "Do NOT ask the PR author to confirm their intention". The comment is not pointing out a clear bug or suggesting a specific improvement - it's just asking for verification. If there was a real issue with the data structure, it would be caught by TypeScript or at runtime. Maybe this is actually pointing out a potential bug in the data structure that could cause runtime issues? Maybe the verification is important for preventing bugs? Even if there could be issues, the comment doesn't point out a specific problem or suggest a fix - it just asks for confirmation. If there are type mismatches, they would be caught by TypeScript. The comment should be deleted as it violates the rule about asking for confirmations and doesn't provide actionable feedback.
3. frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx:30
- Draft comment:
Check that routing in getPluginsSettingsRoutes correctly reflects the updated plugin structure. Validate plugin properties (e.g. path, name) are still available. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to validate and check the routing and properties, which falls under asking the author to double-check things. This violates the rules.
4. frontend/core-ui/src/modules/navigation/hooks/useFavorites.tsx:31
- Draft comment:
useFavorites currently returns an empty array. Confirm if favorite processing has been intentionally disabled or will be re-implemented. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% The comment is asking for confirmation about intention, which explicitly violates our rules. The change is clear - complex processing was removed. If this was a mistake, it would be caught in testing. If it was intentional, asking for confirmation adds no value. Maybe this is a significant change that deserves discussion? The removal of all processing logic could break functionality. While the change is significant, asking for confirmation violates our rules. If there's a real issue, it should be stated directly. The author clearly made this change deliberately. Delete the comment because it violates our rule about not asking for confirmations or explanations of intent.
5. frontend/core-ui/src/modules/navigation/hooks/usePlugins.tsx:64
- Draft comment:
Property renamed from 'subGroups' to 'subGroup' in navigationGroups. Ensure this change is consistent across all consumers. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =30%<= threshold50%The comment is asking the author to ensure consistency across all consumers, which is a form of asking them to double-check their work. This violates the rule against asking the author to confirm or ensure things. However, the comment does point out a specific change in property name, which could be useful if it were rephrased to focus on the change itself rather than asking for confirmation.
6. frontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsx:10
- Draft comment:
Updated pluginName now uses 'module.name' instead of 'module.pluginName'. Confirm this aligns with the new plugin data structure. - Reason this comment was not posted:
Comment looked like it was already resolved.
7. frontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsx:13
- Draft comment:
Filtering plugins using 'plugin.hasFloatingWidget' replaces the former module-level check. Ensure this aligns with the updated plugin schema. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the author to ensure alignment with the updated plugin schema, which is a form of asking for confirmation or verification. This violates the rule against asking the PR author to confirm or ensure things. The comment does not provide a specific suggestion or point out a clear issue.
8. frontend/plugins/components/RenderPluginsComponent.tsx:25
- Draft comment:
Debug console.log present; remove it if not needed in production. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
9. frontend/libs/erxes-ui/src/types/UIConfig.ts:1
- Draft comment:
IUIConfig no longer includes a 'modules' array. Verify that all consumers are updated to use the new configuration shape. - Reason this comment was not posted:
Comment did not seem useful. Confidence is useful =0%<= threshold50%The comment is asking the PR author to verify that all consumers are updated to use the new configuration shape. This falls under the rule of not asking the author to ensure the behavior is intended or to double-check things. Therefore, this comment should be removed.
10. frontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx:35
- Draft comment:
Route for TeamDetail uses an absolute path ('/details/:id'); consider using a relative path to ensure proper nested routing. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
11. frontend/plugins/operation_ui/src/types/operationPaths.ts:5
- Draft comment:
TeamDetail path starts with a leading slash; remove it for consistency with other relative paths in the enum. - Reason this comment was not posted:
Comment was on unchanged code.
12. scripts/create-plugin.js:152
- Draft comment:
Ensure the generated plugin scaffold aligns with the refactored IUIConfig structure and that the expected navigation component (<${kebabCaseModuleName}Navigation />) exists. - Reason this comment was not posted:
Comment was not on a location in the diff, so it can't be submitted as a review comment.
Workflow ID: wflow_q6JyjgSFmnRgbS4V
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
| ))} | ||
| </SettingsNavigationGroup> | ||
| ), | ||
| {pluginSettingsNavigations.map( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable 'pluginSettingsNavigations' is used but not defined or imported. Verify its source to avoid runtime errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additional Comments (3)
-
frontend/plugins/frontline_ui/src/modules/FrontlineMain.tsx, line 26 (link)style: Component name
IntegrationsMaindoesn't match the file nameFrontlineMain.tsx. Should beFrontlineMainfor consistency. -
frontend/plugins/frontline_ui/src/modules/FrontlineMain.tsx, line 39 (link)style: Export name should match component name - consider
export default FrontlineMain; -
frontend/core-ui/src/modules/settings/components/SettingsSidebar.tsx, line 24-45 (link)style: The
pluginsWithSettingsModulesvariable is computed but no longer used after the refactor.
35 files reviewed, 22 comments
| import { ScrollArea } from 'erxes-ui'; | ||
|
|
||
| export const IntegrationSettingsPage = () => { | ||
| console.log('IntegrationSettingsPage'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Remove console.log statement - the coding standards explicitly state to avoid console logs
Context Used: Context from dashboard - .cursorrules (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsx
Line: 5:5
Comment:
**style:** Remove console.log statement - the coding standards explicitly state to avoid console logs
**Context Used:** Context from `dashboard` - .cursorrules ([source](https://app.greptile.com/review/custom-context?memory=bf691a04-8aaa-40fe-8db5-b17d5fe3755f))
How can I resolve this? If you propose a fix, please make it concise.| const [isLoading, setIsLoading] = useState(true); | ||
| const [hasError, setHasError] = useState<{ message: string } | null>(null); | ||
|
|
||
| console.log(pluginName, remoteModuleName, moduleName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Console log should be removed per project guidelines that explicitly state 'Avoid console logs'
Context Used: Context from dashboard - .cursorrules (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsx
Line: 25:25
Comment:
**style:** Console log should be removed per project guidelines that explicitly state 'Avoid console logs'
**Context Used:** Context from `dashboard` - .cursorrules ([source](https://app.greptile.com/review/custom-context?memory=bf691a04-8aaa-40fe-8db5-b17d5fe3755f))
How can I resolve this? If you propose a fix, please make it concise.| const settingsPathPrefix = | ||
| '/settings' + (pathPrefix?.startsWith('/') ? pathPrefix : `/${pathPrefix}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: The path handling logic duplicates the same pattern used in NavigationMenuLinkItem. Consider extracting this into a utility function to avoid repetition.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx
Line: 67:68
Comment:
**style:** The path handling logic duplicates the same pattern used in NavigationMenuLinkItem. Consider extracting this into a utility function to avoid repetition.
How can I resolve this? If you propose a fix, please make it concise.| ref={ref} | ||
| /> | ||
| ); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Missing displayName assignment for SettingsNavigationMenuLinkItem component, which is inconsistent with the pattern used for other components in this file.
| }); | |
| }); | |
| SettingsNavigationMenuLinkItem.displayName = 'SettingsNavigationMenuLinkItem'; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx
Line: 76:76
Comment:
**style:** Missing displayName assignment for SettingsNavigationMenuLinkItem component, which is inconsistent with the pattern used for other components in this file.
```suggestion
});
SettingsNavigationMenuLinkItem.displayName = 'SettingsNavigationMenuLinkItem';
```
How can I resolve this? If you propose a fix, please make it concise.| export enum FrontlinePaths { | ||
| Inbox = '/inbox', | ||
| Integrations = '/integrations', | ||
| IntegrationDetail = '/integrations/:integrationType', | ||
| IntegrationConfig = '/integrations-config', | ||
| ErxesMessengerPreview = '/integrations/erxes-messenger-preview', | ||
| Channels = '/channels', | ||
| Frontline = 'frontline', | ||
| InboxAll = 'inbox/*', | ||
| Inbox = 'inbox', | ||
| Integrations = 'integrations', | ||
| IntegrationDetail = 'integrations/:integrationType', | ||
| IntegrationConfig = 'integration-configs', | ||
| ErxesMessengerPreview = 'integrations/erxes-messenger-preview', | ||
| Channels = 'channels', | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Violates coding standards - enums should be avoided in favor of maps according to the .cursorrules
| export enum FrontlinePaths { | |
| Inbox = '/inbox', | |
| Integrations = '/integrations', | |
| IntegrationDetail = '/integrations/:integrationType', | |
| IntegrationConfig = '/integrations-config', | |
| ErxesMessengerPreview = '/integrations/erxes-messenger-preview', | |
| Channels = '/channels', | |
| Frontline = 'frontline', | |
| InboxAll = 'inbox/*', | |
| Inbox = 'inbox', | |
| Integrations = 'integrations', | |
| IntegrationDetail = 'integrations/:integrationType', | |
| IntegrationConfig = 'integration-configs', | |
| ErxesMessengerPreview = 'integrations/erxes-messenger-preview', | |
| Channels = 'channels', | |
| } | |
| export const FrontlinePaths = { | |
| Frontline: 'frontline', | |
| InboxAll: 'inbox/*', | |
| Inbox: 'inbox', | |
| Integrations: 'integrations', | |
| IntegrationDetail: 'integrations/:integrationType', | |
| IntegrationConfig: 'integration-configs', | |
| ErxesMessengerPreview: 'integrations/erxes-messenger-preview', | |
| Channels: 'channels', | |
| } as const; |
Context Used: Context from dashboard - .cursorrules (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/plugins/frontline_ui/src/modules/types/FrontlinePaths.ts
Line: 1:10
Comment:
**style:** Violates coding standards - enums should be avoided in favor of maps according to the `.cursorrules`
```suggestion
export const FrontlinePaths = {
Frontline: 'frontline',
InboxAll: 'inbox/*',
Inbox: 'inbox',
Integrations: 'integrations',
IntegrationDetail: 'integrations/:integrationType',
IntegrationConfig: 'integration-configs',
ErxesMessengerPreview: 'integrations/erxes-messenger-preview',
Channels: 'channels',
} as const;
```
**Context Used:** Context from `dashboard` - .cursorrules ([source](https://app.greptile.com/review/custom-context?memory=bf691a04-8aaa-40fe-8db5-b17d5fe3755f))
How can I resolve this? If you propose a fix, please make it concise.| <Suspense fallback={<div />}> | ||
| <${kebabCaseModuleName}Navigation /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
syntax: Missing React import - Suspense component requires 'import { Suspense } from 'react'
| <Suspense fallback={<div />}> | |
| <${kebabCaseModuleName}Navigation /> | |
| import { Suspense } from 'react'; | |
| import { IconSandbox } from '@tabler/icons-react'; | |
| import { IUIConfig } from 'erxes-ui/types'; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/create-plugin.js
Line: 164:165
Comment:
**syntax:** Missing React import - Suspense component requires 'import { Suspense } from 'react'
```suggestion
import { Suspense } from 'react';
import { IconSandbox } from '@tabler/icons-react';
import { IUIConfig } from 'erxes-ui/types';
```
How can I resolve this? If you propose a fix, please make it concise.| icon: IconSandbox, | ||
| content: () => ( | ||
| <Suspense fallback={<div />}> | ||
| <${kebabCaseModuleName}Navigation /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Component ${kebabCaseModuleName}Navigation is referenced but never created by this script
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/create-plugin.js
Line: 165:165
Comment:
**logic:** Component ${kebabCaseModuleName}Navigation is referenced but never created by this script
How can I resolve this? If you propose a fix, please make it concise.| {pluginSettingsNavigations.map( | ||
| (SettingsNavigation, index) => | ||
| SettingsNavigation && <SettingsNavigation key={index} />, | ||
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: pluginSettingsNavigations is not defined. You need to either import it or create it from plugin configs with settingsNavigation functions.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/core-ui/src/modules/settings/components/SettingsSidebar.tsx
Line: 83:86
Comment:
**logic:** `pluginSettingsNavigations` is not defined. You need to either import it or create it from plugin configs with `settingsNavigation` functions.
How can I resolve this? If you propose a fix, please make it concise.|
|
||
| return acc; | ||
| }, []); | ||
| return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Favorites functionality has been completely removed - the hook now returns an empty array instead of processing favorites data. This will break any UI components that rely on displaying user favorites.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/core-ui/src/modules/navigation/hooks/useFavorites.tsx
Line: 31:31
Comment:
**logic:** Favorites functionality has been completely removed - the hook now returns an empty array instead of processing favorites data. This will break any UI components that rely on displaying user favorites.
How can I resolve this? If you propose a fix, please make it concise.| './config': './src/config.tsx', | ||
| './operation': './src/modules/main/Main.tsx', | ||
| './teamSettings': './src/modules/team/Settings.tsx', | ||
| './operationSettings': './src/modules/OperationSettings.tsx', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Breaking change: consumers expecting './teamSettings' export will fail. Ensure all references are updated across the codebase.
Prompt To Fix With AI
This is a comment left during a code review.
Path: frontend/plugins/operation_ui/module-federation.config.ts
Line: 20:20
Comment:
**logic:** Breaking change: consumers expecting './teamSettings' export will fail. Ensure all references are updated across the codebase.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
frontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsx (1)
9-15: Remove redundant conditional check.The condition at Line 15 is redundant because of the early return at Lines 9-11. If execution reaches Line 15,
location.pathname.startsWith('/frontline/inbox')is guaranteed to be true.Apply this diff to simplify the code:
- {location.pathname.startsWith('/frontline/inbox') && <InboxActions />} + <InboxActions />frontend/core-ui/src/modules/navigation/hooks/useFavorites.tsx (1)
22-31: Return fetched favorites in useFavorites.In useFavorites.tsx (line 31), the hook currently does
return [], ignoring thefavoritesvariable. Replace that withreturn favoritesso the SidebarNavigationFavorites component receives actual data.scripts/create-plugin.js (1)
152-180: Missing imports in generated config.ts.The generated config template uses
Suspense(line 164) and references a navigation component, but the necessary imports are missing.Add the required imports to the config template:
const configContent = `import { IconSandbox } from '@tabler/icons-react'; - +import { Suspense } from 'react'; import { IUIConfig } from 'erxes-ui/types'; +// import { ${moduleName}Navigation } from './modules/${kebabCaseModuleName}/Navigation'; export const CONFIG: IUIConfig = {frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx (1)
30-44: Restore a guard before creating settings routes.We now create a settings route for every plugin, but only plugins that expose a
${plugin.name}Settingsremote (and supplysettingsNavigation) can satisfy this load. For others the runtime call toloadRemotewill fail. Please filter the list (e.g.,plugin.settingsNavigation) before mapping so we only register routes with actual settings modules.
🧹 Nitpick comments (2)
frontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsx (1)
13-13: Consider a more informative loading fallback.The empty
<div />fallback provides no feedback during loading. Consider using a loading indicator or skeleton component for better user experience.Apply this diff to add a basic loading indicator:
- <Suspense fallback={<div />}> + <Suspense fallback={<div>Loading...</div>}>Or import and use a proper loading component from your UI library.
frontend/plugins/operation_ui/src/modules/OperationSettings.tsx (1)
13-13: Consider a more informative loading fallback.The empty
<div />fallback provides no user feedback during loading. Consider using a loading indicator or skeleton component.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (34)
.cursor/mcp.json(1 hunks)frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx(2 hunks)frontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsx(3 hunks)frontend/core-ui/src/modules/navigation/hooks/useFavorites.tsx(1 hunks)frontend/core-ui/src/modules/navigation/hooks/usePlugins.tsx(1 hunks)frontend/core-ui/src/modules/settings/components/SettingsSidebar.tsx(1 hunks)frontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsx(1 hunks)frontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsx(1 hunks)frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsx(1 hunks)frontend/core-ui/src/plugins/constants/core-plugins.constants.ts(0 hunks)frontend/core-ui/tsconfig.json(1 hunks)frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx(2 hunks)frontend/libs/erxes-ui/src/types/UIConfig.ts(1 hunks)frontend/plugins/frontline_ui/module-federation.config.ts(1 hunks)frontend/plugins/frontline_ui/src/config.tsx(3 hunks)frontend/plugins/frontline_ui/src/modules/FrontlineActions.tsx(0 hunks)frontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsx(1 hunks)frontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsx(1 hunks)frontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsx(2 hunks)frontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsx(1 hunks)frontend/plugins/frontline_ui/src/modules/inbox/Main.tsx(0 hunks)frontend/plugins/frontline_ui/src/modules/inbox/Settings.tsx(0 hunks)frontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsx(1 hunks)frontend/plugins/frontline_ui/src/modules/settings/components/Sidebar.tsx(0 hunks)frontend/plugins/frontline_ui/src/modules/settings/constants/settingsRoutes.ts(0 hunks)frontend/plugins/frontline_ui/src/modules/types/FrontlinePaths.ts(1 hunks)frontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsx(1 hunks)frontend/plugins/operation_ui/module-federation.config.ts(1 hunks)frontend/plugins/operation_ui/src/config.tsx(2 hunks)frontend/plugins/operation_ui/src/modules/OperationSettings.tsx(1 hunks)frontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsx(1 hunks)frontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx(1 hunks)frontend/plugins/operation_ui/src/types/operationPaths.ts(1 hunks)scripts/create-plugin.js(1 hunks)
💤 Files with no reviewable changes (6)
- frontend/plugins/frontline_ui/src/modules/settings/constants/settingsRoutes.ts
- frontend/plugins/frontline_ui/src/modules/FrontlineActions.tsx
- frontend/plugins/frontline_ui/src/modules/inbox/Main.tsx
- frontend/plugins/frontline_ui/src/modules/settings/components/Sidebar.tsx
- frontend/plugins/frontline_ui/src/modules/inbox/Settings.tsx
- frontend/core-ui/src/plugins/constants/core-plugins.constants.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Use functional and declarative programming patterns; avoid classes.
Use TypeScript for all code; prefer interfaces over types.
Avoid enums; use maps instead.
Files:
frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsxfrontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsxfrontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsxfrontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsxfrontend/plugins/operation_ui/module-federation.config.tsfrontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsxfrontend/plugins/operation_ui/src/modules/OperationSettings.tsxfrontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsxfrontend/plugins/frontline_ui/module-federation.config.tsfrontend/plugins/frontline_ui/src/modules/types/FrontlinePaths.tsfrontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsxfrontend/core-ui/src/modules/settings/components/SettingsSidebar.tsxfrontend/plugins/operation_ui/src/types/operationPaths.tsfrontend/core-ui/src/modules/navigation/hooks/useFavorites.tsxfrontend/core-ui/src/modules/navigation/hooks/usePlugins.tsxfrontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsxfrontend/plugins/operation_ui/src/config.tsxfrontend/plugins/frontline_ui/src/config.tsxfrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsxfrontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsxfrontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsxfrontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsxfrontend/libs/erxes-ui/src/types/UIConfig.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Avoid console logs.
Always use absolute paths when importing.
Use the "function" keyword for pure functions.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
**/*.{ts,tsx,js,jsx}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use the "function" keyword for pure functions.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
Use absolute path when import.
Files:
frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsxfrontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsxfrontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsxfrontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsxfrontend/plugins/operation_ui/module-federation.config.tsfrontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsxfrontend/plugins/operation_ui/src/modules/OperationSettings.tsxfrontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsxfrontend/plugins/frontline_ui/module-federation.config.tsfrontend/plugins/frontline_ui/src/modules/types/FrontlinePaths.tsfrontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsxscripts/create-plugin.jsfrontend/core-ui/src/modules/settings/components/SettingsSidebar.tsxfrontend/plugins/operation_ui/src/types/operationPaths.tsfrontend/core-ui/src/modules/navigation/hooks/useFavorites.tsxfrontend/core-ui/src/modules/navigation/hooks/usePlugins.tsxfrontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsxfrontend/plugins/operation_ui/src/config.tsxfrontend/plugins/frontline_ui/src/config.tsxfrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsxfrontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsxfrontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsxfrontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsxfrontend/libs/erxes-ui/src/types/UIConfig.ts
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Favor named exports for components.
Use declarative JSX.
Use Shadcn UI, Radix, and Tailwind for components and styling.
Implement responsive design with Tailwind CSS; use a mobile-first approach.
**/*.{tsx,jsx}: Structure files: exported component, subcomponents, helpers, static content, types.
Favor named exports for components.
Use declarative JSX.
Use Shadcn UI, Radix, and Tailwind for components and styling.
Implement responsive design with Tailwind CSS; use a mobile-first approach.
Files:
frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsxfrontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsxfrontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsxfrontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsxfrontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsxfrontend/plugins/operation_ui/src/modules/OperationSettings.tsxfrontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsxfrontend/core-ui/src/modules/settings/components/SettingsSidebar.tsxfrontend/core-ui/src/modules/navigation/hooks/useFavorites.tsxfrontend/core-ui/src/modules/navigation/hooks/usePlugins.tsxfrontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsxfrontend/plugins/operation_ui/src/config.tsxfrontend/plugins/frontline_ui/src/config.tsxfrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsxfrontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsxfrontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsxfrontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use functional components with TypeScript interfaces.
Minimize 'useEffect', and 'setState'.
Wrap client components in Suspense with fallback.
Use dynamic loading for non-critical components.
Limit 'use client': Favor server components and Next.js SSR. Use only for Web API access in small components. Avoid for data fetching or state management.
Files:
frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsxfrontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsxfrontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsxfrontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsxfrontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsxfrontend/plugins/operation_ui/src/modules/OperationSettings.tsxfrontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsxfrontend/core-ui/src/modules/settings/components/SettingsSidebar.tsxfrontend/core-ui/src/modules/navigation/hooks/useFavorites.tsxfrontend/core-ui/src/modules/navigation/hooks/usePlugins.tsxfrontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsxfrontend/plugins/operation_ui/src/config.tsxfrontend/plugins/frontline_ui/src/config.tsxfrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsxfrontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsxfrontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsxfrontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsx
**/*.{webp,tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
Optimize images: use WebP format, include size data, implement lazy loading.
Files:
frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsxfrontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsxfrontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsxfrontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsxfrontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsxfrontend/plugins/operation_ui/src/modules/OperationSettings.tsxfrontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsxfrontend/core-ui/src/modules/settings/components/SettingsSidebar.tsxfrontend/core-ui/src/modules/navigation/hooks/useFavorites.tsxfrontend/core-ui/src/modules/navigation/hooks/usePlugins.tsxfrontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsxfrontend/plugins/operation_ui/src/config.tsxfrontend/plugins/frontline_ui/src/config.tsxfrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsxfrontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsxfrontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsxfrontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsxfrontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsx
🧬 Code graph analysis (13)
frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx (1)
frontend/libs/erxes-ui/src/components/sidebar.tsx (1)
Sidebar(744-768)
frontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsx (2)
frontend/libs/erxes-ui/src/components/sidebar.tsx (1)
Sidebar(744-768)frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx (1)
SettingsNavigationMenuLinkItem(63-76)
frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx (2)
scripts/start-api-dev.js (1)
plugins(7-7)frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsx (1)
RenderPluginsComponent(9-93)
frontend/plugins/operation_ui/src/modules/OperationSettings.tsx (1)
frontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx (1)
TeamSettings(14-50)
frontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsx (2)
frontend/libs/erxes-ui/src/components/sidebar.tsx (1)
Sidebar(744-768)frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx (1)
SettingsNavigationMenuLinkItem(63-76)
scripts/create-plugin.js (1)
scripts/create-backend-plugin.js (1)
kebabCaseName(10-13)
frontend/plugins/operation_ui/src/config.tsx (2)
frontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsx (1)
OperationSettingsNavigation(4-19)frontend/libs/erxes-ui/src/types/UIConfig.ts (1)
IUIConfig(1-16)
frontend/plugins/frontline_ui/src/config.tsx (3)
frontend/plugins/frontline_ui/src/modules/FrontlineSettingsNavigation.tsx (1)
FrontlineSettingsNavigation(4-29)frontend/plugins/operation_ui/src/config.tsx (1)
CONFIG(28-60)frontend/libs/erxes-ui/src/types/UIConfig.ts (1)
IUIConfig(1-16)
frontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx (1)
frontend/plugins/operation_ui/src/modules/OperationSettings.tsx (1)
TeamSettings(5-9)
frontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsx (2)
frontend/libs/ui-modules/src/modules/header/components/PageHeader.tsx (3)
PageHeader(186-190)PageHeaderStart(34-49)PageHeaderEnd(53-68)frontend/plugins/frontline_ui/src/modules/settings/components/InboxSettingsTopbar.tsx (1)
InboxSettingsTopbar(4-10)
frontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsx (1)
frontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsx (1)
InboxSettings(37-77)
frontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsx (3)
frontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsx (1)
IntegrationSettingsPage(4-19)frontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsx (1)
InboxSettingsLayout(6-27)frontend/plugins/frontline_ui/src/modules/inbox/components/InboxPageChangeEffect.tsx (1)
InboxPageChangeEffect(6-24)
frontend/plugins/frontline_ui/src/modules/FrontlineSubGroups.tsx (1)
frontend/plugins/frontline_ui/src/modules/inbox/components/InboxActions.tsx (1)
InboxActions(7-44)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Sourcery review
- GitHub Check: core-ui
- GitHub Check: frontline_ui-ci
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (13)
frontend/core-ui/tsconfig.json (1)
14-16: Path alias reorder looks good.The aliases still point to the same directories, so this reorder is a no-op behavior-wise and keeps config consistent with the rest of the refactor.
.cursor/mcp.json (1)
2-2: Confirm no downstream consumers require the Nx MCP server entry.We used to expose the
nx-mcpSSE endpoint here; wiping the map means the Cursor MCP client will no longer auto-discover that server. Please double-check any local tooling or scripts that relied on it before merging.frontend/core-ui/src/modules/navigation/hooks/usePlugins.tsx (1)
64-67: LGTM!The transition from
subGroups(array) tosubGroup(single item) is correctly implemented and aligns with the broader navigation refactor described in the PR.frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx (1)
31-33: LGTM!The path normalization ensures consistent active state checking by guaranteeing a leading slash.
frontend/core-ui/src/modules/widgets/components/FloatingWidgets.tsx (1)
10-10: No action needed. The modules returned byuseFloatingWidgetsModules()are typed with aname: stringproperty (e.g. in ui-modules and core-ui types), so replacingmodule.pluginNamewithmodule.nameis correct.frontend/core-ui/src/modules/navigation/components/NavigationPlugins.tsx (1)
39-39: LGTM!The extraction of
subGroupsinto a local constant improves readability and avoids repeated object access in the JSX. This is a clean refactor.Also applies to: 54-54
frontend/plugins/frontline_ui/src/modules/FrontlineSettings.tsx (1)
14-16: Verify the nested Routes pattern is intentional.
InboxSettings(fromfrontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsx) already contains its own<Routes>component with multiple route definitions. This creates a nested Routes structure whereFrontlineSettingsrenders Routes containing a Route that renders another Routes component.While React Router supports nested Routes, this pattern may be unnecessary complexity. Consider whether:
- The outer Routes wrapper here is needed, or
- The routes could be flattened into a single Routes component
If the nesting is intentional for path isolation or modularity, this is acceptable.
frontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx (1)
14-14: LGTM!Converting
TeamSettingsto a named export is the correct approach for the lazy loading pattern used inOperationSettings.tsx. The import path update forOperationPathsaligns with the type reorganization in the PR.frontend/plugins/operation_ui/src/modules/OperationSettings.tsx (2)
5-9: LGTM!The lazy loading pattern correctly imports the named export
TeamSettingsfrom the updated module structure. This aligns with the changes infrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx.
14-16: Verify the nested Routes pattern is intentional.
TeamSettings(fromfrontend/plugins/operation_ui/src/modules/team/TeamSettings.tsx) already contains its own<Routes>component with multiple route definitions. This creates nested Routes where the outer Routes renders a Route that renders another Routes component.While this pattern is supported by React Router, consider whether the routes could be flattened for simplicity. If the nesting is intentional for modularity or path isolation, this is acceptable.
frontend/plugins/operation_ui/src/modules/OperationSettingsNavigation.tsx (1)
10-14: LGTM!The navigation structure correctly uses
SettingsNavigationMenuLinkItemwhich will prepend/settingsto thepathPrefix. Based on the AI summary,OperationPaths.Operationis'operation'andOperationPaths.TeamListis'team', which will result in the correct path/settings/operation/team.frontend/core-ui/src/modules/widgets/hooks/useFloatingWidgetsModules.tsx (1)
13-13: No changes required The hook still returns objects withnameand all consumers derivepluginNamefrommodule.name, so there’s no breaking change.frontend/plugins/operation_ui/module-federation.config.ts (1)
20-20: Verify dynamic module imports and loader configurations
No occurrences of./teamSettingsor./operationSettingswere found in automated searches; manually confirm that anyexposedModule, dynamic import, or loader configuration referencing the old key has been updated to./operationSettings.
| console.log(plugins); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Remove the stray console.log.
Per our frontend guidelines we avoid console logging in shipped code. Please drop this log (or replace with structured telemetry if needed).
🤖 Prompt for AI Agents
In frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx around lines
30-31 there is a stray console.log(plugins); that violates frontend guidelines;
remove this console.log (or replace it with a structured telemetry/analytics
call if you need runtime insight) and ensure no other debug logs remain in this
hook.
| {pluginSettingsNavigations.map( | ||
| (SettingsNavigation, index) => | ||
| SettingsNavigation && <SettingsNavigation key={index} />, | ||
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define pluginSettingsNavigations before rendering.
pluginSettingsNavigations is referenced here but never defined, so the component now throws at render time. Please derive it from pluginsMetaData (e.g., memoize the non-null settingsNavigation functions) before mapping.
- return (
+ const pluginSettingsNavigations = useMemo(
+ () =>
+ Object.values(pluginsMetaData || {})
+ .map((plugin) => plugin.settingsNavigation)
+ .filter(
+ (navigation): navigation is NonNullable<typeof navigation> =>
+ Boolean(navigation),
+ ),
+ [pluginsMetaData],
+ );
+
+ return (
@@
- {pluginSettingsNavigations.map(
- (SettingsNavigation, index) =>
- SettingsNavigation && <SettingsNavigation key={index} />,
- )}
+ {pluginSettingsNavigations.map((SettingsNavigation, index) => (
+ <SettingsNavigation key={index} />
+ ))}📝 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.
| {pluginSettingsNavigations.map( | |
| (SettingsNavigation, index) => | |
| SettingsNavigation && <SettingsNavigation key={index} />, | |
| )} | |
| const pluginSettingsNavigations = useMemo( | |
| () => | |
| Object.values(pluginsMetaData || {}) | |
| .map((plugin) => plugin.settingsNavigation) | |
| .filter( | |
| (navigation): navigation is NonNullable<typeof navigation> => | |
| Boolean(navigation), | |
| ), | |
| [pluginsMetaData], | |
| ); | |
| return ( | |
| {pluginSettingsNavigations.map((SettingsNavigation, index) => ( | |
| <SettingsNavigation key={index} /> | |
| ))} | |
| ); |
🤖 Prompt for AI Agents
frontend/core-ui/src/modules/settings/components/SettingsSidebar.tsx around
lines 83 to 86: the code maps pluginSettingsNavigations which is not defined,
causing a render error; derive pluginSettingsNavigations from pluginsMetaData by
using React.useMemo to collect and return an array of non-null
settingsNavigation components/functions (e.g., pluginsMetaData.map(p =>
p.settingsNavigation).filter(Boolean)), memoized on pluginsMetaData, then use
that variable in the map call; ensure you type-check for undefined and keep the
existing key usage.
| console.log(pluginName, remoteModuleName, moduleName); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the console.log statement.
The coding guidelines specify to avoid console logs in production code. This debug statement should be removed.
As per coding guidelines
Apply this diff to remove the debug statement:
- console.log(pluginName, remoteModuleName, moduleName);
-📝 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.
| console.log(pluginName, remoteModuleName, moduleName); |
🤖 Prompt for AI Agents
In frontend/core-ui/src/plugins/components/RenderPluginsComponent.tsx around
lines 25-26, there is a leftover debug console.log(pluginName, remoteModuleName,
moduleName); which violates coding guidelines; remove that console.log statement
from the file and ensure no other console.* debug calls remain (run project
linter/grep for console.log to confirm) so production code contains no debug
logging.
| const settingsPathPrefix = | ||
| '/settings' + (pathPrefix?.startsWith('/') ? pathPrefix : `/${pathPrefix}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle undefined pathPrefix safely.
If pathPrefix is undefined, the concatenation will produce '/settings/undefined' as a string. Add a guard to handle the undefined case.
Apply this diff to fix the issue:
- const settingsPathPrefix =
- '/settings' + (pathPrefix?.startsWith('/') ? pathPrefix : `/${pathPrefix}`);
+ const settingsPathPrefix = pathPrefix
+ ? '/settings' + (pathPrefix.startsWith('/') ? pathPrefix : `/${pathPrefix}`)
+ : '/settings';📝 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 settingsPathPrefix = | |
| '/settings' + (pathPrefix?.startsWith('/') ? pathPrefix : `/${pathPrefix}`); | |
| const settingsPathPrefix = pathPrefix | |
| ? '/settings' + (pathPrefix.startsWith('/') ? pathPrefix : `/${pathPrefix}`) | |
| : '/settings'; |
🤖 Prompt for AI Agents
In
frontend/libs/erxes-ui/src/modules/navigation-menu/components/NavigationMenu.tsx
around lines 67 to 68, the current expression can yield "/settings/undefined"
when pathPrefix is undefined; update the logic to guard against undefined by
only appending the prefixed path when pathPrefix is truthy—if pathPrefix is
provided, append it ensuring a single leading slash (use
pathPrefix.startsWith('/') ? pathPrefix : `/${pathPrefix}`), otherwise just use
"/settings".
| <Button variant={'ghost'} className="font-semibold"> | ||
| <IconMailFilled className="w-4 h-4 text-accent-foreground" /> | ||
| Team inbox | ||
| </Button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify the purpose of the non-interactive button.
The button has no onClick handler or navigation link, making it appear non-interactive. If this is intended as a label or header, consider using a more appropriate semantic element (e.g., <h1> or <div>). If it should be interactive, add the appropriate action or navigation.
If this is meant to be a label, apply this diff:
- <Button variant={'ghost'} className="font-semibold">
- <IconMailFilled className="w-4 h-4 text-accent-foreground" />
- Team inbox
- </Button>
+ <div className="flex items-center gap-2 font-semibold px-3">
+ <IconMailFilled className="w-4 h-4 text-accent-foreground" />
+ <span>Team inbox</span>
+ </div>📝 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.
| <Button variant={'ghost'} className="font-semibold"> | |
| <IconMailFilled className="w-4 h-4 text-accent-foreground" /> | |
| Team inbox | |
| </Button> | |
| <div className="flex items-center gap-2 font-semibold px-3"> | |
| <IconMailFilled className="w-4 h-4 text-accent-foreground" /> | |
| <span>Team inbox</span> | |
| </div> |
🤖 Prompt for AI Agents
In
frontend/plugins/frontline_ui/src/modules/inbox/components/InboxSettingsLayout.tsx
around lines 15-18, the UI uses a Button component without any
onClick/navigation which makes it appear incorrectly interactive; if this is
intended as a non-interactive label/header, replace the Button with a semantic
element such as an h2 or div (preserving the IconMailFilled and classes for
styling), ensure appropriate heading level and aria attributes if needed, and
remove button-specific props; if it should be interactive instead, add the
correct onClick handler or wrap it with a Link/navigation component to perform
the intended action.
| path="/" | ||
| element={<Navigate to={FrontlinePaths.Integrations} replace />} | ||
| /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the default redirect route
Using path="/" inside this nested <Route> defines an absolute root path, so when users visit …/inbox, the redirect never runs and the outlet renders blank. Switch this to an index route so the redirect fires as intended.
- <Route
- path="/"
- element={<Navigate to={FrontlinePaths.Integrations} replace />}
- />
+ <Route
+ index
+ element={<Navigate to={FrontlinePaths.Integrations} replace />}
+ />🤖 Prompt for AI Agents
In frontend/plugins/frontline_ui/src/modules/inbox/InboxSettings.tsx around
lines 49 to 51, the nested Route currently uses path="/" which creates an
absolute root route and prevents the redirect when visiting .../inbox; change
this Route to be an index route (remove the path prop and use index) so it
matches the parent path and performs Navigate to FrontlinePaths.Integrations
with replace set, ensuring the redirect fires correctly inside the nested
Outlet.
| import { ScrollArea } from 'erxes-ui'; | ||
|
|
||
| export const IntegrationSettingsPage = () => { | ||
| console.log('IntegrationSettingsPage'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the console.log statement.
The coding guidelines specify to avoid console logs in production code.
As per coding guidelines
Apply this diff to remove the debug statement:
- console.log('IntegrationSettingsPage');📝 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.
| console.log('IntegrationSettingsPage'); |
🤖 Prompt for AI Agents
In frontend/plugins/frontline_ui/src/pages/IntegrationSettingsPage.tsx around
line 5, remove the debug console.log('IntegrationSettingsPage') statement;
delete that line so no console logging remains in production code and ensure the
file compiles (remove any leftover unused imports or references if necessary).
| Operation = 'operation', | ||
| OperationAll = 'operation/*', | ||
| TeamList = 'team', | ||
| TeamDetail = '/details/:id', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make TeamDetail relative like the other paths.
We switched Operation paths to relative strings, but TeamDetail still begins with /. In React Router this makes it absolute, so nested routes under team will no longer match. Drop the leading slash.
- TeamDetail = '/details/:id',
+ TeamDetail = 'details/:id',📝 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.
| TeamDetail = '/details/:id', | |
| TeamDetail = 'details/:id', |
🤖 Prompt for AI Agents
In frontend/plugins/operation_ui/src/types/operationPaths.ts around line 5,
TeamDetail is defined as an absolute path '/details/:id' which breaks nested
React Router matching; change it to a relative path 'details/:id' (remove the
leading slash) so it behaves consistently with the other relative paths and
nested routes under team will match correctly.
| navigationGroup: { | ||
| name: '${kebabCaseName}', | ||
| icon: IconSandbox, | ||
| content: () => ( | ||
| <Suspense fallback={<div />}> | ||
| <${kebabCaseModuleName}Navigation /> | ||
| </Suspense> | ||
| ), | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Referenced navigation component is not generated.
The navigationGroup.content references <${kebabCaseModuleName}Navigation /> (line 165), but this component is never created by the plugin generation script. When developers run this script, the generated plugin will have a broken reference.
Solution options:
- Generate the navigation component (recommended):
Add code to generate the navigation component file:
const navigationContent = `export const ${moduleName}Navigation = () => {
return (
<div>
<h1>${moduleName} Navigation</h1>
</div>
);
};
`;
fs.writeFileSync(
path.join(
frontendPluginDir,
'src',
'modules',
kebabCaseModuleName,
'Navigation.tsx',
),
navigationContent,
);-
Remove the navigationGroup from the template, or
-
Update config template to include import and null check:
export const CONFIG: IUIConfig = {
name: '${kebabCaseName}',
icon: IconSandbox,
- navigationGroup: {
- name: '${kebabCaseName}',
- icon: IconSandbox,
- content: () => (
- <Suspense fallback={<div />}>
- <${kebabCaseModuleName}Navigation />
- </Suspense>
- ),
- },
+ // TODO: Implement navigationGroup when needed🤖 Prompt for AI Agents
In scripts/create-plugin.js around lines 160–168 the template references a
navigation component (<${kebabCaseModuleName}Navigation />) that the generator
never creates, causing a broken import at runtime; fix by creating a
Navigation.tsx file under frontendPluginDir/src/modules/{kebabCaseModuleName}/
that exports the navigation component with the expected name (use the
moduleName-based PascalCase export such as `${moduleName}Navigation`) and ensure
the generated file path and export name match the JSX reference in the
navigationGroup template so the component is available when the plugin is
generated.
Summary by Sourcery
Refactor plugin configuration and core loading logic to streamline navigation and settings handling across Frontline and Operation plugins.
New Features:
Enhancements:
Chores:
Greptile Overview
Updated On: 2025-10-07 10:47:11 UTC
Summary
This PR implements a comprehensive config refactor that fundamentally changes how plugins are structured and configured in the erxes-next application. The refactor moves from a complex nested plugin architecture with multiple modules per plugin to a simplified, flattened structure where each plugin is treated as a single entity with standardized configuration.Key Changes:
Plugin Architecture Simplification: The
IUIConfiginterface has been completely restructured, removing the complexmodulesarray and introducing direct properties likepathandhasFloatingWidgetat the plugin level. ThesubGroupsproperty was renamed tosubGroup(singular) to reflect the new simplified approach.Routing Refactoring: Path definitions across plugins have been converted from absolute paths to relative segments. For example, operation paths changed from
/settings/operation/teamtoteam, allowing for more flexible path composition with base prefixes.Settings Navigation Modernization: A new settings navigation system has been implemented where each plugin provides its own dedicated settings navigation component (like
FrontlineSettingsNavigationandOperationSettingsNavigation) that integrates with a centralized settings sidebar.Module Federation Updates: Plugin export configurations have been consolidated, with frontline_ui combining separate settings exports into a unified
frontlineSettingsmodule, and operation_ui changing fromteamSettingstooperationSettings.Component Reorganization: Several components have been restructured, with frontline settings being split into
InboxSettings.tsxandInboxSettingsLayout.tsxfor better separation of concerns, and operation settings being wrapped in a newOperationSettings.tsxrouter component.The refactor affects the entire plugin ecosystem, touching configuration files, routing components, navigation hooks, and UI components across both the core-ui and plugin directories. This change establishes a more maintainable and consistent plugin architecture that reduces complexity while improving modularity.
Important Files Changed
Changed Files
Confidence score: 1/5
Sequence Diagram
sequenceDiagram participant User participant CLI as "CLI Tool" participant Enquirer as "Enquirer (Prompt)" participant FileSystem as "File System" participant BackendPlugin as "Backend Plugin Creator" User->>CLI: "Run create-plugin.js" CLI->>Enquirer: "prompt([pluginName, moduleName])" Enquirer->>User: "What is the name of your plugin?" User->>Enquirer: "Enter plugin name" Enquirer->>CLI: "Validate plugin name format" Enquirer->>User: "What is the name of your module?" User->>Enquirer: "Enter module name" Enquirer->>CLI: "Validate module name format" CLI->>CLI: "Convert names to kebab-case" CLI->>FileSystem: "mkdirSync(frontendPluginDir)" CLI->>FileSystem: "Create directory structure" CLI->>FileSystem: "writeFileSync(assets files)" CLI->>FileSystem: "writeFileSync(config.tsx)" CLI->>FileSystem: "writeFileSync(Main.tsx)" CLI->>FileSystem: "writeFileSync(Settings.tsx)" CLI->>FileSystem: "writeFileSync(IndexPage.tsx)" CLI->>FileSystem: "writeFileSync(module-federation.config.ts)" CLI->>FileSystem: "writeFileSync(project.json)" CLI->>FileSystem: "writeFileSync(tsconfig files)" CLI->>FileSystem: "writeFileSync(jest.config.ts)" CLI->>FileSystem: "writeFileSync(rspack configs)" CLI->>FileSystem: "writeFileSync(eslint.config.js)" CLI->>FileSystem: "writeFileSync(main.ts)" CLI->>FileSystem: "writeFileSync(bootstrap.tsx)" CLI->>FileSystem: "writeFileSync(Widgets.tsx)" CLI->>BackendPlugin: "createBackendPlugin(pluginName, moduleName)" BackendPlugin-->>CLI: "Backend plugin created" CLI->>User: "Plugin created successfully!" CLI->>User: "Display next steps instructions"Summary by CodeRabbit