feat: plugin flexible layout#1219
Conversation
WalkthroughThis pull request introduces several layout and UI enhancements across multiple components. Key changes include adding a conditional class and new functions (e.g., Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant PP as PluginPanel Component
participant LP as useLayout Composable
U->>PP: Initiates drag on resizer (right/left)
PP->>LP: Call onMouseDownRight/onMouseDownLeft (throttled)
LP-->>PP: Update panel width and fixed panel state
PP->>U: Render panel with updated dynamic styles
sequenceDiagram
participant U as User
participant PR as PluginRightMenu Component
participant Layout as useLayout (for context)
U->>PR: Right-click on a plugin item
PR->>PR: Execute showContextMenu (calculate position, set visibility)
PR->>U: Display context menu with options (hide/switch align)
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
✨ Finishing Touches
🪧 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 using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (19)
packages/register/src/constants.js (1)
49-49: Inline Comment Clarity and Consistency CheckThe added inline comment (
// 页面 JS) provides useful context about thePageproperty and its association with page-related JavaScript. Ensure that this style of inline commentary aligns with your project's overall guidelines, especially if other properties might benefit from similar annotations for consistency and clarity.packages/common/component/PluginRightMenu.vue (1)
143-183: Added styling for context menu.The CSS properly styles the context menu with appropriate positioning, shadows, and hover effects. One minor issue is the comment on line 145 about "importing B's CSS style" which appears to be a development note that should be removed.
Consider removing the comment "/* 引入B的CSS样式 */" which appears to be a development note.
packages/plugins/schema/src/Main.vue (1)
127-128: TODO comment for future implementation.There's a TODO comment regarding history stack implementation. Consider creating a separate task to track this feature enhancement.
packages/plugins/block/src/Main.vue (3)
12-14: Check naming consistency between “add-page” and “新建区块”The SVG icon name “add-page” differs from the tooltip text “新建区块,” which can confuse future contributors.
-<svg-button name="add-page" placement="bottom" tips="新建区块" @click="openBlockAdd"></svg-button> +<svg-button name="add-block" placement="bottom" tips="新建区块" @click="openBlockAdd"></svg-button>
15-119: Consider extracting sub-components for maintainabilityThis portion of the template is extensive. Splitting the category/group selection, popover, and block-list display into smaller components can shorten the file, reduce complexity, and improve unit test coverage.
220-224: Provide a default value forfixedPanelsWithout a default, referencing
fixedPanelsin parent or child components could cause errors when it’s undefined.props: { fixedPanels: { type: Array, + default: () => [] } },packages/plugins/state/src/Main.vue (2)
12-77: Break down large content section for clarityThe entire data-source logic is placed under the content slot. Consider splitting the left panel, search bar, and right panel configuration into smaller components to ease maintenance.
118-121: Add a default forfixedPanelsAs with similar components, consider providing a default array to avoid potential undefined references.
props: { fixedPanels: { type: Array, + default: () => [] } }packages/common/component/PluginSetting.vue (1)
103-111: Validate thealignpropSince
alignis a string, restricting it or documenting allowed values could prevent misconfiguration (e.g.,'leftTop', 'rightBottom', 'leftBottom', etc.).align: { type: String, default: 'leftTop' + // Consider validating or enumerating possible values here },packages/layout/src/Main.vue (3)
12-12: Consider unifying the prop names.
You are passing both:plugins="registry.plugins"and:plugin-list="pluginList"todesign-plugins. This is slightly duplicative and could cause confusion. Consider using a single source of truth or a more intuitive naming convention to reduce potential inconsistencies.Also applies to: 14-14
77-82: Evaluate naming consistency for the alignment methods.
changeLeftAligncallsright.value?.changeAlign(pluginId)and vice versa. Although it works logically, consider making the naming more intuitive to reflect moving plugins in or out of each side.
84-118: Wrap localStorage usage in error handling.
Storing plugin data in localStorage is convenient but can fail in some scenarios (e.g., private browsing). Consider adding a try/catch aroundlocalStorage.setItemto gracefully handle potential errors.+ try { localStorage.setItem('plugin', JSON.stringify(plugin)) + } catch (e) { + console.warn('Failed to store plugin data in localStorage:', e) + } initPluginStorageReactive(plugin)packages/layout/src/DesignPlugins.vue (1)
42-65: Refactor potential for shared logic with top nav.
The bottom nav code is nearly identical to the top nav code. Consider extracting common logic to a helper function or shared component to reduce duplication.packages/layout/src/DesignSettings.vue (3)
20-36: Use stable keys in v-for iteration.
v-for="(item, index) in settingPlugins" :key="index"can lead to re-rendering issues when the array changes. It is safer to rely on a unique identifier withinitem(likeitem.id) as the key if possible.Consider this diff:
-<div v-for="(item, index) in settingPlugins" :key="index"> +<div v-for="(item, index) in settingPlugins" :key="item.id || index">
108-136: Ensure functions handle uninitialized states.
The methodsclose,switchAlign,changeAlign,setRender, andclickMenudepend on an existing plugin ID or item. Validate ifitemmight be null or undefined, especially in dynamic plugin scenarios, to avoid runtime errors.If needed, add null checks or default parameters in these methods to handle edge cases gracefully.
211-295: Recommend clarifying nav-panel display logic.
#tiny-engine-nav-paneltoggles.completedclass to managedisplay: block;. If other logic setsdisplay: none;or modifiesz-index, it might conflict. Consider consolidating the display logic into a single style or a computed property to avoid drift.packages/layout/src/composable/useLayout.js (3)
29-31: Fine-grained plugin event management.
pluginEvent: 'all'is a simple approach to unify event handling. Ensure that you properly handle future states if partial events or event scoping become required.
71-84: Unified menu visibility toggles.
leftMenuShownStorageandrightMenuShownStorageeffectively maintain persistent visibility states between sessions. Confirm there isn’t an overlap if a user tries to hide both simultaneously, which might block re-opening the UI.
85-97: Refined approach to changing fixed panels.
changeLeftFixedPanelsandchangeRightFixedPanelshandle toggling with arrays. Consider adding a check to prevent the same plugin from appearing in both left and right panels if that isn’t allowed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (54)
packages/canvas/DesignCanvas/src/DesignCanvas.vue(4 hunks)packages/common/component/PluginPanel.vue(5 hunks)packages/common/component/PluginRightMenu.vue(1 hunks)packages/common/component/PluginSetting.vue(9 hunks)packages/common/component/index.js(1 hunks)packages/layout/package.json(1 hunks)packages/layout/src/DesignPlugins.vue(10 hunks)packages/layout/src/DesignSettings.vue(2 hunks)packages/layout/src/Main.vue(4 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/plugins/block/meta.js(1 hunks)packages/plugins/block/src/BlockSetting.vue(4 hunks)packages/plugins/block/src/Main.vue(5 hunks)packages/plugins/bridge/meta.js(1 hunks)packages/plugins/bridge/src/BridgeSetting.vue(4 hunks)packages/plugins/bridge/src/Main.vue(4 hunks)packages/plugins/datasource/meta.js(1 hunks)packages/plugins/datasource/src/DataSourceForm.vue(6 hunks)packages/plugins/datasource/src/DataSourceGlobalDataHandler.vue(3 hunks)packages/plugins/datasource/src/DataSourceRecordList.vue(3 hunks)packages/plugins/datasource/src/DataSourceRemotePanel.vue(5 hunks)packages/plugins/datasource/src/Main.vue(5 hunks)packages/plugins/help/meta.ts(1 hunks)packages/plugins/help/src/HelpIcon.vue(1 hunks)packages/plugins/i18n/meta.js(1 hunks)packages/plugins/i18n/src/Main.vue(4 hunks)packages/plugins/materials/meta.js(1 hunks)packages/plugins/materials/src/meta/block/src/BlockGroupPanel.vue(4 hunks)packages/plugins/materials/src/meta/layout/src/Main.vue(3 hunks)packages/plugins/page/meta.js(1 hunks)packages/plugins/page/src/Main.vue(3 hunks)packages/plugins/page/src/PageFolderSetting.vue(4 hunks)packages/plugins/page/src/PageSetting.vue(4 hunks)packages/plugins/robot/meta.js(1 hunks)packages/plugins/schema/meta.js(1 hunks)packages/plugins/schema/src/Main.vue(5 hunks)packages/plugins/script/meta.js(1 hunks)packages/plugins/script/src/Main.vue(5 hunks)packages/plugins/state/meta.js(1 hunks)packages/plugins/state/src/Main.vue(5 hunks)packages/plugins/tree/meta.js(1 hunks)packages/plugins/tree/src/Main.vue(3 hunks)packages/plugins/tutorial/meta.js(1 hunks)packages/register/src/common.js(2 hunks)packages/register/src/constants.js(1 hunks)packages/settings/events/index.js(1 hunks)packages/settings/events/meta.js(1 hunks)packages/settings/events/src/Main.vue(1 hunks)packages/settings/props/meta.js(1 hunks)packages/settings/props/src/Main.vue(1 hunks)packages/settings/styles/meta.js(1 hunks)packages/settings/styles/src/Main.vue(6 hunks)packages/theme/base/src/page/base-config-page.less(1 hunks)packages/toolbars/themeSwitch/src/Main.vue(1 hunks)
🔇 Additional comments (199)
packages/plugins/script/src/Main.vue (8)
2-30: Improved component architecture with the new plugin-panel implementation.The template has been restructured to use the
<plugin-panel>component, which provides better organization through named slots for the header and content sections. This aligns with the PR objective of implementing a unified logic for plugin panels and will help maintain consistency across the application.
4-5: Flexible panel configuration properties are now properly supported.The addition of the
:fixed-name="PLUGIN_NAME.Page"and:fixedPanels="fixedPanels"props enables the new flexible layout functionality, allowing this panel to participate in the drag-and-drop and fixed/floating state management system.
34-37: Enhanced state management with Composition API.The addition of
reactiveandprovideimports, along with the use ofuseLayouthook, indicates a shift towards Vue's Composition API for more reactive state management. This is a good practice that enhances component interactivity.
53-58: Component registration and props definition are properly structured.The
PluginPanelcomponent registration and thefixedPanelsprop definition are correctly implemented, with appropriate type checking for the Array type.
65-70: State sharing approach using provide/inject pattern.The implementation of reactive
panelStateand providing it to child components follows Vue's recommended pattern for sharing state across component trees. This is a good approach for maintaining state consistency within the plugin panel hierarchy.
111-111: Plugin name constant properly exposed to template.The
PLUGIN_NAMEconstant from theuseLayouthook is correctly returned for use in the template.
130-151: Well-structured styling for the notification indicator and save button.The styling for the
.icon-wrap,.tiny-button, and.redclasses is clean and maintainable, providing visual feedback about unsaved changes through the red dot indicator. The positioning and sizing are appropriate for the UI design.
154-157: Editor content styling provides appropriate spacing.The padding and height calculations for the code editor content provide sufficient space while maintaining a clean appearance, which is important for a good user experience when working with code.
packages/plugins/page/meta.js (1)
6-6: Alignment property standardized to 'leftTop'This change is part of the standardization of alignment properties across plugin meta files to support the new flexible layout system mentioned in the PR objectives.
packages/plugins/tutorial/meta.js (1)
6-6: Alignment property standardized for plugin positioningThe align property has been updated from 'bottom' to 'leftBottom', which aligns with the PR objective to standardize plugin positioning and enable more flexible layout management.
packages/plugins/materials/meta.js (1)
6-6: Alignment property standardized for materials pluginThe align property has been updated from 'top' to 'leftTop', consistent with the standardization across other plugins to support the new flexible layout system.
packages/common/component/index.js (1)
17-17: New component export added to support plugin context menuThe export of PluginRightMenu is a crucial addition that enables the right-click context menu functionality mentioned in the PR objectives, supporting plugin repositioning and visibility controls.
packages/plugins/datasource/meta.js (1)
5-5: Alignment property standardized for datasource pluginThe align property has been updated from 'top' to 'leftTop', consistent with the pattern applied to other plugins, supporting the new flexible layout system.
packages/plugins/block/meta.js (1)
5-5: Alignment property standardized to new naming conventionThe
alignproperty has been updated from 'top' to 'leftTop' as part of standardizing alignment properties across plugins for the new flexible layout system.packages/plugins/robot/meta.js (1)
8-8: Alignment property updated to use new position conventionThe
alignproperty has been changed from 'bottom' to 'leftBottom', consistent with the standardization of alignment properties across all plugins to support the new flexible layout system.packages/plugins/bridge/meta.js (1)
5-5: Alignment property standardized to new naming conventionThe
alignproperty has been updated from 'top' to 'leftTop', following the same pattern as other plugins to support the new flexible layout implementation.packages/plugins/help/src/HelpIcon.vue (1)
157-157: DOM element reference updated for component settings guideThe
domElementselector has been updated from '#tiny-right-panel' to '#rightTop' to reflect the new DOM structure introduced by the flexible layout implementation. This ensures the help guide correctly targets the right panel in the new UI.packages/plugins/i18n/meta.js (1)
5-6: LGTM: Alignment and width properties updated for flexible layoutThe changes to the alignment property from 'top' to 'leftTop' and the addition of a width property (600) align with the PR objective of implementing a flexible layout for plugin panels. These property changes will enable the plugin to properly position itself in the new layout system.
packages/plugins/schema/meta.js (1)
6-7: LGTM: Alignment and width properties updated for flexible layoutThe alignment property has been updated from 'bottom' to 'leftBottom' and a width property of 600 has been added. These changes are consistent with the standardization of alignment specifications across plugins for the new flexible layout system.
packages/settings/styles/meta.js (1)
6-7: LGTM: Alignment and icon properties updated for flexible layoutThe alignment property has been changed from 'left' to 'rightTop', positioning this panel on the right side of the interface, which differs from the left-side positioning of other plugins. Additionally, the icon has been updated from an empty string to 'display-inline', providing a visual indicator for this setting.
packages/plugins/help/meta.ts (2)
5-5: Added meaningful title for the Help pluginThe title has been updated from an empty string to '帮助' (meaning "Help" in Chinese), which improves the user interface by providing clear labeling for this plugin.
8-8: Standardized alignment propertyThe alignment property has been changed from 'bottom' to 'leftBottom', providing more precise positioning control. This change is consistent with the PR objective of implementing a unified layout logic for plugins.
packages/settings/props/meta.js (2)
5-5: Updated alignment to right side panelChanged alignment from 'left' to 'rightTop', which is consistent with the PR objective of restructuring the display logic for the right-side plugin panel.
7-7: Added appropriate icon for properties panelAdded 'form' as the icon, which visually represents the purpose of this panel better than the previous empty string.
packages/settings/events/meta.js (2)
5-5: Updated alignment to right side panelChanged alignment from 'left' to 'rightTop', maintaining consistency with other settings panels in the right panel structure.
7-7: Added appropriate icon for events panelAdded 'target' as the icon, which provides a visual indicator for the events functionality, improving UI clarity.
packages/plugins/script/meta.js (2)
6-6: Standardized alignment propertyThe alignment has been changed from 'top' to 'leftTop', following the same pattern as other plugins in this PR, which contributes to the unified layout logic implementation.
7-7: Added width property for draggable panel supportA width value of 600 has been added, which supports the PR objective of enabling users to manually adjust panel width through dragging by providing a default width.
packages/register/src/common.js (1)
12-12: Enhanced object validation to avoid processing Vue refsThe changes add a check to prevent Vue reference objects from being treated as regular objects during registry generation. This is important to prevent potential infinite recursion or undesired behavior when processing the registry.
This change is a good defensive programming practice that handles Vue's reactivity system properly.
Also applies to: 164-164
packages/theme/base/src/page/base-config-page.less (1)
43-43: Fine-tuned collection panel width calculationThe change from
100vwto99vwin the collection panel width calculation subtly reduces the panel width. This adjustment likely prevents potential horizontal scroll issues that could occur at edge cases.This is a subtle but effective adjustment to improve the layout's stability.
packages/settings/events/index.js (1)
23-23: Flattened options object structure for better accessThe options structure has been changed from a nested object with
commonEventsto a flat merged object usingObject.assign(). This flattening makes the properties from bothcommonEventsandmetaData.optionsdirectly accessible without an additional nesting level.This simplifies property access and aligns with the new flexible layout implementation for plugins.
packages/canvas/DesignCanvas/src/DesignCanvas.vue (3)
2-2: Added conditional user interaction blocker during drag operationsA new conditional class binding has been added that applies the 'not-selected' class when
getMoveDragBarState()returns true. This class disables pointer events and user selection, effectively blocking interaction with the canvas during drag operations.This prevents unwanted interactions with the canvas while dragging, improving the user experience.
70-71: Added layout state management functionThe
getMoveDragBarStatefunction from theuseLayoutcomposable has been imported and exported from the component's setup. This function determines when drag operations are active.This addition properly integrates with the new flexible layout system being implemented in this PR.
Also applies to: 280-280
291-296: Added critical CSS to disable interactions during dragA new scoped style for the
.not-selectedclass has been added that disables pointer events and user selection. This CSS is applied conditionally when drag operations are active.The CSS implementation is clean and effectively prevents interaction with the canvas during drag operations, which is essential for a good user experience.
packages/plugins/page/src/PageFolderSetting.vue (4)
2-8: Good addition of layout-related properties to plugin-settingThe addition of
:fixed-name="PLUGIN_NAME.AppManage"and:align="align"attributes enables this component to work with the new flexible layout system, allowing it to maintain proper positioning and alignment within the UI.
36-41: LGTM - Proper imports for the new layout functionalityThe addition of
computedfrom Vue anduseLayoutfrom the meta-register package provides the necessary utilities to support the dynamic alignment features.
93-94: Well-structured implementation of layout integrationThe extraction of
PLUGIN_NAMEandgetPluginByLayoutfrom the useLayout composable and the creation of a computed property for alignment provides reactive positioning capability, which aligns with the PR's goal of implementing a flexible layout for plugin panels.
209-212: LGTM - Properly exposing layout properties to the templateThe addition of
alignandPLUGIN_NAMEto the returned object makes these properties available in the template, completing the implementation of the flexible layout feature for this component.packages/plugins/datasource/src/DataSourceRecordList.vue (3)
6-7: Good implementation of layout properties for DataSourceRecordListAdding
:fixed-name="PLUGIN_NAME.Collections"and:align="align"attributes to the plugin-setting component enables this component to participate in the flexible layout system, maintaining consistency with other plugin components.
127-128: LGTM - Proper layout implementation with computed bindingExtracting
PLUGIN_NAMEandgetPluginByLayoutfrom useLayout and creating a computed property for alignment provides the necessary reactivity for dynamic positioning, which is essential for the flexible layout feature.
565-566: Well-implemented exposure of layout properties to templateProperly adding
alignandPLUGIN_NAMEto the returned object makes these properties available in the template, ensuring the component can use the flexible layout system.packages/plugins/datasource/src/DataSourceRemotePanel.vue (4)
5-7: Good addition of alignment and styling for DataSourceRemotePanelAdding the
plugin-datasourceclass and:align="align"attribute enhances the plugin-setting component with proper styling and positioning capabilities, which is consistent with the PR's flexible layout objectives.
56-65: LGTM - Proper imports for layout functionalityAdding
computedfrom Vue and includinguseLayoutin the imports provides the necessary tools for implementing the dynamic layout features.
118-120: Well-structured layout implementation with reactive propertiesThe extraction of layout-related utilities and creation of a computed property for alignment provides the necessary reactivity for the panel's positioning, supporting the PR's flexible layout goals.
228-228: Proper exposure of the align property to the templateAdding
alignto the returned object makes this property available in the template, completing the implementation of the flexible layout feature for this component.packages/plugins/datasource/src/DataSourceForm.vue (5)
2-8: Good implementation of layout attributes for DataSourceFormThe addition of the
plugin-datasourceclass and layout-related attributes (:fixed-nameand:align) enables this component to properly integrate with the flexible layout system, maintaining consistency with other plugin components.
36-36: LGTM - Added computed import for reactive propertiesAdding the
computedimport from Vue enables the creation of reactive properties needed for the dynamic layout system.
100-102: Well-implemented layout integration with computed bindingExtracting layout utilities and creating a computed property for alignment provides the necessary reactivity for dynamic positioning, which is essential for the flexible layout feature.
150-152: Good improvement to watcher configurationAdding
{ immediate: true }to the watch configuration ensures that the watcher runs immediately after creation, which is important for properly initializing the component's state based on incoming props.
260-261: Properly exposed layout properties to the templateAdding
alignandPLUGIN_NAMEto the returned object makes these properties available in the template, enabling the component to utilize the flexible layout system.packages/plugins/tree/src/Main.vue (3)
2-8: Improved panel component integration with the flexible layout system.The
plugin-panelcomponent now includes standard props for fixed panel management (fixed-nameandfixedPanels), which integrates well with the new flexible layout system mentioned in the PR objectives.
39-39: Good update to imports for panel state management.Added
provideandnextTickimports from Vue to support the new panel state management pattern.
58-68: Well-implemented panel state management.The setup function now properly accepts the
emitparameter, creates a reactivepanelStateobject, and usesprovideto make it available to child components. This approach is consistent with other plugins in the codebase and enables more flexible event handling.packages/plugins/materials/src/meta/layout/src/Main.vue (3)
2-7: Consistent implementation of flexible panel layout.The
plugin-panelnow includes the necessary props for the flexible layout system (fixed-nameandfixedPanels), maintaining consistency with other plugin implementations.
23-23: Good import refinement for plugin naming standardization.Updated import statement to include
META_APP as PLUGIN_NAME, which aligns with the standardized approach to plugin naming across components.
83-83: Proper exposure of PLUGIN_NAME to the template.Added
PLUGIN_NAMEto the returned values from the setup function, making it accessible in the template for thefixed-nameprop.packages/plugins/block/src/BlockSetting.vue (4)
6-7: Enhanced plugin setting with alignment and fixed-name props.The
plugin-settingcomponent now includes both:align="align"and:fixed-name="PLUGIN_NAME.BlockManage"props, enabling better integration with the flexible layout system and proper alignment handling.
91-98: Organized imports for layout management.The import statement is properly updated to include
useLayoutand other necessary modules, with good organization using multi-line import.
164-166: Well-implemented layout integration.Added
PLUGIN_NAMEconstant and computedalignproperty that usesgetPluginByLayoutto dynamically determine alignment based on the current layout configuration.
292-293: Proper exposure of layout variables.Added
alignandPLUGIN_NAMEto the returned values from the setup function, making them accessible in the template.packages/plugins/page/src/Main.vue (7)
2-10: Well-structured plugin panel with flexible layout support.The
plugin-panelcomponent now includes proper class, fixed-name, and fixedPanels props, along with documentation features (docsUrl and isShowDocsIcon). This implementation aligns perfectly with the PR's goal of unified logic for panel states.
11-26: Properly implemented header actions for page management.The header slot contains well-positioned SVG buttons for creating new folders and pages, improving the user experience for page management.
28-38: Clean content area implementation with page tree.The content slot contains the page-tree component with appropriate props and event handlers, maintaining a clean separation of concerns.
47-47: Proper import for layout management.Updated import statement to include
useLayout, necessary for the flexible layout implementation.
79-81: Added required prop for flexible panels.Added
fixedPanelsprop with proper type definition, enabling the component to accept an array of fixed panels.
83-94: Well-implemented panel state management.The setup function now properly accepts the emit parameter, extracts the PLUGIN_NAME constant, and creates a reactive panelState object with the emit function, providing it to child components for consistent event handling.
178-178: Proper exposure of PLUGIN_NAME to the template.Added
PLUGIN_NAMEto the returned values from the setup function, ensuring it's accessible for the fixed-name prop in the template.packages/plugins/datasource/src/Main.vue (6)
2-31: Standardized plugin panel structure with enhanced configurabilityThe template has been restructured to use
<plugin-panel>with new props:fixed-name,:fixedPanels, and:isShowDocsIcon. This aligns with the PR objective of implementing a unified logic for floating and fixed states of the plugin panel.
52-52: Updated imports to support layout functionalityThe import statements have been appropriately updated to include necessary components and hooks, particularly
useLayoutfrom the meta-register, which is essential for the new flexible layout functionality.Also applies to: 59-59, 64-65
80-86: Added support for fixed panels via propsNew props have been added to accept
fixedPanelsas an array type, enabling the component to participate in the new flexible layout system.
87-97: Enhanced component communication with reactive stateThe setup function now creates and provides a reactive
panelStateobject that includes the emit function, establishing a pattern for component communication that can be reused across the application.Also applies to: 98-103
153-164: Properly exposing PLUGIN_NAME in the return statementThe
PLUGIN_NAMEconstant obtained fromuseLayout()is correctly returned from the setup function, making it available to the template for consistent plugin identification.
174-175: Improved responsive styling for add-data-source buttonThe addition of
width: calc(100% - 24px)ensures the button properly adapts to its container width, improving the responsive design of the component.packages/plugins/datasource/src/DataSourceGlobalDataHandler.vue (4)
2-24: Restructured plugin panel with standardized propsThe template has been improved by removing unnecessary wrapper div and adding layout-related props (
:align,:fixed-name) to the<plugin-setting>component. This aligns with the PR objective of implementing a more consistent layout system.
28-31: Updated imports to support computed alignmentThe import statement now includes
computedfrom Vue anduseLayoutfrom the meta-register, providing the necessary tools for dynamic alignment calculation.
57-59: Implemented dynamic alignment based on layout configurationThe component now uses a computed
alignproperty derived from the layout configuration, allowing it to dynamically position itself based on the overall layout system.
99-102: Properly exposing alignment and plugin nameThe
aligncomputed property andPLUGIN_NAMEconstant are correctly returned from the setup function, making them available to the template for consistent plugin identification and positioning.packages/settings/styles/src/Main.vue (8)
2-10: Implemented flexible plugin panel with collapse functionalityThe template now uses
<plugin-panel>with props for fixed panels and collapse functionality, which aligns with the PR objective of creating a more flexible layout system.
10-77: Structured content within template slotThe style editor content is now properly organized within the
#contentslot of the plugin panel, maintaining the existing functionality while benefiting from the new layout system.
81-81: Updated imports to support layout functionalityThe import statements now include necessary Vue features (
reactive,provide) and thePluginPanelcomponent, providing the foundation for the flexible layout system.Also applies to: 83-83, 99-99
120-124: Added support for fixed panels via propsThe component now accepts
fixedPanelsas a prop, allowing it to participate in the flexible layout system being implemented across the application.
138-138: Using reactive ref for collapse stateThe
isCollapsedstate is now a reactive reference, andPLUGIN_NAMEis obtained fromuseLayout(), improving state management and integration with the layout system.Also applies to: 145-146
147-151: Enhanced component communication with reactive stateA reactive
panelStateobject is created and provided to child components, establishing a consistent pattern for component communication.
223-226: Added method to manage collapse stateThe new
updateCollapseStatusmethod properly manages the collapse state of the panel, supporting the PR objective of enhancing the interactivity of the plugin panel.
239-240: Properly exposing new functionality in the return statementThe
updateCollapseStatusmethod andPLUGIN_NAMEconstant are correctly returned from the setup function, making them available to the template.packages/settings/events/src/Main.vue (6)
2-8: Implemented flexible plugin panel structureThe template now uses
<plugin-panel>with appropriate props for fixed panels and plugin identification, which aligns with the PR objective of implementing a more consistent and flexible layout system.
9-19: Preserved original functionality within content slotThe existing
<tiny-collapse>component is now properly contained within a slot of the plugin panel, maintaining functionality while benefiting from the new layout system.
23-28: Updated imports to support new layout functionalityThe import statements now include necessary Vue composition API features and the
PluginPanelcomponent, along with theuseLayouthook for accessing layout information.
30-31: Using layout plugin name constantsThe component correctly obtains
PLUGIN_NAMEfrom theuseLayouthook, ensuring consistent plugin identification across the application.
33-35: Added support for fixed panels via propsThe component now accepts
fixedPanelsas a prop using thedefinePropsfunction, allowing it to participate in the flexible layout system.
37-43: Enhanced component communication with reactive stateThe component establishes a reactive
panelStateobject that includes the emit function and provides it to child components, creating a consistent pattern for component communication.packages/plugins/i18n/src/Main.vue (5)
2-10: Implemented fixed panel configuration for flexible layout.The plugin-panel now includes new props
:fixed-name="PLUGIN_NAME.I18n"and:fixedPanels="fixedPanels"which enables it to participate in the new flexible layout system. This allows users to control the panel's positioning and visibility as described in the PR objectives.
124-124: New import for layout functionality.Added necessary imports including
providefrom Vue anduseLayoutfrom meta-register to support the new layout management functionality.Also applies to: 130-136
156-160: Added fixedPanels prop for panel configuration.This new prop allows the component to receive information about fixed panels, which is essential for implementing the unified logic for the floating and fixed states mentioned in the PR objectives.
161-161: Implemented reactive state sharing via provide/inject pattern.The setup function now correctly receives props and emit, and establishes a reactive state with the emit function that is provided to child components. This enables proper event propagation throughout the component hierarchy.
Also applies to: 169-174
422-423: Exposed PLUGIN_NAME to template.Now returning PLUGIN_NAME from setup, making it available in the template for the fixed-name prop of the plugin-panel.
packages/plugins/bridge/src/Main.vue (5)
2-9: Implemented fixed panel configuration for resource management.The plugin-panel now includes new props to participate in the flexible layout system, maintaining consistency with other plugin components and allowing users to control the panel's positioning.
21-23: Added necessary imports for reactive state management.Imports now include
reactiveandprovidefrom Vue, anduseLayoutfrom meta-register, supporting the new layout functionality.
36-40: Added fixedPanels prop for consistency.This prop definition matches other plugin components, ensuring a consistent API across the plugin system.
41-41: Implemented event propagation and state sharing.The setup function now uses the provide/inject pattern with a reactive object to share the emit function with child components, and extracts PLUGIN_NAME from useLayout.
Also applies to: 46-52
66-67: Exposed PLUGIN_NAME to template.Making PLUGIN_NAME available in the template, which is required for the fixed-name prop.
packages/settings/props/src/Main.vue (5)
2-19: Restructured component using plugin-panel for consistent layout.The template has been refactored to use the plugin-panel component, which provides a unified layout and behavior consistent with other plugin components. This change is essential for implementing the flexible panel layout described in the PR objectives.
22-24: Updated imports to support new panel layout.Added imports for reactive state management and layout utilities, including the PluginPanel component.
32-34: Registered PluginPanel component.Properly registered the PluginPanel component that's used in the template.
35-35: Implemented state sharing for panel management.Setup function now includes props and emit parameters, and establishes the reactive state sharing pattern consistent with other plugin components.
Also applies to: 40-46
54-55: Exposed PLUGIN_NAME for template usage.Now returning PLUGIN_NAME from setup, making it available for the fixed-name prop in the template.
packages/common/component/PluginRightMenu.vue (5)
1-26: Implemented context menu for plugin management.This template creates a context menu that appears at specified coordinates, allowing users to:
- Hide specific plugins
- Switch plugin alignment between left and right sides
- Toggle visibility of multiple plugins via checkboxes
The implementation includes proper conditional rendering and positioning logic, addressing the PR objective of enabling users to control plugins' visibility and position.
28-54: Created reactive state management for context menu.The component properly defines props for the plugin list and alignment, and sets up a reactive context menu state object to track visibility, position, and the currently selected item. This supports the PR's objective of allowing users to reposition plugins.
55-84: Implemented position-aware context menu display.The
showContextMenufunction intelligently positions the menu based on available screen space, ensuring it remains visible when opened near the bottom of the viewport. This provides a better user experience for the new plugin management features.
90-114: Added plugin management actions.These methods handle the core functionality of the context menu:
hidePlugin: Toggles visibility of the selected pluginswitchAlign: Emits an event to change plugin alignmentchangeShowState: Updates the visibility state of a pluginThese functions directly support the PR objective of allowing users to control plugin positioning and visibility.
116-128: Implemented proper click-outside behavior.The component correctly adds and removes event listeners during its lifecycle to close the context menu when clicking outside, following best practices for modal interfaces.
packages/plugins/bridge/src/BridgeSetting.vue (4)
2-2: The plugin-setting component now supports flexible layout configuration.The addition of
:align="align"and:fixed-name="PLUGIN_NAME.Bridge"properties enhances the plugin panel's configurability, allowing it to participate in the new flexible layout system. This is consistent with the PR's objective to implement unified logic for floating and fixed states.
115-115: Updated imports to support layout functionality.The import statement now includes
useLayoutfrom the meta-register package, which provides the necessary functionality for the flexible layout system.
154-155: Layout hooks properly initialized in setup.The
useLayouthook is correctly used to extract the plugin name constant and the layout retrieval function. The computedalignproperty will reactively update whenever the layout configuration changes.
279-281: Added new properties to component return object.The
aligncomputed property andPLUGIN_NAMEconstant are correctly exposed to the template, enabling the flexible layout features.packages/plugins/materials/src/meta/block/src/BlockGroupPanel.vue (4)
2-9: Enhanced plugin-setting component with flexible layout support.The addition of
:align="align"and:fixed-name="PLUGIN_NAME.Materials"properties enables this component to participate in the new flexible layout system. This implementation supports the PR objective of allowing users to adjust panel positioning and visibility.
37-37: Updated imports to include necessary Vue reactivity and layout features.The import statements now properly include
computedfrom Vue anduseLayoutfrom the meta-register package, providing the required functionality for the flexible layout system.Also applies to: 43-43
128-129: Layout hooks correctly initialized in setup.The
useLayouthook is properly used to extract the plugin name constant and the layout retrieval function. The computedalignproperty will reactively update whenever the layout configuration changes.
285-292: Updated component's return object with layout properties.The
aligncomputed property andPLUGIN_NAMEconstant are correctly added to the setup function's return object, making them available to the template.packages/plugins/page/src/PageSetting.vue (4)
2-8: Enhanced plugin-setting component with flexible layout configuration.The addition of
:fixed-name="PLUGIN_NAME.AppManage"and:align="align"properties enables this component to participate in the flexible layout system. This implementation supports the PR's objective to unify floating and fixed states logic.
63-63: Added computed import for reactive alignment support.The import statement has been updated to include the
computedfunction from Vue, which is necessary for creating the reactivealignproperty.
145-146: Layout hooks properly initialized in setup.The
useLayouthook is correctly used to extract the plugin name constant and the layout retrieval function. The computedalignproperty will reactively update whenever the layout configuration changes.
393-394: Added layout properties to component's return object.The
aligncomputed property andPLUGIN_NAMEconstant are correctly added to the setup function's return object, making them available to the template.packages/plugins/schema/src/Main.vue (7)
2-39: Migrated to plugin-panel component with flexible layout support.The implementation has been refactored to use the
<plugin-panel>component instead of custom divs, providing a more consistent UI across plugins with built-in support for the flexible layout system. This change supports the PR objectives of unified plugin panel logic and consistent behavior.The structure now properly uses named slots for header and content sections, improving maintainability and alignment with the component architecture.
43-47: Updated imports to support plugin panel and layout functionality.The import statements have been updated to include necessary dependencies:
providefrom Vue for passing state to child componentsPluginPanelfrom common componentsuseLayoutfrom meta-register for flexible layout supportThis ensures all required functionality is available for the plugin panel implementation.
61-65: Added fixedPanels prop to support panel management.The component now accepts a
fixedPanelsprop which allows for dynamic management of fixed panel states. This enhancement aligns with the PR objective of implementing unified logic for floating and fixed states of the plugin panel.
75-75: Added layout hook for plugin name access.The
useLayouthook is correctly used to extract the plugin name constant, which is needed for the flexible layout system.
77-81: Implemented panel state with context sharing.A reactive
panelStateobject is created and provided to the component context, facilitating communication between parent and child components. This implementation pattern enhances the component's extensibility.
15-21: Hidden schema import functionality.The UI includes hidden elements for schema import functionality (a popover and a footer button). If this is intentional (feature flagging), this is fine. If these are meant to be implemented as part of this PR, they should be either completed or removed.
Could you clarify if the hidden schema import functionality is intentionally disabled or if it's a planned feature for a future PR?
Also applies to: 35-37
187-237: Updated styling to support plugin panel.The CSS has been appropriately adjusted to work with the new component-based structure. The removal of specific header styles and adjustments to content height reflect the shift of styling responsibilities to the
<plugin-panel>component.packages/plugins/block/src/Main.vue (3)
2-11: Good use of<plugin-panel>propsThese newly added props (
:fixed-name,:fixedPanels,:docsUrl, etc.) integrate smoothly with the existing layout utilities. No immediate issues detected.
473-474: Margin style looks fineSwapping
margin: 12px 0;formargin-bottom: 12px;is a harmless refinement, aligning well if you no longer need top spacing.
273-280:Details
✅ Verification successful
Verify the panelState injection
You’re providing
panelStateviaprovide('panelState', panelState). Ensure child components inject it under the same key and handle events properly.
🏁 Script executed:
#!/bin/bash # Description: Search for all inject calls referencing 'panelState' in the codebase. rg "inject\(['\"]panelState['\"]" -A 10Length of output: 7975
PanelState Injection Verified
The provider inpackages/plugins/block/src/Main.vuecorrectly sets up thepanelStateobject with theemitEventfunction. A search of the repository confirms that child components consistently inject it using the key'panelState', and examples like those inPluginPanel.vueindicate that event handling (usingpanelState.emitEvent) works as expected.packages/plugins/state/src/Main.vue (2)
2-11: Smooth transition to<plugin-panel>Using
<plugin-panel>with props like:fixed-nameand:fixedPanelsappears consistent with other components. No immediate issues found.
146-153: Ensure alignment logic covers multiple layouts
getPluginWidthandgetPluginByLayoutcomputations look correct for offsetting a right-side panel. If future layouts require additional top/bottom control, consider extending the logic or verifying it dynamically.packages/common/component/PluginSetting.vue (3)
3-11: Dynamic alignment is clearUsing
align-rightand computed styles is a straightforward approach to positioning. Ensure thealignlogic gracefully handles all future expansions (e.g., top/bottom or diagonal align).
119-131: Confirm offset logic for second-panel usage
firstPanelOffsetandalignStylerely ongetPluginWidth. If the panel’s width or position changes at runtime, ensure these computations update correctly without stale references.
154-159: Shadow class usage is consistentConditional application of
shadow-rightorshadow-leftimproves the UI feedback for different alignments.packages/layout/src/Main.vue (10)
9-10: Looks good for conditional rendering of the left plugins.
Thev-if="leftMenuShownStorage"andref="left"references appear consistent with the rest of the code and should allow for controlled visibility and programmatic access to the component.
22-22: Right menu rendering approach is consistent.
Usingv-if="rightMenuShownStorage"andref="right"to control and reference the right panel mirrors the logic on the left-hand side, keeping the layouts symmetric.Also applies to: 23-23
25-26: Props binding for the right panel is clear.
Providing:render-panel="settings.render",:plugin-list="pluginList", and@changeRightAlign="changeRightAlign"ensures the panel’s rendering logic is customizable, matching the left side pattern.Also applies to: 28-28
42-42: Import statement is appropriate.
Bringing inreffrom'vue'is straightforward and necessary.
61-61: No concerns with the updatedsetup()signature.
The function signature effectively captures the relevant properties for the layout.
66-67: Destructuring fromuseLayout()looks valid.
This nicely organizes layout states and methods.
74-75: Reactivity references for left and right.
Usingref(null)for bothleftandrightis a clean way to reference these child components.
121-127: Re-exported references improve clarity.
Exposing these parameters fromsetupfosters maintainability.
132-132: ReturningsettingsfromlayoutStateis consistent.
No issues spotted with the additional destructuring.
164-165: Flex display for.tiny-engine-right-wrapis appropriate.
This ensures the right panel aligns well for horizontal content arrangement.packages/layout/src/DesignPlugins.vue (15)
4-6: Efficient use of drag-and-drop for top nav list.
Bindingv-model="state.topNavLists", filtering, and grouping under"plugins"looks well-structured. This should simplify reordering.Also applies to: 9-10
23-23: Context menu logic is well-placed.
Preventing default on right-click ensures the custom menu is displayed instead of the browser’s default context menu.
25-25: Conditional visibility of plugins.
v-if="getPluginShown(item.id)"is a clear approach for toggling plugin display states.
39-41: Separating the bottom nav list enhances clarity.
This layout structure improves user experience by distinctly managing top and bottom plugin lists.
69-88: Plugin container logic is comprehensive.
Wrapping the plugin panel and the “not-selected” class in a separate<div>helps isolate drag bar states and visual cues.
90-90: Right-click menu integration.
Including<plugin-right-menu>with references to the combined top/bottom lists is a neat way to maintain a single context menu for all left-side plugins.
101-101: Importingvue-draggable-next.
Bringing in the library is necessary to support the newly added drag features.
103-103: Consolidating additional components under a single import.
{ PublicIcon, PluginRightMenu }from@opentiny/tiny-engine-commonhelps maintain a consistent shared library approach.
138-146: Destructuring fromuseLayout()is well-organized.
Retrieving multiple layout helpers fosters modular design. Keep ensuring these remain cohesive across the codebase.
148-155:showContextMenufunction handles various usage scenarios.
Handling both standard and item-specific context menus with the same function is flexible.
159-160: Dynamic assignment for top/bottom nav lists.
UsinggetPluginsByPositioncentralizes retrieval logic and keeps code more maintainable.
168-171: Binding entries and icons in a single pass is clean.
This approach centralizes plugin metadata, improving readability.
185-185: Passing appropriate nav list references to parent events.
Index-based referencing ensures the correct plugin is identified across different alignment lists.
217-227:switchAlignmethod for moving plugins to the right side.
This function nicely delegates the alignment changes upward (emit('changeLeftAlign', id)) and callsdragPluginLayout.
257-261: Handling drag end across different sides.
Closing the panel if it’s moved to the opposite side is a logical approach to avoid unexpected states.packages/common/component/PluginPanel.vue (20)
2-3: Responsive styling for the plugin panel.
Binding:style="{ width: panelWidth + 'px' }"and a configurable margin bottom helps adapt the panel’s layout dynamically.
12-22: Tooltip-based collapse icon is a great UI enhancement.
Having a light-effect tooltip for toggling collapse state improves discoverability while keeping the panel’s UI clean.
23-28: Fixed panel toggle.
Using a single button to toggle between fixed and non-fixed states is clear. Ensure that updates propagate consistently in the parent’s state.
32-34: Scrollable container.
Wrapping the main slot in a.scroll-contentcontainer with hidden scrollbars is user-friendly, especially for long plugin content.
36-37: Dual-sided resizers for flexible panel sizing.
Declaring.resizer-rightand.resizer-leftprovides symmetrical resizing. This is helpful for panels on either side of the screen.Also applies to: 38-38
42-42: Additional imports add clarity.
Pulling ininject,ref,computed,onMounted,provide,SvgButton, andTooltipneatly organizes external dependencies.Also applies to: 44-44, 47-47, 51-51, 53-54
83-109: Well-structured new props.
Props such asfixedPanels,fixedName,headerMarginBottom, andisShowCollapseIconare expressive and improve panel configuration.
110-110: EmittingupdateCollapseStatusfosters reactivity.
This allows parent components to respond to collapse changes immediately.
118-119: Constants for width boundaries.
MIN_WIDTHandMAX_WIDTHkeep resizing logic straightforward and readable.
124-125: Computed icon name for collapsed state is intuitive.
Switching between'collapse_all'and'expand_all'clarifies the panel’s state at a glance.
127-127: Injection and panel fixing logic.
ProvidingisCollapsedand injectingpanelStateensure consistent shared state. ThefixPanelmethod delegates updates back to the layout state neatly.Also applies to: 129-130
134-138: Retrieving plugin layout details.
getPluginWidth,changePluginWidth, and alignment checks are seamlessly integrated for a flexible panel design.
141-151: Responsive resizing logic.
CalculatingnewWidthbased on mouse movement is cleanly done. Hard-limiting toMIN_WIDTHandMAX_WIDTHprevents awkward UI states.
153-173: Throttling enhances performance.
Using a custom throttle function prevents excessive calculations during drag.
175-177: Applying the throttled functions.
throttledMouseMoveRightandthrottledMouseMoveLeftproperly limit the frequency of redraws.
181-215: Comprehensive event handling for mouse up/down.
Removing event listeners after mouse release and toggling the cursor styles anddraggingclass are crucial for a polished drag UX.
217-220: Late DOM selection for resizers.
initResizerDOM()is a safe approach for hooking into the DOM after mount, preventing null references.
222-225:clickCollapseIcontriggers an emit.
This straightforward method updates the local collapsed state and notifies the parent seamlessly.
227-229: Resizer initialization on mount.
onMounted(() => { initResizerDOM() })ensures the resizer elements exist before referencing them.
232-242: Returning the updated references.
Exposing these reactive states and methods fromsetupmaintains a fully open interface for any parent usage.packages/layout/src/DesignSettings.vue (7)
1-3: Use caution with pointer-events disabling when dragging.
Applying thenot-selectedclass based ongetMoveDragBarState()disables pointer events, which is typical for preventing undesired interactions while dragging. However, ensure the user experience remains consistent (e.g., no vital controls become accidentally non-interactive).Do you have tests confirming that essential UI elements are still accessible when
getMoveDragBarState()returns true?
5-16: Validate conditional rendering logic.
Usingv-show="renderPanel && components[renderPanel]"is good for performance, but confirm thatrenderPanelalways corresponds to a valid key incomponents. Otherwise, the empty panel might appear unexpectedly.Please confirm how you handle scenarios where
renderPanelmight reference a non-existent component, to prevent unexpected blank UI.
39-44: Review potential overlap in right-click management.
The<plugin-right-menu>component is rendered separately from the main draggable panel. Ensure no event conflicts occur when the user right-clicks multiple plugins in quick succession, as race conditions might cause unexpected menu positioning.
62-72: Props definition confirmed.
Usingtype: Arraywith a default empty array is consistent and safe forpluginList. Ensure you validate or filter the array to prevent references to invalid plugin structures.
93-105: Check context menu data flow.
showContextMenu(event, type, item, index, align)directly passes native event coordinates. It's correct for an internal UI, but confirm thatitemoraligncan’t be manipulated by external sources, preventing potential code injection or misalignment.Do you sanitize or restrict
itemandalignto known values?
137-150: Verify drag-and-drop indices.
onEnd(e)callsdragPluginLayout(e.from.id, e.to.id, e.oldIndex, e.newIndex). Confirm that the final list indices match the new plugin order, especially if external state modifies these arrays at the same time.
180-209: Maintain consistent styling for the right panel.
The usage of absolute positioning withright: var(--base-nav-panel-width)and conditionally applyingis-fixedis valid. Just ensure the final bounding box remains accessible on variable screen widths.packages/layout/src/composable/useLayout.js (6)
14-14: Local storage usage.
Importing and usinguseStorageis a convenient approach. Confirm that potential large amounts of data in storage do not degrade performance, and handle older or missing keys gracefully.
20-27: Good usage of PLUGIN_POSITION constants.
These enumerations clarify plugin alignment states, preventing magic strings. Keep them updated if new positions (liketopFixed) emerge.
34-47: Reactive layoutState expansions.
You’ve added more plugin and settings properties. Validate that changes torender,fixedPanels, andactivatingdo not introduce side effects if watchers or other reactive computations rely on them.Do you have unit tests covering transitions from non-fixed to fixed states?
65-70: Drag bar toggling logic.
getMoveDragBarStateandchangeMoveDragBarStateproperly reflect reactive state. If toggling it across multiple UI components, watch out for ephemeral race conditions (e.g., two components toggling the state out of sync).
133-138: Ensure forced closure logic doesn’t break pinned panels.
closeSetting(forceClose)forcibly setssettings.render = null. If a pinned or fixed panel is forcibly closed, ensure consistent re-opening logic is intact.
236-276: Validate drag indices especially across positions.
dragPluginLayout(...)updates item.index for cross-list and same-list drags. If there are external changes to these indices or if new plugins are injected after rendering, the method might cause collisions.Would you like a shell script or approach to test drag and drop correctness across repeated plugin additions?
packages/plugins/tree/meta.js (1)
6-6: Alignment property updated to support new flexible layoutChanging the alignment from 'top' to 'leftTop' is consistent with the PR's objective of implementing a unified logic for plugin panel positioning. This standardization appears across multiple plugin meta files in this PR and will help support the new draggable functionality.
packages/toolbars/themeSwitch/src/Main.vue (1)
84-84: Good practice: Using const for non-reassigned variableChanging from
lettoconstis appropriate here sincefilterListis not reassigned after its initial declaration. This improves code clarity by signaling the immutability intention of this variable.packages/plugins/state/meta.js (1)
5-5: Alignment property standardized for flexible layout supportThis change from 'top' to 'leftTop' is part of the standardization effort across all plugin meta files to support the new flexible layout system. This change ensures consistent positioning behavior with the enhanced plugin panel functionality introduced in this PR.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
packages/layout/src/DesignPlugins.vue (1)
293-294: Consider adding a width constraint for the dynamic panel width.The CSS changes set width to
auto !important, which allows flexible sizing. However, consider adding min/max width constraints to prevent panels from becoming too narrow or too wide.- width: auto !important; + width: auto !important; + min-width: 250px; + max-width: 600px;packages/layout/src/DesignSettings.vue (1)
309-312: Consolidate duplicate icon style definitions.There are duplicate style definitions for
.svg-icon.icon-plugin-icon-plugin-helpwith different font sizes (18px on line 306 and 22px on line 315). This can lead to inconsistent styling.- :deep(.svg-icon.icon-plugin-icon-plugin-help) { - font-size: 18px; - } - - :deep(.svg-icon.icon-plugin-icon-plugin-help) { - font-size: 22px; - } + :deep(.svg-icon.icon-plugin-icon-plugin-help) { + font-size: 22px; + }Also applies to: 314-316
packages/layout/src/composable/useLayout.js (2)
170-185: Ensure width limits to prevent UI issues with extremely wide panels.The
changePluginWidthfunction allows setting any width value. Consider adding validation to ensure width values stay within reasonable limits to prevent UI issues.const changePluginWidth = (name, width, offset) => { + // Ensure width stays within reasonable limits + const limitedWidth = Math.max(200, Math.min(800, width)) if (Object.prototype.hasOwnProperty.call(pluginStorageReactive.value, name)) { - pluginStorageReactive.value[name].width = width + pluginStorageReactive.value[name].width = limitedWidth pluginStorageReactive.value[name].offset = offset } else { pluginStorageReactive.value[name] = { - width + width: limitedWidth } } }
287-290: Ensure plugin list initialization is robust.The
initPluginStorageReactivefunction doesn't validate the structure of the providedpluginList. Consider adding validation to ensure it has the expected format.const initPluginStorageReactive = (pluginList) => { if (Object.keys(pluginStorageReactive.value).length) return + if (!Array.isArray(pluginList) || !pluginList.length) { + console.warn('Invalid plugin list provided for initialization'); + return; + } pluginStorageReactive.value = pluginList }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
packages/common/package.json(1 hunks)packages/configurator/package.json(1 hunks)packages/layout/package.json(1 hunks)packages/layout/src/DesignPlugins.vue(10 hunks)packages/layout/src/DesignSettings.vue(2 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/plugins/tree/src/Main.vue(3 hunks)
✅ Files skipped from review due to trivial changes (2)
- packages/configurator/package.json
- packages/common/package.json
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/layout/package.json
- packages/plugins/tree/src/Main.vue
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (10)
packages/layout/src/DesignPlugins.vue (5)
4-36: Great implementation of drag-and-drop functionality for the top navigation list!The transition from static lists to
vue-draggable-nextenhances the user experience by enabling flexible rearrangement of plugins. The proper setup with group name "plugins" ensures consistent dragging behavior.
163-172: Good fix for ensuring plugin deduplication in changeAlign!The implementation now properly checks and removes existing items before adding them to the target list, which resolves the previous issue noted in past reviews.
264-267: Ensure consistent panel state after drag operations.The
onEndmethod properly handles drag completion by closing panels when necessary and updating the layout. Make sure to test this with fixed panels to ensure they maintain their fixed state after dragging.
416-419: Good use of the .not-selected class for drag operations.The class effectively prevents pointer events and user selection during drag operations, which provides a better user experience.
223-233:Details
❓ Verification inconclusive
Verify closures on cross-panel alignment changes.
The
switchAlignmethod changes plugin alignment between panels and closes the current panel if necessary, which is good. However, verify that the interaction betweenclose()anddragPluginLayout()doesn't cause unexpected behavior when rapidly switching alignments.
🏁 Script executed:
#!/bin/bash # Check for any related issues or error handling around plugin alignment changes rg -B 2 -A 2 "switchAlign|changeAlign|dragPluginLayout" --type vueLength of output: 96
I'll run a revised shell script that searches for the relevant functions in Vue files using a glob pattern. This should help us gather the necessary context on how
close()anddragPluginLayout()interact.
🏁 Script executed:
#!/bin/bash # Re-run search for 'switchAlign' and 'dragPluginLayout' in .vue files using a glob filter rg -g "*.vue" -B 2 -A 2 "switchAlign|dragPluginLayout"Length of output: 5554
Action Required: Verify Rapid Switching Behavior on Panel Alignment
The implementation of
switchAlignin both DesignPlugins.vue and DesignSettings.vue follows a consistent pattern—removing the plugin from one panel, emitting an alignment change, conditionally closing the panel, and then triggeringdragPluginLayout(). While this ordering appears intentional and consistent across files, it’s important to manually verify that the immediate call toclose()beforedragPluginLayout()doesn’t introduce race conditions or state inconsistencies when users rapidly toggle alignments.
- Files to review:
packages/layout/src/DesignPlugins.vue(lines 223-233)packages/layout/src/DesignSettings.vuepackages/common/component/PluginRightMenu.vue(alignment trigger handlers)Please ensure that any asynchronous operations or state updates triggered by rapid switching are correctly managed in your manual tests or through additional automated tests to prevent unexpected behavior.
packages/layout/src/DesignSettings.vue (3)
20-37: Well-structured draggable navigation panel for right-side plugins!The implementation mirrors the left-side panel structure, providing consistent behavior. The context menu integration is properly implemented.
119-127: Great implementation of changeAlign with proper deduplication.The implementation checks for existing items and properly handles removing duplicates before adding to the target list.
91-99:Details
❓ Verification inconclusive
Verify context menu positioning for right-side panels.
The
showContextMenufunction is similar to the left panel implementation. Ensure the menu appears in the correct position for right-aligned elements, as screen coordinates may need adjustment.
🏁 Script executed:
#!/bin/bash # Check how the context menu positioning is handled in the codebase rg -A 5 "showContextMenu.*clientX.*clientY" --type vueLength of output: 84
I'll run a new shell script using an updated rg command that explicitly registers
.vuefiles. This will help verify how the context menu positioning is handled in theDesignSettings.vuefile.Please execute the following script:
#!/bin/bash # Re-run the search in the DesignSettings.vue file with vue file type explicitly added rg --type-add "vue:*.vue" -A 5 "rightMenu.value.showContextMenu" packages/layout/src/DesignSettings.vueOnce we have the output of this script, we can confirm if the positioning logic for right-side panels is consistent with the left-side implementation and verify that the screen coordinates are used properly.
packages/layout/src/composable/useLayout.js (2)
20-27: Good use of constants for plugin positions!Using a constant object for position values ensures consistency throughout the codebase and prevents typos in string values.
224-266: Robust implementation for handling drag operations!The
dragPluginLayoutfunction handles both same-list and cross-list dragging with proper index adjustments. The logic properly accounts for all edge cases.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (6)
packages/layout/src/composable/useLayout.js (6)
156-163: Enhance error handling with contextual information.The current implementation rethrows the original error without adding context. This makes debugging challenging as it's unclear where the error originated.
try { const storedPlugin = localStorage.getItem('plugin') if (storedPlugin) { plugin = JSON.parse(storedPlugin) } } catch (error) { - throw new Error(error) + throw new Error(`Failed to parse plugin data from localStorage: ${error.message}`) }
173-185: Add validation for plugin width.The
changePluginWidthfunction accepts any value without validation, which could lead to unusable UI if extreme values are provided.// 修改插件宽度 const changePluginWidth = (name, width, offset) => { + // Ensure width is a reasonable value (e.g., between 100 and 800 pixels) + const validWidth = Math.max(100, Math.min(width, 800)) if (Object.prototype.hasOwnProperty.call(pluginStorageReactive.value, name)) { - pluginStorageReactive.value[name].width = width + pluginStorageReactive.value[name].width = validWidth pluginStorageReactive.value[name].offset = offset } else { pluginStorageReactive.value[name] = { - width + width: validWidth } } }
211-215: Validate layout positions when changing plugin layout.The
changePluginLayoutfunction doesn't verify if the provided layout is a valid position.// 修改某个插件的布局 const changePluginLayout = (name, layout) => { + // Ensure the layout is a valid position + if (!Object.values(PLUGIN_POSITION).includes(layout)) { + console.warn(`Invalid layout position: ${layout}. Using default position.`) + layout = PLUGIN_POSITION.leftTop + } if (pluginStorageReactive.value[name]) { pluginStorageReactive.value[name].align = layout } }
235-243: Translate comments to English for consistency.The comments "往后移动" and "往前移动" are in Chinese, while the rest of the codebase uses English comments.
if (oldIndex < newIndex) { - //往后移动 + // Moving backward items.forEach((item) => { if (item !== movedItem && item.align === from && item.index > oldIndex && item.index <= newIndex) { item.index -= 1 } }) } else { - //往前移动 + // Moving forward items.forEach((item) => {
225-266: Add index bounds validation in dragPluginLayout.The
dragPluginLayoutfunction assumes indices are valid without checking, which could lead to unexpected behavior if invalid indices are provided.Consider adding validation to ensure indices are non-negative integers and within expected bounds:
const dragPluginLayout = (from, to, oldIndex, newIndex) => { if (from === to && oldIndex === newIndex) return + + // Validate indices are non-negative integers + if (!Number.isInteger(oldIndex) || !Number.isInteger(newIndex) || oldIndex < 0 || newIndex < 0) { + console.warn('Invalid indices provided to dragPluginLayout. Indices must be non-negative integers.') + return + } const items = Object.values(pluginStorageReactive.value) // Record the dragged item const movedItem = items.find((item) => item.align === from && item.index === oldIndex) + + // If no item found with matching position and index, exit early + if (!movedItem) { + console.warn(`No item found at position ${from} with index ${oldIndex}`) + return + }
201-208: Add error handling when plugin is not found.The
getPluginByIdfunction doesn't handle the case when a plugin with the given ID doesn't exist in the list. This could lead to undefined being returned and potentially cause errors elsewhere.const getPluginById = (pluginId) => { - return pluginList.find((item) => item.id === pluginId) + const plugin = pluginList.find((item) => item.id === pluginId) + if (!plugin) { + console.warn(`Plugin with ID ${pluginId} not found`) + } + return plugin } const getPluginsByPosition = (position, pluginList) => { - return getPluginsByLayout(position).map((pluginId) => getPluginById(pluginList, pluginId)) + return getPluginsByLayout(position) + .map((pluginId) => getPluginById(pluginList, pluginId)) + .filter(Boolean) // Filter out undefined values from plugins not found }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/layout/src/composable/useLayout.js(5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (4)
packages/layout/src/composable/useLayout.js (4)
48-48: Check for plugin name collisions.
layoutState.plugins.apiis an object where all plugin APIs are stored, which could lead to name collisions if two plugins register the same API key.Consider storing plugin APIs under unique sub-objects, e.g.
plugins.api[pluginName] = …, to avoid collisions.
14-14: Great work on the persistent storage implementation.The use of
useStoragefrom Vue Use to persist layout state is a good practice. The implementation correctly handles initialization and storage, including error handling and type checking.Also applies to: 154-170, 290-293
20-27: Well-defined position constants.Creating a clear
PLUGIN_POSITIONconstant object makes the code more maintainable and prevents typos when referencing positions.
268-277: Good implementation of side detection logic.The
isSameSidefunction is well-implemented, making it easy to determine if two positions are on the same side of the interface. This is crucial for the drag-and-drop functionality.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (10)
packages/layout/src/Main.vue (2)
74-82: Implementation of cross-component communication for alignment changesThe component references and alignment change methods enable communication between the left and right panels, supporting the drag-and-drop functionality mentioned in the PR objectives.
However, consider adding a defensive check for the
changeAlignmethod existence.const changeLeftAlign = (pluginId) => { - right.value?.changeAlign(pluginId) + if (right.value && typeof right.value.changeAlign === 'function') { + right.value.changeAlign(pluginId) + } }
87-118: Comprehensive plugin alignment initialization logicThis code initializes plugin alignment groups and properties, storing them in localStorage for persistence. This implementation supports the PR objectives of repositioning plugins and controlling visibility.
Consider two improvements:
- Extract this logic to a separate function for better readability
- Add error handling for localStorage operations
+ const initializePluginAlignments = (pluginList) => { + try { const alignGroups = {} const plugin = {} pluginList.forEach((item) => { if (item.id) { const align = item?.align || 'leftTop' // Initialize alignGroups[align] if (!alignGroups[align]) { alignGroups[align] = [] } // Add item.id to the corresponding alignGroups alignGroups[align].push(item.id) // Assign index and properties to each plugin const index = alignGroups[align].indexOf(item.id) plugin[item.id] = { width: item?.width || 300, align: align, index: index, isShow: true, entry: item.entry, id: item.id, icon: item.icon } } }) localStorage.setItem('plugin', JSON.stringify(plugin)) return plugin + } catch (error) { + console.error('Failed to initialize plugin alignments:', error) + return {} + } + } + + const plugin = initializePluginAlignments(pluginList) initPluginStorageReactive(plugin)packages/layout/src/composable/useLayout.js (8)
29-31: Consider consolidating plugin state management.The new
pluginStatereactive object only has one property (pluginEvent), which seems redundant aslayoutState.plugins.pluginEventalso exists (line 47). This could cause confusion about which property should be used in different contexts.-const pluginState = reactive({ - pluginEvent: 'all' -}) const layoutState = reactive({ isMoveDragBar: false, dimension: { // ... }, plugins: { isShow: true, fixedPanels: [PLUGIN_NAME.Materials], render: PLUGIN_NAME.Materials, pluginEvent: 'all', // ... }, // ... })
44-50: Consider standardizing comment language.There's a comment in Chinese at line 48 ("插件需要注册交互API到这里") while other comments are in English. Standardizing comment language improves codebase consistency and accessibility for all developers.
plugins: { isShow: true, fixedPanels: [PLUGIN_NAME.Materials], render: PLUGIN_NAME.Materials, pluginEvent: 'all', - api: {}, // 插件需要注册交互API到这里 + api: {}, // Plugins need to register interaction APIs here activating: false, // 右侧面版激活提示状态 showDesignSettings: true },
156-163: Improve error handling in localStorage operations.The current error handling simply rethrows the error without any additional context. Consider adding more descriptive error messages and potentially handling specific error types differently.
try { const storedPlugin = localStorage.getItem('plugin') if (storedPlugin) { plugin = JSON.parse(storedPlugin) } } catch (error) { - throw new Error(error) + console.error('Failed to parse plugin data from localStorage:', error) + plugin = [] }
173-173: Extract magic number to a named constant.The default plugin width of 300 appears as a magic number. Consider extracting this to a named constant at the top of the file for better maintainability.
+const DEFAULT_PLUGIN_WIDTH = 300 + // ... // 获取插件宽度 -const getPluginWidth = (name) => pluginStorageReactive.value[name]?.width || 300 +const getPluginWidth = (name) => pluginStorageReactive.value[name]?.width || DEFAULT_PLUGIN_WIDTH
176-185: Add validation for plugin width values.The
changePluginWidthfunction doesn't validate the input width. Consider adding validation to ensure the width is reasonable (e.g., positive, not too small or large).// 修改插件宽度 const changePluginWidth = (name, width, offset) => { + // Ensure width is a positive number and within reasonable bounds + if (typeof width !== 'number' || width < 100 || width > 800) { + console.warn(`Invalid plugin width: ${width}. Using default value.`) + width = DEFAULT_PLUGIN_WIDTH + } + if (Object.prototype.hasOwnProperty.call(pluginStorageReactive.value, name)) { pluginStorageReactive.value[name].width = width pluginStorageReactive.value[name].offset = offset } else { pluginStorageReactive.value[name] = { width } } }
188-188: Consistent default values across functions.The
getPluginByLayoutfunction uses a default value of 'leftTop', while other functions handling layouts don't specify defaults. Consider using thePLUGIN_POSITIONconstants for consistency.// 获取插件布局 -const getPluginByLayout = (name) => pluginStorageReactive.value[name]?.align || 'leftTop' +const getPluginByLayout = (name) => pluginStorageReactive.value[name]?.align || PLUGIN_POSITION.leftTop
225-266: Enhance documentation for complex drag logic.The
dragPluginLayoutfunction has complex logic for reordering items. While the initial comment is helpful, consider adding additional inline comments to explain the more complex parts of the algorithm.const dragPluginLayout = (from, to, oldIndex, newIndex) => { if (from === to && oldIndex === newIndex) return const items = Object.values(pluginStorageReactive.value) // 记录拖拽项 const movedItem = items.find((item) => item.align === from && item.index === oldIndex) + + // If the item to move wasn't found, exit early + if (!movedItem) { + console.warn('Could not find item to move in dragPluginLayout') + return + } // 同一列表中的拖拽 if (from === to) { + // Handle reordering within the same list if (oldIndex < newIndex) { //往后移动 + // When moving an item backward, decrement indices of items in between items.forEach((item) => { if (item !== movedItem && item.align === from && item.index > oldIndex && item.index <= newIndex) { item.index -= 1 } }) } else { //往前移动 + // When moving an item forward, increment indices of items in between items.forEach((item) => { if (item !== movedItem && item.align === from && item.index >= newIndex && item.index < oldIndex) { item.index += 1 } }) } } else { // 跨列表拖拽 + // When moving between lists: + // 1. Decrement indices of items after the moved item in the source list + // 2. Increment indices of items at or after the target position in the destination list items.forEach((item) => { if (item !== movedItem && item.align === from && item.index > oldIndex) { item.index -= 1 } if (item !== movedItem && item.align === to && item.index >= newIndex) { item.index += 1 } }) } // 更新拖拽项的位置 - if (movedItem) { - movedItem.align = to - movedItem.index = newIndex - } + // Update the position of the moved item + movedItem.align = to + movedItem.index = newIndex }
290-293: Consider validating plugin list in initialization function.The
initPluginStorageReactivefunction doesn't validate the structure of the providedpluginList. Adding validation would make this function more robust against invalid input.const initPluginStorageReactive = (pluginList) => { if (Object.keys(pluginStorageReactive.value).length) return + + // Validate that pluginList is an array or object + if (!pluginList || (typeof pluginList !== 'object')) { + console.warn('Invalid plugin list provided to initPluginStorageReactive') + pluginStorageReactive.value = {} + return + } + pluginStorageReactive.value = pluginList }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/layout/src/Main.vue(4 hunks)packages/layout/src/composable/useLayout.js(5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (10)
packages/layout/src/Main.vue (7)
9-14: Improved flexibility with conditional rendering and plugin list integrationThe addition of conditional rendering based on
leftMenuShownStorageand passing the combinedpluginListenhances the component's flexibility. The reference assignment will enable communication between components via the new alignment change methods.
22-28: Consistent pattern applied to right-side componentsGood consistency in applying the same pattern to the right-side components as was done for the left side. The conditional rendering with
v-if="rightMenuShownStorage"aligns with the PR's goal of unified logic for plugin panels.
42-42: Added Vue ref import for component referencesThe import of
reffrom Vue is necessary for the new reactive references that will hold component instances.
66-67: Enhanced state management with useLayout composableGood use of destructuring to access the necessary state variables from
useLayout, including the new storage states that control panel visibility.
84-86: Unified plugin list for consistent managementCreating a combined list of plugins and settings supports the PR's goal of unified logic for plugin panels and enables cross-panel interactions.
120-135: Updated return values with new refs and methodsThe updated return object correctly includes all the new refs, methods, and properties needed for the template.
164-165: Improved right panel layout with flexboxChanging the styling of
.tiny-engine-right-wrapfrom position-based to flexbox aligns with the PR goal of creating a more flexible layout. This will allow for better control of the panel's dimensions and positioning.packages/layout/src/composable/useLayout.js (3)
20-27: Good use of constants for plugin positions.The introduction of the
PLUGIN_POSITIONconstant provides a clean way to reference various plugin positions throughout the code, eliminating magic strings and improving maintainability.
283-288: Good implementation of error handling for changePluginShown.The
changePluginShownfunction now includes validation to check if the plugin exists, which addresses a previous review comment. This prevents runtime errors when toggling visibility for undefined plugins.
295-330: Good export organization.The module exports are well-organized and include all the necessary functions for the flexible layout system. This provides a clear interface for other parts of the application to interact with the layout system.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/layout/src/DesignSettings.vue (1)
315-318: 🛠️ Refactor suggestionDuplicate CSS class definition.
The
.not-selectedclass is defined twice in this file (see also lines 332-334 in past review), potentially causing confusion about which rules apply.Consider consolidating the duplicate definitions:
-.not-selected { - pointer-events: none; - user-select: none; -}And keep only one definition that includes both properties.
🧹 Nitpick comments (12)
packages/common/component/PluginPanel.vue (1)
117-119: Consider making min/max width configurable.The hardcoded min/max width values might not be suitable for all use cases. Consider making these configurable through props to enhance flexibility.
- const MIN_WIDTH = 300 // 固定的最小宽度值 - const MAX_WIDTH = 1000 // 固定的最大宽度值 + const MIN_WIDTH = props.minWidth || 300 // 固定的最小宽度值 + const MAX_WIDTH = props.maxWidth || 1000 // 固定的最大宽度值Also add these to the props definition:
isShowCollapseIcon: { type: Boolean, default: false + }, + /** + * 面板最小宽度 + */ + minWidth: { + type: Number, + default: 300 + }, + /** + * 面板最大宽度 + */ + maxWidth: { + type: Number, + default: 1000 }packages/plugins/block/src/Main.vue (1)
472-472: Adjusted margin styling for better layout.Changed from
margin: 12px 0;tomargin-bottom: 12px;for the.app-manage-typeclass, improving vertical spacing and visual layout.packages/layout/src/composable/useLayout.js (10)
29-31: Consider expanding the pluginState object.The
pluginStatereactive object currently only contains a single property. As you continue to develop the plugin system, consider structuring this object more comprehensively to avoid adding reactive properties later.
48-48: Use English comments throughout the codebase.The comment "右侧面版激活提示状态" is in Chinese. For consistency and to improve readability for all team members, consider using English for all comments.
- activating: false, // 右侧面版激活提示状态 + activating: false, // Right panel activation indicator state
87-96: Consider consolidating panel management functions.The
changeLeftFixedPanelsandchangeRightFixedPanelsfunctions are nearly identical. Consider creating a single utility function to avoid code duplication.-const changeLeftFixedPanels = (pluginName) => { - leftFixedPanelsStorage.value = leftFixedPanelsStorage.value?.includes(pluginName) - ? leftFixedPanelsStorage.value?.filter((item) => item !== pluginName) - : [...leftFixedPanelsStorage.value, pluginName] -} -const changeRightFixedPanels = (pluginName) => { - rightFixedPanelsStorage.value = rightFixedPanelsStorage.value?.includes(pluginName) - ? rightFixedPanelsStorage.value?.filter((item) => item !== pluginName) - : [...rightFixedPanelsStorage.value, pluginName] -} +const togglePanelPlugin = (storage, pluginName) => { + storage.value = storage.value?.includes(pluginName) + ? storage.value?.filter((item) => item !== pluginName) + : [...storage.value, pluginName] +} + +const changeLeftFixedPanels = (pluginName) => { + togglePanelPlugin(leftFixedPanelsStorage, pluginName) +} + +const changeRightFixedPanels = (pluginName) => { + togglePanelPlugin(rightFixedPanelsStorage, pluginName) +}
155-168: Improve error handling for localStorage operations.The current error handling just re-throws the error without providing context. Consider adding more descriptive error messages and possibly falling back to default values instead of throwing.
try { const storedPlugin = localStorage.getItem('plugin') if (storedPlugin) { plugin = JSON.parse(storedPlugin) } } catch (error) { - throw new Error(error) + console.error('Error parsing plugin data from localStorage:', error) + plugin = [] }
172-172: Extract magic numbers to constants.The default width of 300 should be extracted to a named constant at the top of the file for better maintainability.
+const DEFAULT_PLUGIN_WIDTH = 300 + // 获取插件宽度 -const getPluginWidth = (name) => pluginStorageReactive.value[name]?.width || 300 +const getPluginWidth = (name) => pluginStorageReactive.value[name]?.width || DEFAULT_PLUGIN_WIDTH
175-184: Add validation for width parameter.The
changePluginWidthfunction doesn't validate the width parameter, which could lead to unexpected UI issues if negative or extremely large values are provided.// 修改插件宽度 const changePluginWidth = (name, width, offset) => { + // Ensure width is a reasonable value (e.g., between 100 and 800 pixels) + const validWidth = Math.max(100, Math.min(800, width)) + if (Object.prototype.hasOwnProperty.call(pluginStorageReactive.value, name)) { - pluginStorageReactive.value[name].width = width + pluginStorageReactive.value[name].width = validWidth pluginStorageReactive.value[name].offset = offset } else { pluginStorageReactive.value[name] = { - width + width: validWidth } } }
187-187: Add a fallback for invalid layouts.The
getPluginByLayoutfunction returns a default of 'leftTop', but should verify that this is a valid position from your PLUGIN_POSITION constants.-const getPluginByLayout = (name) => pluginStorageReactive.value[name]?.align || 'leftTop' +const getPluginByLayout = (name) => { + const align = pluginStorageReactive.value[name]?.align + return Object.values(PLUGIN_POSITION).includes(align) ? align : PLUGIN_POSITION.leftTop +}
190-199: Optimize the getPluginsByLayout function.The function is well-structured, but could be optimized slightly to avoid redundant sorting when the result is an empty array.
const getPluginsByLayout = (layout = 'all') => { // 筛选出符合布局条件的插件名称 const pluginNames = Object.keys(pluginStorageReactive.value).filter( (key) => pluginStorageReactive.value[key].align === layout || layout === 'all' ) + if (pluginNames.length === 0) return pluginNames; + pluginNames.sort((a, b) => pluginStorageReactive.value[a].index - pluginStorageReactive.value[b].index) return pluginNames }
224-265: Optimize the dragPluginLayout function.The current implementation has multiple iterations over the same items array. Consider consolidating the loops and adding input validation.
- Add validation for from, to, oldIndex, and newIndex parameters
- Consider using a more efficient algorithm that doesn't require multiple iterations
const dragPluginLayout = (from, to, oldIndex, newIndex) => { if (from === to && oldIndex === newIndex) return + // Validate inputs + if (!Object.values(PLUGIN_POSITION).includes(from) || !Object.values(PLUGIN_POSITION).includes(to)) { + console.error('Invalid position values in dragPluginLayout:', { from, to }) + return + } + + if (typeof oldIndex !== 'number' || typeof newIndex !== 'number' || oldIndex < 0 || newIndex < 0) { + console.error('Invalid index values in dragPluginLayout:', { oldIndex, newIndex }) + return + } const items = Object.values(pluginStorageReactive.value) // 记录拖拽项 const movedItem = items.find((item) => item.align === from && item.index === oldIndex) + if (!movedItem) { + console.error('Could not find item to move in dragPluginLayout') + return + } // Same list logic and cross-list logic remain the same...
289-292: Consider adding validation in initPluginStorageReactive.The
initPluginStorageReactivefunction doesn't validate the structure ofpluginListbefore assigning it to storage.const initPluginStorageReactive = (pluginList) => { if (Object.keys(pluginStorageReactive.value).length) return + + // Validate pluginList structure + if (!Array.isArray(pluginList) && typeof pluginList !== 'object') { + console.error('Invalid pluginList format:', pluginList) + return + } + pluginStorageReactive.value = pluginList }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
packages/common/component/PluginPanel.vue(5 hunks)packages/common/package.json(1 hunks)packages/layout/src/DesignPlugins.vue(10 hunks)packages/layout/src/DesignSettings.vue(2 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/plugins/block/src/Main.vue(6 hunks)packages/plugins/bridge/src/Main.vue(4 hunks)packages/plugins/i18n/src/Main.vue(4 hunks)packages/plugins/page/src/Main.vue(4 hunks)packages/plugins/script/src/Main.vue(5 hunks)packages/settings/events/index.js(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/common/package.json
- packages/settings/events/index.js
🔇 Additional comments (60)
packages/common/component/PluginPanel.vue (10)
12-22: Great addition of collapsible functionality with tooltip.The implementation of the collapsible feature with tooltip guidance enhances user experience by providing visual feedback on the action. The conditional rendering based on
isShowCollapseIconprop allows for flexible usage across different panel instances.
23-28: Good implementation of fixed panel functionality.The fixed panel toggle uses conditional rendering based on the
fixedPanelsarray andfixedNameprop, with appropriate tooltip text that changes based on the current state. This provides clear visual indication of panel state to users.
32-34: Good addition of scroll container for content.Wrapping the content slot in a scrollable div with appropriate CSS ensures content overflow is handled properly while maintaining the overall layout structure.
36-37: Excellent implementation of resize handles.The conditional rendering of resize handles based on the panel's alignment (left/right) provides intuitive UI for users to adjust panel width according to their needs.
42-42: Good use of useThrottleFn for performance optimization.Using
useThrottleFnfrom @vueuse/core for throttling mouse move events is an excellent approach to improve performance during resize operations.
84-109: Well-documented props with clear descriptions.The new props are well documented with clear JSDoc comments explaining their purpose, which improves code maintainability and makes it easier for other developers to understand how to use this component.
140-144: Good implementation of resize handlers with boundary checks.The resize handler correctly restricts the panel width within the defined min/max boundaries and updates the width through the layout system. The use of
changePluginWidthensures that the changes are properly propagated to the layout system.
152-153: Excellent use of throttling for mouse move events.Throttling mouse move events is a good practice to prevent performance issues during resize operations. The 50ms throttle interval provides a good balance between responsiveness and performance.
158-164: Proper cleanup of event listeners.The code properly removes event listeners when the resize operation is complete, which prevents memory leaks and ensures clean event handling. Also, it resets the cursor style and removes the dragging class.
278-326: Well-implemented CSS for resize handles.The CSS for the resize handles provides good visual feedback with hover effects and clear indication during dragging. The transition effect provides a smooth user experience.
packages/plugins/script/src/Main.vue (5)
2-29: Clean restructuring using the enhanced PluginPanel component.The template has been nicely refactored to use the enhanced PluginPanel component with proper slot usage for header and content. The structure is clean and follows a consistent pattern with other plugin components.
33-33: Good addition of reactive state management.Adding
reactivefrom Vue's composition API enhances the component's state management capabilities.
55-57: Proper prop definition for fixedPanels.The type is correctly defined as Array, matching the expected type in the PluginPanel component.
66-69: Good use of provide/inject pattern for panel state.Creating a reactive panelState object and providing it to child components establishes a clean communication channel for panel-related events.
129-150: Improved styling with better organization.The CSS has been restructured with proper nesting and semantic class names, making it easier to maintain and understand.
packages/plugins/page/src/Main.vue (5)
2-38: Well-structured template with clear slot usage.The template has been organized clearly with properly named slots for header and content. The buttons and icons in the header are well aligned and properly encapsulated within the header slot.
47-48: Good addition of useLayout import.Adding the useLayout hook provides access to layout-related functionality like PLUGIN_NAME, enhancing the component's integration with the layout system.
79-81: Proper prop definition for fixedPanels.The fixedPanels prop is correctly defined with the Array type, consistent with other components using the same pattern.
83-83: Good explicit emits declaration.Explicitly declaring the 'close' emit enhances the component's API clarity and documentation.
90-94: Well-implemented panel state management.The reactive panelState object with emitEvent method provides a clean way to handle events from the panel.
packages/plugins/i18n/src/Main.vue (4)
2-9: Good integration with the enhanced PluginPanel.The PluginPanel is properly configured with the required props, including fixedName and fixedPanels, maintaining consistency with other plugin components.
123-135: Good organization of imports.The imports are well organized, with Vue-related imports first, followed by component imports and then service imports. Using destructuring for the useLayout import is a clean approach.
156-158: Proper prop definition for fixedPanels.The fixedPanels prop is correctly defined with the Array type, consistent with the implementation in other components.
170-173: Good use of provide/inject pattern.Creating a reactive panelState object and providing it to child components establishes a consistent communication pattern across the application.
packages/plugins/bridge/src/Main.vue (6)
2-7: Looks good - New plugin panel props added.The addition of
:fixed-name="PLUGIN_NAME.Bridge"and:fixedPanels="fixedPanels"props enhances the plugin panel's configurability, aligning with the PR's goal to implement flexible layout for the plugin panel.
20-22: Added reactive and layout utilities for flexible plugin management.The addition of
reactiveandprovideimports, along with theuseLayouthook, enables reactive state management for the plugin panel's positioning and visibility.
35-39: Good - Added fixedPanels prop.Adding the
fixedPanelsprop allows this component to receive information about which panels should be fixed in the layout, supporting the flexible positioning feature.
40-45: Appropriate setup function update.The setup function now properly accepts props and emit, and retrieves the PLUGIN_NAME constant from useLayout, enabling consistent plugin identification across the application.
47-50: Effective state management with provide/inject pattern.Creating a reactive panelState object and providing it to child components establishes a clean communication channel for the panel's state.
65-65: Added PLUGIN_NAME to return value.Exposing PLUGIN_NAME to the template enables proper identification of the plugin in the flexible layout system.
packages/plugins/block/src/Main.vue (5)
1-10: Good restructuring of plugin-panel with flexible layout props.The plugin-panel component has been enhanced with
:fixed-name="PLUGIN_NAME.BlockManage"and:fixedPanels="fixedPanels"props, properly implementing the flexible layout system from the PR objectives.
219-223: Added fixedPanels prop for dynamic panel management.Adding the
fixedPanelsprop allows this component to receive and utilize information about which panels should maintain fixed positions in the layout.
273-280: State management with provide/inject pattern implemented.The addition of the reactive panelState object and providing it to child components establishes a clean communication channel for the panel's state, consistent with the implementation in other plugin components.
318-321: Proper event emission on close.Adding
emit('close')in the close function ensures parent components are properly notified when the panel is closed, maintaining component communication integrity.
436-436: Added PLUGIN_NAME to return value.Exposing PLUGIN_NAME to the template enables proper identification of the plugin in the flexible layout system, consistent with other plugin implementations.
packages/layout/src/DesignPlugins.vue (10)
3-9: Implemented draggable navigation with vue-draggable-next.Replaced static lists with draggable components, enabling users to reposition plugins via drag-and-drop as specified in the PR objectives.
23-24: Added context menu support for flexible plugin management.The
@contextmenu.preventhandler enables right-click menu functionality for plugins, supporting the requirement to control plugin visibility and position through a right-click menu.
39-49: Added draggable functionality to bottom navigation.The bottom navigation list now also implements draggable functionality using vue-draggable-next, completing the flexible layout implementation for all plugin positions.
69-87: Implemented panel visibility toggling with drag state awareness.The
:class="{ 'not-selected': getMoveDragBarState() }"binding disables interaction with panels during drag operations, providing better user experience during layout adjustments.
90-95: Added plugin context menu component.The integration of the
plugin-right-menucomponent provides a unified interface for plugin management actions, supporting the PR objective of controlling plugin visibility and position.
124-172: Implemented changeAlign with proper deduplication.The
changeAlignfunction now correctly checks for and removes existing items before adding to the target list, preventing duplicates when changing plugin alignment.
223-238: Implemented panel switching with proper cleanup.The
switchAlignmethod handles transitioning a plugin between different panel positions, including necessary cleanup and event emissions to maintain layout integrity.
269-272: Added drag event handling for layout updates.The
onEndmethod properly processes the completion of drag events, ensuring the layout updates correctly after repositioning plugins.
299-299: Responsive panel width with auto setting.Setting
width: auto !important;for the left panel allows it to adjust based on content, supporting the requirement to make the panel width adjustable.
422-425: Added utility class for drag operations.The
.not-selectedclass disables pointer events and user selection during drag operations, providing better visual feedback and preventing unintended interactions.packages/layout/src/DesignSettings.vue (8)
3-19: Implemented flexible panel structure with fixed panel support.The right panel implementation now supports dynamic rendering and fixed positioning based on the renderPanel prop and rightFixedPanelsStorage state, fulfilling the PR objective for consistent floating and fixed panel logic.
20-37: Implemented draggable navigation for right panel.Replaced static navigation with vue-draggable-next component, supporting the PR's goal of allowing users to reposition plugins via dragging.
39-44: Added plugin context menu for right panel.The plugin-right-menu component integration enables right-click management of plugins in the right panel, consistent with the implementation in DesignPlugins.vue.
93-99: Implemented context menu handling.The showContextMenu method properly handles different context menu scenarios based on event type and position, enhancing user interaction options.
117-122: Implemented cross-panel plugin movement.The switchAlign method handles moving plugins between panels with proper cleanup, ensuring consistent state across the application.
124-132: Implemented changeAlign with proper deduplication.Similar to DesignPlugins.vue, this function correctly prevents duplicates when changing plugin alignment by checking and removing existing items before adding.
139-145: Implemented toggle behavior for plugin panels.The clickMenu method properly handles toggling panel visibility when clicking an already active plugin, improving user experience.
157-160: Added drag event handling with proper cleanup.The onEnd method properly handles drag completion, including closing panels when appropriate and updating layout state.
packages/layout/src/composable/useLayout.js (7)
14-14: Nice addition of useStorage for persistent state.Using
useStoragefrom@vueuse/coreis a good choice for maintaining state persistence across page reloads, which is essential for remembering user layout preferences.
20-27: Well-structured plugin position constants.Good job defining a clear enum-like object for plugin positions. This makes the code more maintainable and prevents magic strings across the codebase.
64-69: Good implementation of drag bar state management.The functions for getting and changing the drag bar state are simple and focused, following good practices for state management.
70-83: Well-designed menu visibility toggle.The implementation effectively uses persistent storage and provides a clean API for toggling menu visibility. The switch statement is easy to extend if more menu positions are added in the future.
122-127: Good implementation of conditional setting closure.The
closeSettingfunction properly handles closure conditions based on whether the setting is fixed or needs to be force-closed.
282-287: Good job adding error handling to changePluginShown.You've added proper error handling to ensure that the plugin exists before toggling its visibility, which helps prevent runtime errors.
294-329: Well-organized exports with comprehensive functionality.The exported object provides a complete and organized API for layout management, including all the new flexible layout capabilities. The function names are descriptive and follow a consistent pattern.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/layout/src/composable/useLayout.js (1)
225-266: Comprehensive implementation of drag-and-drop functionality.The
dragPluginLayoutfunction handles all possible drag scenarios, including same-list and cross-list dragging, with proper index adjustments. The logic is complex but thorough.Consider adding more inline comments to document the different scenarios being handled, which would make this complex function easier to maintain in the future.
const dragPluginLayout = (from, to, oldIndex, newIndex) => { if (from === to && oldIndex === newIndex) return const items = Object.values(pluginStorageReactive.value) - // 记录拖拽项 + // Record the dragged item const movedItem = items.find((item) => item.align === from && item.index === oldIndex) - // 同一列表中的拖拽 + // Handle drag within the same list if (from === to) { if (oldIndex < newIndex) { - //往后移动 + // Moving backward: decrement indices of items between old and new position items.forEach((item) => { if (item !== movedItem && item.align === from && item.index > oldIndex && item.index <= newIndex) { item.index -= 1 } }) } else { - //往前移动 + // Moving forward: increment indices of items between new and old position items.forEach((item) => { if (item !== movedItem && item.align === from && item.index >= newIndex && item.index < oldIndex) { item.index += 1 } }) } } else { - // 跨列表拖拽 + // Handle drag between different lists + // 1. Decrement indices of items after the old position in source list items.forEach((item) => { if (item !== movedItem && item.align === from && item.index > oldIndex) { item.index -= 1 } + // 2. Increment indices of items at or after the new position in target list if (item !== movedItem && item.align === to && item.index >= newIndex) { item.index += 1 } }) } - // 更新拖拽项的位置 + // Update the position of the dragged item if (movedItem) { movedItem.align = to movedItem.index = newIndex } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/canvas/container/src/components/CanvasResize.vue(1 hunks)packages/layout/src/DesignPlugins.vue(9 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/utils/src/constants/index.js(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
packages/utils/src/constants/index.js (1)
Learnt from: rhlin
PR: opentiny/tiny-engine#1011
File: packages/utils/src/constants/index.js:101-101
Timestamp: 2025-03-13T02:41:34.105Z
Learning: The `CANVAS_ROUTER_VIEW_SETTING_VIEW_MODE_KEY` constant in `packages/utils/src/constants/index.js` intentionally omits CHANNEL_UID to maintain a single localStorage entry that can be restored across different instances of the designer.
🧬 Code Definitions (1)
packages/layout/src/composable/useLayout.js (1)
packages/utils/src/constants/index.js (4) (4)
STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (18)
packages/utils/src/constants/index.js (1)
100-101: Clean addition of panel storage constants.These new constants follow the same pattern as
CANVAS_ROUTER_VIEW_SETTING_VIEW_MODE_KEYby intentionally omitting the CHANNEL_UID, ensuring that panel configurations persist consistently across different designer instances.packages/canvas/container/src/components/CanvasResize.vue (1)
109-121: Well-implemented watchers for right panel layout changes.These watchers provide consistent behavior for right panel layout changes, matching the existing pattern used for left panel changes. The use of
flush: 'post'ensures these run after DOM updates, which is appropriate for scale adjustments.packages/layout/src/DesignPlugins.vue (8)
4-37: Good implementation of draggable plugin navigation.Replacing the static list with
vue-draggable-nextsignificantly improves the user experience by enabling fluid drag-and-drop functionality for plugins, which aligns with the PR's objective of implementing a flexible layout.
39-66: Well-structured bottom navigation area with drag support.The implementation maintains consistency with the top navigation area while adding proper context menu handling and drag-and-drop support for the bottom section.
69-88: Appropriate use of pointer-events control during drag operations.The
.not-selectedclass wrapper prevents interaction with the panel whengetMoveDragBarState()returns true, which is a good approach to avoid unintended interactions during drag operations.
90-95: Effective implementation of context menu component.The
PluginRightMenucomponent consolidates context menu functionality, improving code organization and reusability while enabling the new alignment features described in the PR objectives.
155-170: Properly implemented state management for plugin lists.The reactive state properly initializes the plugin lists based on position, and the
changeAlignfunction now correctly checks for and removes existing items before adding them to a new list, which addresses a concern from a previous review.
226-236: Well-implemented alignment switching logic.The
switchAlignmethod handles panel repositioning effectively, with proper cleanup of the source list and appropriate API calls. It also appropriately closes panels when switching between sides.
242-246: Good implementation of drag end handler.The
onEndmethod properly updates plugin layout after drag operations complete, with appropriate handling of same-side vs. cross-side drag scenarios.
397-400: Effective utility class for preventing interactions.The
.not-selectedclass provides a clean way to disable pointer events and user selection when needed, which is particularly useful during drag operations.packages/layout/src/composable/useLayout.js (8)
20-27: Well-defined position constants for flexible layout management.The
PLUGIN_POSITIONconstant provides a clear enumeration of all possible plugin positions, which supports the flexible layout objectives of the PR.
64-69: Good implementation of drag bar state management.The getter and setter functions for the drag bar state provide a clean API for controlling the interactive state of the UI during drag operations.
70-83: Clean implementation of menu visibility toggling.The use of
useStoragefor persisting menu visibility state across sessions is a good approach, and thechangeMenuShownfunction provides a simple API for toggling visibility.
84-96: Well-implemented panel fixation state management.The functions leverage the newly added storage constants and provide a clean API for toggling fixed states of panels. The implementation correctly handles both adding and removing panels from the fixed state.
172-185: Robust plugin width management functions.The implementation properly handles both existing and new plugins, ensuring that width and offset values are correctly stored and retrieved.
187-208: Clean functions for plugin position and layout management.These utility functions provide a foundation for the flexible layout system, making it easy to retrieve plugins by position, layout, or ID.
268-277: Good utility function for side determination.The
isSameSidefunction provides a clean way to determine if two positions are on the same side of the layout, which is useful for handling cross-side drag operations.
283-288: Properly fixed plugin visibility toggle function.The
changePluginShownfunction now includes proper initialization for non-existent plugins, addressing the concern raised in a previous review.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (15)
packages/plugins/script/src/Main.vue (1)
165-165: Removed unnecessary empty line.The empty line after the closing bracket is unnecessary but doesn't affect functionality.
} - :deep(.help-box) {packages/common/component/PluginSetting.vue (2)
104-111: New props enhance component flexibilityThe new
fixedNameandalignprops enhance the component's flexibility and reusability across different contexts.Consider adding more descriptive JSDoc comments for these new props to better document their purpose and accepted values, similar to the existing props.
119-131: Well-structured computed properties for dynamic layoutThe computed properties logically break down the positioning calculations, making the code more maintainable. The
firstPanelOffsetprovides the initial panel width,secondPanelAligndetermines direction, andalignStylecombines them for positioning.Consider renaming
firstPanelOffsetto something more descriptive likefirstPanelWidthsince it represents width rather than an offset.packages/common/styles/vars.less (1)
31-32: Consider referencing an existing theming variable to maintain consistency.The new
--te-component-common-resizer-border-colorvariable introduces a static hex color. If you already have a theming system or brand color reference, referencing that might help keep the styles consistent and maintainable.packages/plugins/schema/src/Main.vue (2)
76-80: UsingpanelStatewithprovideis a practical approach.This approach helps sibling or child components to seamlessly interact with the panel. Ensure there are no reactivity pitfalls or watchers needed if the state changes externally.
188-218: Scoped styling updates.You’ve introduced styling for the
.icon-wrapclass and the.source-code-contentcontainer. These changes appear consistent with your new layout. However, verify that relying onheight: calc(100% - 12px)does not break in smaller screens or alternate usage contexts. A potential fallback or media query may be needed for responsiveness.packages/common/component/PluginRightMenu.vue (4)
24-50: Review alignment logic in props.The
alignprop defaults to'left', but the usage includesalign.includes('right'). This is valid, yet consider normalizing this prop to an enum-like approach ('left' | 'right') for clarity. Right now, string containment checks can be prone to edge cases if used incorrectly in the future.
52-80: Check potential offset issues inshowContextMenu.The code calculates
contextMenu.x = x - contextMenuWidth, which may cause negative values ifxis near the viewport’s left edge. Consider adding boundary checks so the menu displays properly even at the edges.
112-116: Click-outside approach is good.Using
closest('.plugin-context-menu')to detect outside clicks is straightforward, but watch out for integrations with frameworks that might dynamically change the DOM or introduce shadow roots.
139-180: Basic styling for the context menu.The styling is minimalistic and likely meets the immediate design requirements. If theming is essential, maybe unify the border and background with other palette variables (like
--te-component-common-border-color).packages/layout/src/DesignPlugins.vue (2)
4-36: Use a stable key in your v-for loop.Currently, the code uses the loop index as the key (
:key="index"). This can cause potential re-render issues if the array is reordered. Consider usingitem.idor another unique attribute instead:- <div v-for="(item, index) in state.topNavLists" :key="index"> + <div v-for="item in state.topNavLists" :key="item.id">
276-277: Avoid!important;if possible.Line 276 uses
width: auto !important;. While it’s sometimes necessary, see if a higher CSS specificity can achieve the same result. Overuse of!importantmay complicate future styling.packages/layout/src/DesignSettings.vue (1)
3-45: Use stable keys in the v-for loop for settingPlugins.Similar to the left panel, using
:key="item.id"instead of:key="index"leads to more predictable rendering when dragging or reordering plugins.packages/common/component/PluginPanel.vue (1)
44-221: Consider removing listeners on unmount to prevent leaks.If the user navigates away while dragging (before
mouseup), the document listeners might remain attached. As a precaution, consider removing them inonBeforeUnmountif still active, preventing potential memory leaks.packages/layout/src/composable/useLayout.js (1)
236-275: Ensure movedItem always exists in dragPluginLayout.
movedItemis found by matchingalign === from && index === oldIndex. If not found, the function silently does nothing. If that’s intentional, that’s fine, but confirm you aren’t missing an error log or fallback.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
packages/design-core/assets/display-inline.svgis excluded by!**/*.svgpackages/design-core/assets/form.svgis excluded by!**/*.svgpackages/design-core/assets/target.svgis excluded by!**/*.svg
📒 Files selected for processing (16)
packages/canvas/DesignCanvas/src/DesignCanvas.vue(5 hunks)packages/canvas/container/src/components/CanvasResize.vue(2 hunks)packages/common/component/PluginPanel.vue(5 hunks)packages/common/component/PluginRightMenu.vue(1 hunks)packages/common/component/PluginSetting.vue(9 hunks)packages/common/styles/vars.less(1 hunks)packages/layout/src/DesignPlugins.vue(9 hunks)packages/layout/src/DesignSettings.vue(2 hunks)packages/layout/src/Main.vue(4 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/plugins/schema/src/Main.vue(5 hunks)packages/plugins/script/src/Main.vue(5 hunks)packages/plugins/tree/src/Main.vue(3 hunks)packages/settings/props/src/Main.vue(1 hunks)packages/settings/styles/src/Main.vue(7 hunks)packages/utils/src/constants/index.js(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- packages/canvas/container/src/components/CanvasResize.vue
- packages/plugins/tree/src/Main.vue
- packages/canvas/DesignCanvas/src/DesignCanvas.vue
- packages/settings/styles/src/Main.vue
- packages/layout/src/Main.vue
- packages/settings/props/src/Main.vue
🧰 Additional context used
🧠 Learnings (1)
packages/utils/src/constants/index.js (1)
Learnt from: rhlin
PR: opentiny/tiny-engine#1011
File: packages/utils/src/constants/index.js:101-101
Timestamp: 2025-03-13T02:41:34.105Z
Learning: The `CANVAS_ROUTER_VIEW_SETTING_VIEW_MODE_KEY` constant in `packages/utils/src/constants/index.js` intentionally omits CHANNEL_UID to maintain a single localStorage entry that can be restored across different instances of the designer.
🧬 Code Definitions (1)
packages/layout/src/composable/useLayout.js (1)
packages/utils/src/constants/index.js (6) (6)
STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)PLUGIN_DEFAULT_WIDTH(168-168)PLUGIN_DEFAULT_WIDTH(168-168)
🔇 Additional comments (37)
packages/plugins/script/src/Main.vue (10)
2-11: The new plugin-panel component structure improves layout flexibility.The replacement of the custom div structure with a reusable
plugin-panelcomponent aligns well with the PR's objective to introduce a unified flexible layout system. The addition of properties like:fixed-name,:fixedPanels, and:draggable-enabled="true"enables the panel to participate in the new drag-and-resize functionality.
12-17: Clean implementation of change indicator and save button.The header slot's implementation with the change indicator dot and save button provides good visual feedback to users about unsaved changes, enhancing the UX.
18-29: Content structure preserved correctly.The monaco editor implementation has been properly moved to the content slot while maintaining all its functionality, ensuring a seamless transition to the new layout system.
34-37: Good enhancement of reactive capabilities.The addition of
reactiveandprovideimports from Vue, along with the updated imports for common components, supports the component's enhanced state management approach.
52-54: Proper component registration.The PluginPanel component is correctly registered, allowing it to be used in the template.
55-59: Added support for fixed panels configuration.The new
fixedPanelsprop enables the component to participate in the panel management system, consistent with other components in the PR.
65-70: Effective implementation of shared panel state.The addition of
PLUGIN_NAMEfromuseLayout()and the reactivepanelStatethat's provided to the component context supports the flexible layout system by enabling consistent plugin identification and state sharing between components.
111-111: Good exposure of PLUGIN_NAME to template.Making PLUGIN_NAME available in the template ensures consistency in plugin identification throughout the component.
130-152: Well-styled change indicator and save button.The styling for the change indicator and save button is clean and effective, providing good visual feedback when changes are made.
154-157: Appropriate content padding adjustments.The padding and height calculations for the code editor content have been updated to fit well within the new panel structure.
packages/common/component/PluginSetting.vue (6)
3-11: Enhanced template structure with improved dynamic classes and stylingThe template has been improved with a proper ID and dynamic class/style bindings that support the new flexible layout functionality. This approach allows for cleaner styling based on alignment direction.
Adding the ID also makes DOM selection more reliable for external components that might need to reference this element.
42-47: Good addition of necessary imports for the new functionalityAdding
computed,nextTickand theuseLayoutcomposable from the meta-register aligns well with the PR objectives of implementing a flexible layout for the plugin panel.
133-139: Avoid direct DOM queries inwatchEffectRelying on
document.querySelectormight cause timing issues in complex UIs. Using a template ref for.second-panelor a reactive approach can reduce risk and simplify testing.Consider refactoring to use template refs:
-watchEffect(() => { - // 处理二级面板偏移量 - const secondPanelOffset = document.querySelector('.plugin-setting')?.clientWidth + firstPanelOffset.value - nextTick(() => { - document.querySelector('.second-panel')?.style.setProperty(secondPanelAlign.value, `${secondPanelOffset}px`) - }) -}) +// Add refs in the template +<div + id="panel-setting" + ref="pluginSettingRef" + :class="..." + :style="alignStyle" +> + +// In setup +const pluginSettingRef = ref(null) +const secondPanelRef = ref(null) + +watchEffect(() => { + // Only execute if both refs are available + if (pluginSettingRef.value && secondPanelRef.value) { + const secondPanelOffset = pluginSettingRef.value.clientWidth + firstPanelOffset.value + nextTick(() => { + secondPanelRef.value.style.setProperty(secondPanelAlign.value, `${secondPanelOffset}px`) + }) + } +})
154-158: Good use of computed property for dynamic shadow classThe
shadowClasscomputed property elegantly determines the appropriate shadow class based on component props, making the template cleaner and the logic more centralized.
184-192: Good visual enhancement with directional shadowsThe shadow classes provide visual depth that changes based on the panel's position, enhancing the UI's visual hierarchy. This aligns well with the PR's goal of improving the plugin panel's visual experience.
256-258: Simple but effective right alignment styleThe
.align-rightclass provides a clean way to position the panel on the right side of the screen. This is a key component for the flexible layout functionality mentioned in the PR objectives.packages/utils/src/constants/index.js (2)
167-168: Validate naming and usage ofPLUGIN_DEFAULT_WIDTH.Adding
PLUGIN_DEFAULT_WIDTHis a clear improvement for maintainability. Please place it in relevant usage contexts (e.g., plugin panel sizing) and confirm that no conflicting hardcoded widths remain in the codebase.
100-102:Details
✅ Verification successful
Confirm consistent usage of new storage keys.
The new constants
STORAGE_KEY_LEFT_FIXED_PANELSandSTORAGE_KEY_RIGHT_FIXED_PANELSreplace a more generic single key. Ensure all references in the codebase are updated and tested to prevent leftover references to the old key.Run this script to verify references:
🏁 Script executed:
#!/bin/bash rg --context 3 'STORAGE_KEY_(LEFT|RIGHT)_FIXED_PANELS'Length of output: 2053
Storage Keys Usage Confirmed
The regex search confirms that bothSTORAGE_KEY_LEFT_FIXED_PANELSandSTORAGE_KEY_RIGHT_FIXED_PANELSare consistently used in the codebase. They appear inpackages/utils/src/constants/index.jsand inpackages/layout/src/composable/useLayout.jswith no remnants of the old storage key. Please proceed with comprehensive testing to ensure that all functionality relying on these keys operates as expected.packages/plugins/schema/src/Main.vue (3)
2-41: Verify that<plugin-panel>is properly replacing any prior container logic.The introduction of
<plugin-panel>to wrap content is a good improvement for consistent layout. Double-check other parts of the application (if any) that formerly controlled container height, drag behavior, or header structure so you don’t accidentally duplicate or conflict with this new approach.
44-46: Imports look good.Importing
PluginPanelfrom@opentiny/tiny-engine-commonaligns with the new usage. No immediate concerns here.
62-66: Prop definition forfixedPanelsis clear.Passing this array into
<plugin-panel>is consistent with the changes made inconstants/index.jsfor left and right fixed panels. Good job on decoupling logic from design.packages/common/component/PluginRightMenu.vue (3)
2-22: Double-checkv-if="false"usage.The entire list is wrapped in
v-if="false", which effectively prevents rendering. If this is intentional (e.g., toggled at runtime) and replaced by other logic, clarify or remove it. Otherwise, this might be a placeholder code leftover.
82-98: Ensure consistent naming forhideContextMenu,hidePlugin, andswitchAlign.These methods are well-defined and handle user interactions. Just be sure that transitions (e.g., animations) or other visual cues finish before reflow triggers if you plan to extend the UI.
100-110: Conditional usage inhideSidebar.Reusing the
changeMenuShownmethod for toggling sidebars is suitable. Confirm anywhere else in the code that depends on the previous approach of toggling the sidebar. Potential race conditions or mismatch states can occur if used simultaneously in multiple components.packages/layout/src/DesignPlugins.vue (4)
38-66: Similarly use stable keys when iterating bottomNavLists.Same rationale as the topNavLists. Using
item.idas the key will help keep list item states consistent when items are shuffled or re-sorted.
69-95: Looks good!The usage of
<plugin-right-menu>withref="rightMenu"for context menus is well-structured, and the event-based communication appears clean and maintainable.
99-108: Double-check alignment switching logic to avoid duplicates.Methods like
switchAlignsplice the plugin from one list and then emit an event to change alignment. Confirm that if the same plugin already exists in the destination list, it gets cleaned up to prevent duplicates.Also applies to: 114-185
399-402: Consolidate repeated.not-selecteddefinitions.A previous review comment suggested merging or reusing this
.not-selectedstyle across files to avoid duplication or confusion.packages/layout/src/DesignSettings.vue (3)
48-60: Import statements look good.No issues found with import references or version constraints.
62-185: Verify plugin removal when switching sides.The functions
switchAlignandchangeAligneffectively splice items when moving them. Please ensure that the plugin cannot remain in both arrays if it was already on the target side, preventing duplicates.
191-318: Unify.not-selectedstyle definitions.As highlighted in prior reviews,
.not-selectedis defined more than once in different files. Consolidating it helps reduce confusion and ensure consistent styling.packages/common/component/PluginPanel.vue (2)
2-39: Conditional draggable sections look fine.Enabling or disabling the drag behavior via
v-if="draggableEnabled"is a neat approach, and the two resizer divs are cleanly separated for left and right usage.
291-344: Styling changes provide clear visual feedback.The resizer effect, including hover transitions and the
.draggingclass, is an excellent UX touch. No concerns here.packages/layout/src/composable/useLayout.js (4)
14-35: New constants and reactive objects are well-organized.Defining
PLUGIN_POSITIONandpluginStatein one place improves maintainability, and the naming is appropriately descriptive.
84-96: Left/right fixed panels logic is clear.The toggling logic for
changeLeftFixedPanelsandchangeRightFixedPanelsis straightforward, using storage and array operations. Looks good.
128-130: Check ifrendermight be null or undefined.When computing
leftPanelFixedorrightPanelFixed, confirm thatlayoutState.plugins.renderorlayoutState.settings.renderis always defined. Otherwise,.includes(undefined)can fail.
298-303: Initialization logic is functional.
initPluginStorageReactiveandgetPluginsByPositionare well designed. They simplify integration by decoupling plugin storage from the rest of the code. Good approach.Also applies to: 341-341
…n bar right-click menu
4fd4959 to
bdc039f
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (8)
packages/plugins/script/src/Main.vue (4)
13-17: Good visual feedback for unsaved changesThe addition of a red indicator dot for unsaved changes provides important visual feedback to users. However, consider adding a tooltip to explicitly communicate its meaning.
- <i v-show="state.isChanged" class="red"></i> + <i v-show="state.isChanged" class="red" title="有未保存的更改"></i>
55-58: Improve prop definition with default value and validationThe
fixedPanelsprop would benefit from a default value and more specific type validation to prevent potential runtime errors.fixedPanels: { type: Array, + default: () => [], + validator: (value) => Array.isArray(value) }
67-70: Document the purpose of the provided stateThe reactive
panelStateis provided to child components, but its purpose and consumption pattern aren't clear. Consider adding a comment explaining how this state is used by child components.// Create reactive panel state for child components const panelState = reactive({ emitEvent: emit }) + // This state is consumed by child components to access the emit function provide('panelState', panelState)
167-169: Consider using CSS variables for consistencyFor better maintainability, consider using CSS variables for spacing values like padding and margins.
.code-edit-content { - padding: 0 12px; + padding: 0 var(--te-spacing-s, 12px); height: calc(100% - 12px); }packages/plugins/block/src/Main.vue (1)
472-473: Margin adjustment improves spacingChanging from
margin: 12px 0tomargin-bottom: 12pxremoves the top margin, which likely creates a more consistent spacing in the panel's layout.packages/plugins/state/src/Main.vue (1)
513-514: Improved tab header paddingThe update to the tab header padding ensures consistent spacing around the tabs, improving the overall appearance of the plugin panel.
packages/layout/src/DesignSettings.vue (1)
20-36: Well-structured draggable navigation panel.The navigation panel with drag-and-drop functionality is nicely implemented. The context menu integration is properly handled with the
@contextmenu.preventdirective.Consider using unique IDs instead of array indices as keys for the
v-forloop to ensure proper component reconciliation when items are reordered:- :key="index" + :key="item.id"packages/layout/src/composable/useLayout.js (1)
164-178: Improve error handling in plugin storage initialization.The current implementation throws the error directly, which might cause the application to crash. Consider logging the error and providing a fallback instead.
try { const storedPlugin = localStorage.getItem('plugin') if (storedPlugin) { plugin = JSON.parse(storedPlugin) } } catch (error) { - throw new Error(error) + console.error('Failed to parse plugin storage:', error) + // Fallback to empty array already happens below }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
packages/design-core/assets/display-inline.svgis excluded by!**/*.svgpackages/design-core/assets/form.svgis excluded by!**/*.svgpackages/design-core/assets/target.svgis excluded by!**/*.svg
📒 Files selected for processing (58)
packages/canvas/DesignCanvas/src/DesignCanvas.vue(5 hunks)packages/canvas/container/src/components/CanvasResize.vue(2 hunks)packages/common/component/PluginPanel.vue(5 hunks)packages/common/component/PluginRightMenu.vue(1 hunks)packages/common/component/PluginSetting.vue(9 hunks)packages/common/component/index.js(1 hunks)packages/common/package.json(1 hunks)packages/common/styles/vars.less(1 hunks)packages/configurator/package.json(1 hunks)packages/layout/package.json(1 hunks)packages/layout/src/DesignPlugins.vue(9 hunks)packages/layout/src/DesignSettings.vue(2 hunks)packages/layout/src/Main.vue(4 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/plugins/block/meta.js(1 hunks)packages/plugins/block/src/BlockSetting.vue(4 hunks)packages/plugins/block/src/Main.vue(6 hunks)packages/plugins/bridge/meta.js(1 hunks)packages/plugins/bridge/src/BridgeSetting.vue(4 hunks)packages/plugins/bridge/src/Main.vue(4 hunks)packages/plugins/datasource/meta.js(1 hunks)packages/plugins/datasource/src/DataSourceForm.vue(6 hunks)packages/plugins/datasource/src/DataSourceGlobalDataHandler.vue(3 hunks)packages/plugins/datasource/src/DataSourceRecordList.vue(3 hunks)packages/plugins/datasource/src/DataSourceRemotePanel.vue(5 hunks)packages/plugins/datasource/src/Main.vue(5 hunks)packages/plugins/help/meta.ts(1 hunks)packages/plugins/help/src/HelpIcon.vue(1 hunks)packages/plugins/i18n/meta.js(1 hunks)packages/plugins/i18n/src/Main.vue(4 hunks)packages/plugins/materials/meta.js(1 hunks)packages/plugins/materials/src/meta/block/src/BlockGroupPanel.vue(4 hunks)packages/plugins/materials/src/meta/layout/src/Main.vue(3 hunks)packages/plugins/page/meta.js(1 hunks)packages/plugins/page/src/Main.vue(5 hunks)packages/plugins/page/src/PageFolderSetting.vue(4 hunks)packages/plugins/page/src/PageSetting.vue(4 hunks)packages/plugins/robot/meta.js(1 hunks)packages/plugins/schema/meta.js(1 hunks)packages/plugins/schema/src/Main.vue(5 hunks)packages/plugins/script/meta.js(1 hunks)packages/plugins/script/src/Main.vue(5 hunks)packages/plugins/state/meta.js(1 hunks)packages/plugins/state/src/Main.vue(5 hunks)packages/plugins/tree/meta.js(1 hunks)packages/plugins/tree/src/Main.vue(4 hunks)packages/plugins/tutorial/meta.js(1 hunks)packages/register/src/common.js(2 hunks)packages/settings/events/index.js(1 hunks)packages/settings/events/meta.js(1 hunks)packages/settings/events/src/Main.vue(1 hunks)packages/settings/props/meta.js(1 hunks)packages/settings/props/src/Main.vue(1 hunks)packages/settings/styles/meta.js(1 hunks)packages/settings/styles/src/Main.vue(7 hunks)packages/theme/base/src/page/base-config-page.less(1 hunks)packages/toolbars/themeSwitch/src/Main.vue(1 hunks)packages/utils/src/constants/index.js(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (38)
- packages/plugins/state/meta.js
- packages/plugins/tutorial/meta.js
- packages/plugins/block/meta.js
- packages/common/package.json
- packages/common/styles/vars.less
- packages/plugins/datasource/meta.js
- packages/plugins/robot/meta.js
- packages/utils/src/constants/index.js
- packages/configurator/package.json
- packages/plugins/help/src/HelpIcon.vue
- packages/plugins/page/meta.js
- packages/plugins/bridge/meta.js
- packages/settings/events/meta.js
- packages/register/src/common.js
- packages/common/component/index.js
- packages/plugins/schema/meta.js
- packages/toolbars/themeSwitch/src/Main.vue
- packages/plugins/help/meta.ts
- packages/plugins/materials/meta.js
- packages/plugins/page/src/PageFolderSetting.vue
- packages/plugins/i18n/meta.js
- packages/plugins/script/meta.js
- packages/canvas/container/src/components/CanvasResize.vue
- packages/layout/package.json
- packages/theme/base/src/page/base-config-page.less
- packages/plugins/datasource/src/DataSourceRecordList.vue
- packages/settings/props/meta.js
- packages/settings/events/index.js
- packages/plugins/datasource/src/DataSourceForm.vue
- packages/plugins/bridge/src/BridgeSetting.vue
- packages/plugins/datasource/src/Main.vue
- packages/settings/styles/src/Main.vue
- packages/plugins/tree/meta.js
- packages/plugins/page/src/Main.vue
- packages/common/component/PluginRightMenu.vue
- packages/plugins/materials/src/meta/block/src/BlockGroupPanel.vue
- packages/settings/styles/meta.js
- packages/plugins/datasource/src/DataSourceRemotePanel.vue
🧰 Additional context used
🧬 Code Definitions (1)
packages/layout/src/composable/useLayout.js (1)
packages/utils/src/constants/index.js (6) (6)
STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)PLUGIN_DEFAULT_WIDTH(168-168)PLUGIN_DEFAULT_WIDTH(168-168)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (101)
packages/plugins/script/src/Main.vue (3)
2-11: The new PluginPanel implementation improves layout flexibilityThe switch to a structured
<plugin-panel>component with key props likefixed-name,fixedPanels, anddraggable-enabledaligns well with the PR's goal of creating a flexible layout for plugins. This encapsulation enables the drag functionality and unified fixed/floating logic mentioned in the PR objectives.
34-37: Appropriate Vue composition API usageThe addition of
reactiveandprovidefrom Vue, along with the new imports for layout utilities, follows good practices for component state management in the Vue composition API.
142-164: Well-structured UI elements for visual feedbackThe styling for the icon wrap, save button, and indicator dot is well-implemented. The absolute positioning of the red dot provides a clean visual indicator without disrupting the layout.
packages/settings/events/src/Main.vue (5)
2-19: Good implementation of the plugin-panel componentThe code has been restructured to wrap the existing
<tiny-collapse>component within a new<plugin-panel>component. This implementation supports the PR's objective of creating a flexible layout for the plugin panel.The configuration properties like
title,fixed-panels,fixed-name, and event handling look correct.
23-28: Appropriate imports added for the new structureThe additional imports support the new component structure properly. Adding
reactive,provide,defineProps,defineEmitsfrom Vue along with the engine-specific imports is necessary for the plugin panel enhancements.
31-31: Good usage of layout constantsExtracting
PLUGIN_NAMEfromuseLayout()is a clean approach for maintaining consistent naming conventions across the plugin system.
33-35: Props definition looks goodDefining the
fixedPanelsprop correctly to receive an array of fixed panel configurations.
39-43: Well-structured state management with provide/inject patternThe reactive state object with the emit function is properly provided to child components. This pattern allows for clean communication between parent and child components in the plugin system.
packages/settings/props/src/Main.vue (6)
2-18: Good implementation of the plugin-panel wrapperThe code correctly wraps the existing content with the new
<plugin-panel>component. The configuration properties are consistent with the implementation in other files and support the PR's objective of creating a unified plugin panel layout system.
22-24: Appropriate imports for the new component structureThe modified imports add necessary functionality for the new component structure. Adding
reactiveandprovidefrom Vue and importingPluginPanelfrom the common package is appropriate.
32-34: Component registration is properly updatedThe
PluginPanelcomponent is correctly added to the components list.
35-35: Setup function signature appropriately updatedThe updated setup function signature correctly accepts
propsand{ emit }to support the new component structure.
40-45: Good state management implementationThe reactive state with the emit function is properly created and provided to descendant components, consistent with the pattern used in other files.
54-55: Layout constants properly added to the returned objectAdding
PLUGIN_NAMEto the returned object makes it available in the template, which is necessary for the plugin panel configuration.packages/plugins/block/src/BlockSetting.vue (4)
6-7: Good implementation of dynamic alignment and fixed namingAdding the
:alignand:fixed-nameprops to the plugin-setting component supports the PR's objective of enabling repositioning of plugins. This will allow the plugin to be dynamically aligned based on the layout configuration.
91-98: Import statement properly updatedThe import statement has been correctly structured to include
useLayoutamong other imports. The organization is clean and follows the project's import style.
164-165: Good implementation of layout utilitiesExtracting
PLUGIN_NAMEandgetPluginByLayoutfromuseLayout()provides the necessary tools for dynamic plugin positioning. The computed propertyaligncorrectly usesgetPluginByLayoutto determine the alignment based on the plugin name.
292-293: Layout configuration properly added to the returned objectAdding
alignandPLUGIN_NAMEto the returned object makes them available in the template, which is necessary for the plugin panel configuration.packages/plugins/materials/src/meta/layout/src/Main.vue (3)
2-7: Good implementation of the plugin-panel with fixed namingThe plugin-panel component is correctly configured with
fixed-nameandfixedPanelsprops. The implementation supports the PR's objective of creating a unified plugin panel layout system.Note that the header template section has been removed, which is consistent with the new plugin panel design.
23-23: Appropriate import of layout constantsImporting
META_APP as PLUGIN_NAMEprovides consistency with the naming conventions used in other files. This standardization helps maintain a unified approach to plugin configuration.
83-83: Layout constants properly added to the returned objectAdding
PLUGIN_NAMEto the returned object makes it available in the template, which is necessary for the plugin panel configuration.packages/plugins/tree/src/Main.vue (3)
9-9: Consider renamingdraggable-enabledfor clarity.The prop name
draggable-enabledimplies general drag functionality, but it specifically controls width resizing through dragging.Consider renaming to
width-resizableorresize-enabledto better represent its functionality.
2-11: LGTM! Panel flexibility enhancement implemented correctly.The panel now properly accepts fixed-name and fixedPanels properties, enabling the new flexible layout system.
90-93: Good implementation of state management with Vue provide/inject pattern.Using
provideto share the panel state with child components is a clean approach for event handling across component boundaries.packages/plugins/datasource/src/DataSourceGlobalDataHandler.vue (2)
2-9: Properly configured plugin panel with alignment properties.The plugin-setting component now correctly uses the align property and fixed-name attributes, consistent with the new plugin layout system.
58-58: Good use of computed property for dynamic alignment.Computing the alignment based on the layout configuration provides flexibility in positioning the panel.
packages/plugins/i18n/src/Main.vue (2)
2-9: LGTM! Plugin panel configured correctly with fixed-name and fixedPanels.The component now properly integrates with the flexible layout system.
170-173: Well-structured panel state management.Using a reactive object to encapsulate the emit function and providing it to child components is a clean approach for communication.
packages/plugins/bridge/src/Main.vue (2)
2-7: Properly integrated with the flexible layout system.The plugin-panel component now correctly uses the fixed-name and fixedPanels props.
47-50: Consistent implementation of panel state management.The reactive panelState object with emitEvent maintains consistency with the pattern used across other plugin components.
packages/plugins/schema/src/Main.vue (4)
2-40: Well-structured update to use a plugin-panel componentThe refactoring from a div-based structure to a plugin-panel component improves the organization and maintainability of the UI. The added properties for fixedName, fixedPanels, and draggable-enabled align well with the flexible layout objectives of this PR.
44-47: Good import organizationAdding the necessary imports for the new component structure, including
provideandPluginPanel, keeps the dependencies clear and properly organized.
62-66: Props and state management properly implementedThe addition of the fixedPanels prop and the panelState reactive object with provide/inject pattern enables effective communication between components, which is essential for the plugin panel's flexible layout functionality.
Also applies to: 78-81
218-219: Height calculation adjusted for new component structureThe height calculation has been updated to accommodate the new component structure, ensuring the Monaco editor properly fills the available space.
packages/plugins/block/src/Main.vue (3)
2-14: Plugin panel implementation consistent with project standardsThe implementation of the plugin-panel component with its properties (fixed-name, fixedPanels) maintains consistency with other plugin components, ensuring a uniform approach to flexible layouts throughout the application.
219-223: Well-structured props and panel state managementThe addition of the fixedPanels prop and the implementation of the panelState with provide/inject pattern ensures proper state management across components, which is crucial for the plugin's flexible layout functionality.
Also applies to: 273-279
319-321: Proper cleanup on closeThe close method now properly emits the close event and calls closePanel(), ensuring that both the UI state and any internal state are properly cleaned up when the panel is closed.
packages/canvas/DesignCanvas/src/DesignCanvas.vue (4)
2-2: Improved interaction state with conditional classThe addition of the
not-selectedclass based on thegetMoveDragBarState()function enhances the visual feedback during drag operations, aligning with the PR's goal to improve the dragging experience.
70-71: Good modularization of layout-related functionsImporting specific functions from useLayout maintains good separation of concerns and keeps the code focused on specific functionality.
156-167: Enhanced panel management logicThe updated nodeSelected function now properly respects the fixed status of panels before attempting to close them, ensuring that fixed panels remain open during node selection, which improves user experience.
299-304: Effective pointer event handlingThe addition of the
not-selectedclass with pointer-events: none and user-select: none properly prevents interaction with the canvas during drag operations, which is essential for smooth dragging functionality.packages/plugins/state/src/Main.vue (4)
2-11: Consistent plugin panel implementationThe implementation of the plugin-panel component with appropriate properties maintains consistency with other plugin components and aligns with the PR's goal of implementing a flexible layout.
45-45: Dynamic panel positioningThe addition of
:style="alignStyle"to the right panel enables dynamic positioning based on the panel's alignment, which is crucial for the flexible layout functionality.
148-156: Well-implemented dynamic panel offset calculationThe computed properties
firstPanelOffsetandalignStyleeffectively calculate the positioning of panels based on their layout configuration, enabling seamless repositioning of panels via dragging or menu options.
158-162: Effective state sharing with provide/injectThe implementation of the panelState reactive object with provide/inject pattern ensures proper communication between components, which is essential for the flexible panel layout functionality.
packages/plugins/page/src/PageSetting.vue (4)
2-8: Props added for flexible layout managementThe
plugin-settingcomponent has been enhanced with two new props:
:fixed-name="PLUGIN_NAME.AppManage"- Specifies the plugin identifier:align="align"- Determines the alignment of the pluginThese additions are consistent with the PR objective to implement a flexible layout for plugin panels.
63-63: Added computed import to support new reactive propertyThe import statement now includes
computedfrom Vue, which is necessary for the new dynamicalignproperty.
145-146: Added layout integration for plugin positioningDestructuring
PLUGIN_NAMEandgetPluginByLayoutfromuseLayout()brings in the necessary layout management utilities. The computed propertyaligndetermines the plugin's alignment dynamically based on the plugin name.
410-411: Exposed layout properties to the templateAdded
alignandPLUGIN_NAMEto the component's return object, making them available in the template.packages/layout/src/DesignPlugins.vue (11)
4-36: Replaced static nav list with draggable componentThe static navigation list has been replaced with a
vue-draggable-nextcomponent, enabling:
- Drag-and-drop functionality for plugin reordering
- Proper event handling with
@end="onEnd"- Filtering specific plugins with the
filterpropertyThis implementation supports the PR's goal of allowing users to reposition plugins via dragging.
39-65: Enhanced bottom navigation with draggable functionalityThe bottom navigation area now features:
- A flexible layout with proper spacing
- Draggable functionality matching the top navigation
- Consistent DOM structure with the top navigation
- Context menu support for plugin repositioning
This maintains consistency with the top navigation while supporting the PR's objective of providing flexible plugin layouts.
69-87: Improved plugin panel rendering with conditional classThe plugin panel now:
- Includes a conditional class for drag state management
- Has proper positioning classes based on fixed state
- Wraps the component in a container for better layout control
The addition of the
not-selectedclass during drag operations prevents unwanted interactions while dragging, improving the user experience.
90-95: Added context menu for plugin managementA new
plugin-right-menucomponent has been integrated to provide:
- A consistent interface for plugin alignment changes
- Access to all plugins from both top and bottom lists
- A centralized way to trigger the
switchAlignactionThis supports the PR objective of allowing users to control plugin visibility and positioning through right-click menus.
122-123: Added pluginList prop for unified plugin managementAdded a new
pluginListprop to receive all available plugins (from both left and right panels), enabling:
- Consistent plugin identification across the application
- Better management of plugin state and positioning
- Unified source of truth for plugin information
This prop works together with the existing
pluginsprop to maintain backward compatibility.
147-153: Improved context menu handlingThe
showContextMenumethod now provides:
- Different behavior based on click target (plugin vs empty area)
- Contextual information about the clicked plugin (item, index, position)
- Proper event positioning using client coordinates
This enhances the right-click functionality required for the flexible plugin layout.
155-170: Fixed plugin duplication issue when changing alignmentThe
changeAlignmethod now properly:
- Finds and removes the plugin from its current list if it exists
- Then adds it to the target list
This fixes the issue identified in the previous review where plugins could be duplicated when changing alignment.
177-182: Enhanced component resolution with safety checksThe
currentComponentcomputed property now:
- Verifies plugin existence in both navigation lists
- Returns null when a plugin isn't found
- Prevents errors when accessing non-existent components
This improves error handling and provides a more robust UI experience.
228-238: Implemented alignment switching with proper cleanupThe
switchAlignmethod:
- Properly removes the plugin from its source list
- Emits an event to update the parent component
- Closes the panel if needed when changing sides
- Triggers the layout update through
dragPluginLayoutThis method is key to enabling the flexible plugin positioning required by the PR.
245-248: Added drag end handler for layout updatesThe
onEndmethod properly:
- Checks if the plugin has moved between different sides
- Closes the panel if needed
- Updates the plugin layout based on the drag operation
This completes the drag-and-drop functionality for repositioning plugins.
399-402: Added styling for non-interactive state during draggingThe
.not-selectedclass provides:
- Disabled pointer events to prevent unwanted interactions
- User-select prevention to improve drag experience
This small but important style addition improves the drag-and-drop user experience.
packages/layout/src/Main.vue (6)
9-16: Enhanced DesignPlugins with conditional rendering and alignment controlThe
design-pluginscomponent now:
- Uses a conditional render with
v-if="leftMenuShownStorage"for better control- Includes a reference to access methods on the component
- Passes the combined
pluginListfor unified plugin management- Handles alignment changes with the new
@changeLeftAligneventThese changes support the PR's goal of implementing a unified logic for the floating and fixed states of plugin panels.
21-29: Enhanced DesignSettings with conditional rendering and alignment controlSimilar to the left panel, the right panel now:
- Uses conditional rendering with
v-if="rightMenuShownStorage"- Includes a reference for method access
- Receives the unified
pluginList- Handles alignment changes with
@changeRightAlignThese parallel changes ensure consistent behavior between left and right panels.
67-68: Expanded layout state access with menu visibility controlsThe destructuring now includes:
leftMenuShownStorageandrightMenuShownStoragefor conditional renderinginitPluginStorageReactivefor initializing plugin stateThis provides the necessary reactive state for controlling panel visibility.
75-83: Added cross-panel communication for alignment changesThe new refs and methods:
- Create references to both panel components (
leftandright)- Implement methods to propagate alignment changes between panels
- Enable plugins to move from one panel to another
This is a key mechanism for the flexible layout implementation described in the PR.
86-121: Implemented unified plugin list management with persistent storageThe new plugin management logic:
- Combines plugins and settings into a unified
pluginList- Organizes plugins by alignment group
- Assigns consistent properties to each plugin (width, align, index, etc.)
- Persists the configuration to localStorage for state persistence
This comprehensive approach provides a solid foundation for the flexible plugin layout implementation.
167-168: Updated right panel container to use flexbox layoutChanged the
.tiny-engine-right-wrapstyling from:
- Position-based layout to flexbox layout
- Added row direction with nowrap
This provides better structural support for the flexible layout of the right panel.
packages/common/component/PluginSetting.vue (8)
2-12: Enhanced plugin setting with dynamic positioning classesThe plugin setting component now supports:
- Identification with an ID for easier DOM access
- Conditional classes for different alignments
- Shadow styling based on position
- Dynamic CSS through the computed
alignStylepropertyThese enhancements make the component much more flexible for different layout positions.
42-47: Added necessary imports for enhanced functionalityAdded imports:
nextTickfor proper DOM updatescomputedfor reactive style propertiesuseLayoutfor accessing the layout management systemThese imports enable the new dynamic positioning features of the component.
104-111: Added props for flexible positioningTwo important new props were added:
fixedName: Identifies the plugin in the layout systemalign: Specifies the positioning direction (leftTop, rightTop, etc.)These props are central to the flexible layout implementation, allowing plugins to be placed consistently in various positions.
121-131: Added computed properties for dynamic positioningThree new computed properties calculate positioning values:
firstPanelOffset: Gets the width of a specified fixed panelsecondPanelAlign: Determines alignment direction based on thealignpropalignStyle: Constructs the CSS positioning stringThese properties enable the component to adapt its position dynamically based on other panels.
133-139: Avoid direct DOM queries in watchEffectThe current implementation directly queries the DOM to adjust panel positioning:
watchEffect(() => { const secondPanelOffset = document.querySelector('.plugin-setting')?.clientWidth + firstPanelOffset.value nextTick(() => { document.querySelector('.second-panel')?.style.setProperty(secondPanelAlign.value, `${secondPanelOffset}px`) }) })This approach may lead to timing issues in complex UIs and can be hard to test.
Consider using template refs instead of direct DOM queries:
-watchEffect(() => { - const secondPanelOffset = document.querySelector('.plugin-setting')?.clientWidth + firstPanelOffset.value - nextTick(() => { - document.querySelector('.second-panel')?.style.setProperty(secondPanelAlign.value, `${secondPanelOffset}px`) - }) -}) +// Add refs to the template +const panelRef = ref(null) +const secondPanelRef = ref(null) + +// Then use the refs in the watchEffect +watchEffect(() => { + if (!panelRef.value || !secondPanelRef.value) return + + const secondPanelOffset = panelRef.value.clientWidth + firstPanelOffset.value + nextTick(() => { + secondPanelRef.value.style.setProperty(secondPanelAlign.value, `${secondPanelOffset}px`) + }) +})Don't forget to add the corresponding
ref="panelRef"andref="secondPanelRef"attributes to the relevant elements in the template.
155-158: Added shadow class computation for visual distinctionThe
shadowClasscomputed property:
- Adds no shadow for secondary panels
- Adds appropriate left or right shadow based on alignment
- Improves visual hierarchy and separation between panels
This visual enhancement helps users understand the panel structure better.
183-193: Enhanced shadow styling for different alignmentsAdded specific shadow styles for both left and right aligned panels:
.shadow-leftapplies shadow to the right edge.shadow-rightapplies shadow to the left edge- Both remove their respective borders for a cleaner look
This visual refinement improves the appearance of the flexible panel layout.
256-258: Added right alignment stylingAdded the
.align-rightclass to position panels on the right side of the screen, complementing the existing left positioning.This small but crucial addition enables the right-side panel layout required by the PR.
packages/layout/src/DesignSettings.vue (9)
3-3: Good implementation of drag interaction prevention.The conditional class
.not-selectedis a smart way to disable interactions during drag operations, improving the user experience by preventing unintended clicks.
4-18: Clean implementation of the dynamic right panel.The right panel implementation properly handles conditional rendering based on the selected panel and applies appropriate classes for fixed/floating states. The component structure allows for flexible content rendering.
39-44: Good separation of context menu functionality.Extracting the right-click menu into a separate component improves code modularity and reusability across the application.
93-99: Clean context menu handling.The
showContextMenumethod properly handles different types of context menu interactions based on the provided parameters.
101-104: Efficient plugin component registration.Using a
forEachloop to populate the components and iconComponents objects from the pluginList prop is a clean approach.
124-132: Well-implemented plugin alignment adjustment.The
changeAlignmethod effectively handles the repositioning of plugins with proper checks for existing items.
139-145: Smart toggle behavior for plugin menu.The
clickMenumethod intelligently handles the toggle behavior, closing the panel if it's already open or opening it if it's not.
157-160: Comprehensive drag event handling.The
onEndmethod properly handles drag operations, with intelligent panel closing when plugins are moved between sides.
315-318: Duplicate CSS class definition.The
.not-selectedclass appears to be defined twice in the file - here and at lines 332-334 (not shown in this code but mentioned in previous comments).packages/common/component/PluginPanel.vue (10)
2-2: Good dynamic width implementation.Using a binding for the panel width enables responsive resizing and improves user experience.
12-22: Well-implemented collapsible functionality with tooltip.The collapsible icon with tooltip provides clear user feedback and improves usability.
23-28: Clear visual indication for fixed panel state.The fixed panel button properly changes its icon and tooltip based on the current state, providing good visual feedback to users.
32-34: Improved content scrolling container.Wrapping the content slot in a scrollable container improves the handling of overflowing content.
36-39: Well-implemented resizing functionality.The conditional resizers on both sides allow for flexible panel resizing based on panel position.
166-167: Efficient mouse move handling with throttling.Using
useThrottleFnfrom@vueuse/corefor mouse move events is an excellent optimization that will improve performance during resizing operations.
208-211: Avoid direct DOM queries for resizer elements.Using
document.querySelectorto get DOM elements is brittle and can lead to issues if the DOM structure changes.
213-216: Good collapse state management with event emission.The
clickCollapseIconmethod properly toggles the state and notifies the parent component via an event.
291-316: Clean resizer styling with visual feedback.The resizer styles provide appropriate visual feedback with hover and dragging states, improving the user experience during resizing operations.
334-343: Optimized scrolling container styles.The
.scroll-contentstyles properly hide the scrollbar while maintaining scrolling functionality across different browsers.packages/layout/src/composable/useLayout.js (8)
20-27: Well-defined plugin position constants.Creating a
PLUGIN_POSITIONobject with clear constant values improves code readability and maintainability.
64-69: Clean drag bar state management.The getter and setter functions for the drag bar state provide a clean API for managing this state.
70-83: Persistent menu visibility state.Using
useStoragefor menu visibility ensures the user's preferences are preserved across sessions.
84-96: Elegant fixed panels toggle implementation.The functions for toggling fixed panels use a clean pattern: if the panel exists, remove it; otherwise, add it. This avoids duplication and ensures atomic updates.
126-130: Comprehensive fixed panels status check.The
getFixedPanelsStatusfunction provides a convenient way to check the fixed status of both panels at once.
182-194: Robust plugin width management.The width management functions properly handle both existing and new plugins, with appropriate fallback to a default width.
234-275: Comprehensive drag and drop implementation.The
dragPluginLayoutfunction handles complex drag operations including both within-list and cross-list scenarios. The index adjustments ensure consistent ordering after moves.
292-297: Safe plugin visibility toggle with initialization.The
changePluginShownfunction safely handles the case where a plugin doesn't exist in storage yet by initializing it with a default visibility state.
There was a problem hiding this comment.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
packages/plugins/schema/src/Main.vue (1)
87-98:⚠️ Potential issueFix inverted condition logic in close function.
The condition logic appears to be inverted. If
state.pageData === strsis true, there are no changes, but the code treats this as if there are changes.const close = () => { const strs = app.refs.container.getEditor().getValue() - const isChanged = state.pageData === strs + const isChanged = state.pageData !== strs if (!isChanged) { + emit('close') + } else { confirm({ title: '提示', message: '有改动未保存,您确定关闭吗?', exec: () => emit('close') }) - } else { - emit('close') } }
🧹 Nitpick comments (5)
packages/common/component/PluginPanel.vue (3)
154-164: Reduce code duplication in mouse move handlers.The right and left mouse move handlers share similar logic with only minor differences. Consider refactoring them into a single function to improve maintainability.
-const onMouseMoveRight = (event) => { - const newWidth = startWidth + (event.clientX - startX) - panelWidth.value = Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH)) - changePluginWidth(props.fixedName, panelWidth.value) -} - -const onMouseMoveLeft = (event) => { - const newWidth = startWidth - (event.clientX - startX) - panelWidth.value = Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH)) - changePluginWidth(props.fixedName, panelWidth.value) -} +const onMouseMove = (event, direction = 'right') => { + const factor = direction === 'right' ? 1 : -1 + const newWidth = startWidth + (factor * (event.clientX - startX)) + panelWidth.value = Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH)) + changePluginWidth(props.fixedName, panelWidth.value) +} + +const onMouseMoveRight = (event) => onMouseMove(event, 'right') +const onMouseMoveLeft = (event) => onMouseMove(event, 'left')
172-206: Implement cleanup for event listeners in component lifecycle.Event listeners attached to
documentaren't automatically removed when the component is unmounted, which could lead to memory leaks.+import { inject, ref, computed, onMounted, onBeforeUnmount, provide } from 'vue' // ...existing code... +const removeEventListeners = () => { + document.removeEventListener('mousemove', throttledMouseMoveRight) + document.removeEventListener('mousemove', throttledMouseMoveLeft) + document.removeEventListener('mouseup', onMouseUpRight) + document.removeEventListener('mouseup', onMouseUpLeft) +} +onBeforeUnmount(() => { + removeEventListeners() +}) const onMouseUpRight = () => { changeMoveDragBarState(false) - document.removeEventListener('mousemove', throttledMouseMoveRight) - document.removeEventListener('mouseup', onMouseUpRight) + removeEventListeners() rightResizer.value.style.cursor = '' rightResizer.value.classList.remove('dragging') } // ...similar changes for onMouseUpLeft...
129-131: Consider making width constants configurable through props.The minimum and maximum width values are currently hardcoded, but could be made configurable for better component reusability.
+ /** + * 最小宽度 + */ + minWidth: { + type: Number, + default: () => constants.PLUGIN_DEFAULT_WIDTH + }, + /** + * 最大宽度 + */ + maxWidth: { + type: Number, + default: 1000 + } // ...in setup function: - const MIN_WIDTH = PLUGIN_DEFAULT_WIDTH // 固定的最小宽度值 - const MAX_WIDTH = 1000 // 固定的最大宽度值 + const MIN_WIDTH = props.minWidth // 可配置的最小宽度 + const MAX_WIDTH = props.maxWidth // 可配置的最大宽度packages/plugins/schema/src/Main.vue (2)
16-22: Remove or implement the hidden import Schema feature.This popover is permanently hidden with
v-show="false". If this feature is not ready yet, consider removing it entirely or adding a prop to conditionally show it.-<tiny-popover v-show="false" placement="bottom" trigger="hover" append-to-body content="导入 Schema"> +<!-- TODO: Implement import schema functionality --> +<!-- <tiny-popover placement="bottom" trigger="hover" append-to-body content="导入 Schema"> <template #reference> <span class="icon-wrap"> <icon-download-link></icon-download-link> </span> </template> -</tiny-popover> +</tiny-popover> -->
36-38: Conditionally render the footer instead of hiding it with CSS.The footer has
display: nonein CSS (line 227), but is still being rendered. For better performance, conditionally render it only when needed.-<div class="source-code-footer"> - <button>导入 Schema</button> -</div> +<!-- TODO: Implement import functionality --> +<!-- <div class="source-code-footer"> + <button>导入 Schema</button> +</div> -->
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
packages/common/component/PluginPanel.vue(5 hunks)packages/plugins/schema/src/Main.vue(5 hunks)packages/plugins/script/src/Main.vue(5 hunks)packages/plugins/tree/src/Main.vue(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/plugins/tree/src/Main.vue
🔇 Additional comments (14)
packages/plugins/script/src/Main.vue (10)
2-11: Good restructuring to a standardized componentThe refactoring to use the standardized
<plugin-panel>component improves consistency with the rest of the application and adds important functionality like width resizing. The clear prop naming makes the component's purpose evident.
12-17: Well-organized header with visual feedbackThe header implementation with the conditional red indicator provides good visual feedback for unsaved changes, and the save button placement is intuitive. The named slot structure improves readability and maintainability.
18-29: Content organization is clean and functionalThe content section maintains its functionality while benefiting from the new panel structure. The monaco editor integration remains intact with all necessary event handlers.
34-38: Good Vue 3 composition API usageThe addition of
reactiveandprovideimports, along with the updated component imports, properly leverages Vue 3's composition API for state management. The integration with the engine's layout system viauseLayoutis a good approach.
53-59: Component registration and props are properly definedThe
PluginPanelcomponent registration and the addition of thefixedPanelsprop are correctly implemented. The prop type is defined according to Vue best practices.
65-71: Good reactive state management implementationThe implementation of reactive state and providing it to descendant components follows Vue 3 best practices. The extraction of
PLUGIN_NAMEfromuseLayout()ensures consistency with the application's layout system.
123-123: Properly exposing PLUGIN_NAME to the templateAdding
PLUGIN_NAMEto the return object ensures it's available in the template for the fixed-name prop, which is necessary for the panel system to work correctly.
142-164: Well-structured styling for new elementsThe styling for the icon wrapper and indicators is well-organized and follows good CSS practices. The positioning of the red dot indicator is precise and provides clear visual feedback.
166-169: Appropriate content area stylingThe updated padding and height calculations ensure the editor has sufficient space while maintaining the overall aesthetics of the panel.
177-177: Clean removal of unnecessary stylingThe empty line indicates removal of styles that were likely specific to the previous implementation, which is appropriate as part of this refactoring.
packages/common/component/PluginPanel.vue (1)
208-211: Consider using Vue refs instead of direct DOM queries.Using
document.querySelectorfor DOM elements is fragile and could cause issues if multiple instances of this component exist or if the DOM structure changes.- const initResizerDOM = () => { - leftResizer.value = document.querySelector('.resizer-left') - rightResizer.value = document.querySelector('.resizer-right') - } + // Add refs in the template + // <div class="resizer-right" v-if="isLeftResizer" ref="rightResizerRef" @mousedown="onMouseDownRight"></div> + // <div class="resizer-left" v-if="isRightResizer" ref="leftResizerRef" @mousedown="onMouseDownLeft"></div> + + // Then in setup(): + const rightResizerRef = ref(null) + const leftResizerRef = ref(null) + + // Update the references after mount + onMounted(() => { + leftResizer.value = leftResizerRef.value + rightResizer.value = rightResizerRef.value + }) + + // Include in return statement + return { + // ...other returns + rightResizerRef, + leftResizerRef + }packages/plugins/schema/src/Main.vue (3)
77-81: Good use of reactive panelState with provide/inject pattern.This implementation creates a clean communication channel between components and follows Vue's composition API best practices.
8-8:Details
❓ Verification inconclusive
Add validation for the width-resizable prop.
You're passing
:width-resizable="true"directly, but should verify that the PluginPanel component properly handles this prop.Run the following script to verify that the
width-resizableprop is correctly defined in the PluginPanel component:
🏁 Script executed:
#!/bin/bash # Description: Check if widthResizable prop is properly defined in PluginPanel # Search for the prop definition in PluginPanel.vue rg -A 8 "widthResizable.*type:\s*Boolean" "packages/common/component/PluginPanel.vue"Length of output: 85
Action Required: Verify Width-Resizable Prop Handling
It appears that our initial search in
packages/common/component/PluginPanel.vuedid not return any evidence of a definedwidthResizableprop (i.e., a Boolean prop definition). Please manually confirm whether the PluginPanel component is intended to accept and validate this prop. If it should, update PluginPanel to include the proper prop definition and validation (ensuring proper handling of the kebab-case to camelCase transformation). If not, consider removing or revising its usage inpackages/plugins/schema/src/Main.vue.
6-7:Details
✅ Verification successful
Ensure consistent handling of fixedPanels and fixedName props.
Make sure the PluginPanel component correctly handles these props and that PLUGIN_NAME.Schema exists.
Run the following script to verify the constant existence and proper handling:
🏁 Script executed:
#!/bin/bash # Description: Verify PLUGIN_NAME.Schema existence and fixedPanels handling # Check if PLUGIN_NAME.Schema is defined rg -A 5 "PLUGIN_NAME\s*=\s*{" --type js # Check how fixedPanels is used in PluginPanel rg "fixedPanels.*includes\(fixedName\)" --type vue packages/common/componentLength of output: 250
Below is an updated verification script using corrected regex and file glob patterns. Please run it and manually inspect the output to ensure that the constant is defined and used as expected:
Re-verify fixedPanels and fixedName prop handling in PluginPanel
- Confirm that the constant
PLUGIN_NAME.Schemaexists by searching for it in JS files.- Verify that the PluginPanel component in
packages/common/component(or related Vue components) correctly handles thefixedPanelsprop by checking for its use withincludes(fixedName).Once you manually verify that these conditions are met based on the above script’s output, please update or confirm the code accordingly.
🏁 Script executed:
#!/bin/bash # Verify PLUGIN_NAME.Schema definition in JavaScript files rg "PLUGIN_NAME\.Schema" --type js # Verify that fixedPanels is used appropriately in PluginPanel. # Searching within .vue files in the packages/common/component directory. rg "fixedPanels.*includes\\(fixedName\\)" -g "*.vue" packages/common/componentLength of output: 544
Re-verified: FixedPanels and FixedName Props Handling
- Verified that
PLUGIN_NAME.Schemais present inpackages/plugins/schema/src/Main.vue.- Confirmed that the
PluginPanelcomponent (inpackages/common/component/PluginPanel.vue) correctly uses thefixedPanelsprop with theincludes(fixedName)logic.The code handles these props consistently, so no further changes are necessary.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/layout/src/composable/useLayout.js (1)
163-180: Local storage parse fallback
Storing plugin info inlocalStoragehelps user continuity. However, if parsing fails (e.g., corrupted JSON), rethrowing the error might break the UI. Consider a fallback reset or user-facing warning to handle invalid data more gracefully.try { const storedPlugin = localStorage.getItem('plugin') if (storedPlugin) { plugin = JSON.parse(storedPlugin) } } catch (error) { - throw new Error(error) + console.warn('Invalid plugin data in localStorage; resetting to default.') + plugin = [] }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
packages/common/component/PluginPanel.vue(5 hunks)packages/layout/src/Main.vue(4 hunks)packages/layout/src/composable/useLayout.js(5 hunks)packages/plugins/schema/meta.js(1 hunks)packages/plugins/schema/src/Main.vue(5 hunks)packages/plugins/script/meta.js(1 hunks)packages/plugins/script/src/Main.vue(5 hunks)packages/plugins/tree/meta.js(1 hunks)packages/plugins/tree/src/Main.vue(4 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
packages/layout/src/composable/useLayout.js (1)
packages/utils/src/constants/index.js (6) (6)
STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_LEFT_FIXED_PANELS(100-100)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)STORAGE_KEY_RIGHT_FIXED_PANELS(101-101)PLUGIN_DEFAULT_WIDTH(168-168)PLUGIN_DEFAULT_WIDTH(168-168)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: push-check
🔇 Additional comments (42)
packages/plugins/tree/meta.js (1)
6-7: Enhancement to plugin configuration aligns with flexible layout objectivesThese changes effectively support the PR's goal of implementing a flexible layout for the plugin panel:
- Adding
widthResizable: trueenables users to manually adjust the panel width through dragging, as specified in the PR objectives.- Changing
alignfrom'top'to'leftTop'standardizes alignment specification across plugins, supporting the unified logic for floating and fixed states.Both modifications contribute to the improved layout flexibility while maintaining backward compatibility.
packages/plugins/script/meta.js (1)
6-8: Configuration additions support flexible plugin layout requirementsThe changes to the plugin metadata properly implement the flexible layout requirements by:
- Standardizing the alignment approach with
leftTopinstead oftop- Setting an initial width of 600px
- Enabling width resizing with
widthResizable: trueThese changes align perfectly with the PR objectives of making the plugin panel width adjustable through dragging.
packages/plugins/script/src/Main.vue (6)
2-29: Improved component architecture with plugin-panelThe template restructuring effectively leverages the
plugin-panelcomponent to support the flexible layout requirements. The use of named slots for header and content creates a clean separation of concerns, while properly passing the fixed panel configuration.
33-37: Enhanced reactivity with composition APIGood use of Vue 3's composition API with reactive state management and the useLayout hook to access PLUGIN_NAME constants. This provides a more maintainable and scalable approach.
54-58: Added configuration prop for flexible panelsAdding the
fixedPanelsprop correctly implements the ability to configure fixed vs floating behavior per the PR requirements.
64-69: State management improvement with provide/inject patternThe implementation of a reactive panelState that's provided to child components follows best practices for state management in Vue. This enables better component communication and state sharing.
141-162: Well-structured visual feedback for changesThe styling for the change indicator (red dot) and save button is well implemented, providing clear visual feedback to users when there are unsaved changes.
166-167: Simplified content layoutThe code-edit-content styling is appropriately simplified, providing proper spacing while maintaining the full height calculation for the editor.
packages/plugins/schema/meta.js (1)
6-8: Updated plugin alignment and added resizing capabilitiesThese changes align with the PR objective to implement a flexible layout for plugin panels. The
alignproperty change positions the schema plugin at the left bottom, while the newwidthResizableandwidthproperties enable width adjustment through dragging with a default width of 600px.packages/plugins/tree/src/Main.vue (2)
2-10: Improved panel structure with unified fixed/floating logicThe template has been simplified to use the
plugin-panelcomponent with appropriate props for fixed panel management. This change aligns with the PR objective to implement unified logic for the floating and fixed states of the plugin panel.
78-92: Added panel state management for improved component communicationThe new reactive
panelStateobject andprovidemechanism create a clean way to share state with child components, enabling better communication between the panel and its parent components.packages/plugins/schema/src/Main.vue (3)
2-39: Restructured plugin panel with improved layout organizationThe template has been completely restructured to use the
plugin-panelcomponent with clearly defined header and content slots. This change supports the PR objective of restructuring the display logic for the plugin panel and provides a more consistent UI structure.
77-80: Added panel state management for improved component communicationSimilar to the tree plugin, this component now uses a reactive
panelStateobject andprovidemechanism to share state with child components, enabling better communication between components.
217-218: Fixed content height calculationThe height calculation has been adjusted to account for the new panel structure, ensuring the content area properly fills the available space with a small margin.
packages/layout/src/Main.vue (5)
9-14: Enhanced plugin panel management with conditional rendering and alignment controlThe left plugin panel now uses conditional rendering based on
leftMenuShownStorageand includes a reference and event handler for alignment changes, supporting the PR objective of controlling the visibility and position of plugins.
22-28: Added flexible control for the right settings panelSimilar to the left panel, the right settings panel now has conditional rendering, a reference, and alignment control, which supports the PR objective of enabling users to control the visibility and position of plugins.
75-83: Implemented cross-panel communication for alignment changesThe new refs and change alignment methods allow the left and right panels to communicate when plugin alignment changes, ensuring both panels stay in sync when plugins are moved between them.
86-123: Implemented comprehensive plugin organization and storageThis new code segment:
- Creates a merged plugin list
- Organizes plugins by alignment group
- Sets up plugin properties including width, visibility, and resizability
- Stores the configuration in localStorage
This is central to the PR objective of implementing a flexible layout system where users can reposition and resize plugins.
169-170: Updated right panel layout to use flexboxChanged the right panel layout from position-based to flexbox, which provides better flexibility for dynamic content and supports the plugin panel's resizing capabilities.
packages/common/component/PluginPanel.vue (13)
2-3: Use of inline width binding looks good
You correctly bind the width topanelWidthwhile referencing the DOM element viaref="panel". This ensures the panel’s width is dynamically updated based on reactive state.
12-28: Collapsible tooltip and button implementation is clear
Conditional rendering of<tiny-tooltip>and<svg-button>based onisShowCollapseIconandisCollapsedis straightforward and easy to maintain. The logic for toggling icon and updates to collapsed/expanded state look sound.
32-39: Scroll and width resizing sections are well separated
Creating a dedicated.scroll-contentwrapper and then placing the resizer elements within a conditional block (v-if="isWidthResizable") keeps the layout modular and clear.
44-48: Imports and component registrations are aligned
Using@vueuse/corefor throttling, referencingSvgButton, and registeringTinyTooltipfrom@opentiny/vueare all consistent with best practices. The newly introduced or updated imports and component definitions appear correct and match usage.Also applies to: 51-51, 55-58
86-112: Flexible configuration props and improved documentation
Defining new props (fixedPanels,fixedName,showBottomBorder, andisShowCollapseIcon) and providing clear doc comments make the component more flexible and understandable. Good job ensuring default values and proper type checks.
114-114: New event emission
EmittingupdateCollapseStatuson collapse toggle is a clean way to keep the parent component in sync with the panel’s state.
120-134: Resizing parameters are well-defined
UsingPLUGIN_DEFAULT_WIDTHforMIN_WIDTHis a sensible baseline, and specifying aMAX_WIDTHof 1000 is fine for normal usage. InjectingpanelStateto handle fix/unfix logic also seems appropriate, though consider confirming thatpanelStateis always provided to avoid runtime errors.Would you like to ensure or verify that
panelStateis always injected by the parent and notundefined?
138-138: Neat computed and layout integration
headerBottomLineandisWidthResizablecomputed properties integrate smoothly with your layout logic (useLayout), ensuring the panel’s style and resizability respond to the user’s preferences.Also applies to: 140-140, 143-147
149-211: Throttled drag event handlers
The resizing routines (onMouseDownRight,onMouseMoveRight, etc.) are cleanly implemented with throttling to avoid excessive re-renders. StoringstartX/startWidthin outer scope is a standard and clear approach.
203-206: Use refs instead of direct DOM queries
This code reintroduces the approach of querying.resizer-left/.resizer-rightviadocument.querySelector, which can be fragile if the DOM structure changes. Using Vue refs would be more robust. This was previously noted in an older review.
213-230: Mounted lifecycle usage
CallinginitResizerDOM()ononMountedis a straightforward approach. If you switch to Vue refs in the future, you can remove direct DOM queries.
286-311: Right resizer CSS
The.resizer-rightrules, plus hover and.draggingstates, provide clear user feedback. Good job using transitions and distinct cursor styling.
313-339: Left resizer and scroll-content styling
Consistent styling for.resizer-leftmirrors the approach on the right side. Hiding scrollbars with::-webkit-scrollbar { display: none; }can improve the visual design, provided it meets user accessibility needs.packages/layout/src/composable/useLayout.js (10)
14-14: VueUse for storage looks good
ImportinguseStoragefrom@vueuse/coreis a concise approach to persisting layout-related states and menu visibility.
18-19: Multi-constant import fromconstants
Destructuring needed constants, includingPLUGIN_DEFAULT_WIDTH, keeps the code organized and clarifies your usage of these layout-specific values.
20-27: Well-definedPLUGIN_POSITION
Mapping out all relevant plugin positions in one object makes references to layout alignment more self-documenting and straightforward to maintain.
29-31:pluginStateaddresses global plugin events
StoringpluginEventin a reactive object can be advantageous for watchers or computed logic that might respond to changes. This is a simple approach.
34-34: Expanded layoutState for isShow and fixedPanels
Adding theisShowandfixedPanelsfields for plugins/settings clarifies each panel’s visibility and pinned state. The default configuration is well-structured, ensuring minimal setup friction.Also applies to: 44-49, 51-54
65-69: Menu visibility & fixed panels are elegantly stored
UsinguseStorageforleftMenuShown/rightMenuShownandleftFixedPanelsStorage/rightFixedPanelsStorageis a neat solution for persisting user preferences. The toggle functionschangeMenuShown,changeLeftFixedPanels, andchangeRightFixedPanelsare straightforward and robust.Also applies to: 70-72, 73-82, 84-85, 86-86, 87-91, 92-96
101-102: Getter functions for layout states
getPluginState()andgetSettingState()provide a clear, typed approach to retrieving layout sub-states. Straightforward and maintainable.
114-114: Highlighting settings with an activation flag
Enabling a short highlight effect (settings.activating = true) is a good UX touch to draw focus to the settings panel.
120-121: Retrieving fixed panels status and closing setting
getFixedPanelsStatus()andcloseSetting(forceClose)let you handle pinned states gracefully. The logic to setsettings.render = nullif not pinned or forced closed stands out as understandable and consistent.Also applies to: 122-130
181-349: Plugin storage and layout mechanics
Functions (getPluginWidth,changePluginWidth,getPluginByLayout, drag-and-drop logic) thoroughly handle plugin alignment and sizing. The checks for existence inchangePluginShownandchangePluginWidthhelp avoid null references. The approach is modular and comprehensible.


English | 简体中文
PR
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
Background and solution
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
New Features
Refactor
Style
Chores