Skip to content

feat: 添加区块双向绑定属性选择功能到事件表单 #1453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

0x7A7A6572
Copy link
Contributor

@0x7A7A6572 0x7A7A6572 commented May 30, 2025

在 BlockEventForm.vue 中添加了双向绑定属性选择器,允许用户通过悬浮图标查看并选择可用属性来自动生成v-model事件。

English | 简体中文

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • Built its own designer, fully self-validated

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • [x ] Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

Background and solution

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • [ x] No

Other information

添加区块-事件管理中双向绑定属性的事件,对应schema events 的 onUpdate:eventName
Snipaste_2025-05-30_03-12-59
Snipaste_2025-05-30_03-13-39

Summary by CodeRabbit

  • New Features

    • Added a popover to the event name input, allowing users to quickly bind update events to block properties.
    • Users can select properties from a list to auto-generate "onUpdate:" events and update labels accordingly.
  • Improvements

    • Enhanced event name validation to recognize and support auto-generated update events.
    • Improved UI feedback and styling for event binding and selection.

在 BlockEventForm.vue 中添加了双向绑定属性选择器,允许用户通过悬浮图标查看并选择可用属性来自动生成v-model事件。
Copy link
Contributor

coderabbitai bot commented May 30, 2025

Walkthrough

The BlockEventForm.vue component was updated to introduce a popover UI for the event name input, allowing users to select block properties for quick event binding. The update includes new reactive state, computed properties, a custom validator, and additional components to support this interactive feature and its associated styling.

Changes

File(s) Change Summary
packages/plugins/block/src/BlockEventForm.vue Added a suffix popover to the event name input for binding update events to block properties; introduced new reactive state, computed properties (eventNameList, isUpdateEvent), a custom validation rule, new components (TinyPopover, TinyIconRichTextLink), methods, and styling for the popover and input suffix.

Poem

In the garden of blocks, a popover grew,
With properties to pick, and events to renew.
Click and it binds, with a suffix so neat,
Validation adapts, making forms complete.
🐇✨ Now event names bloom,
In this Vue-filled room!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07b948b and e5ba960.

📒 Files selected for processing (1)
  • packages/plugins/block/src/BlockEventForm.vue (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/plugins/block/src/BlockEventForm.vue
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the enhancement New feature or request label May 30, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/plugins/block/src/BlockEventForm.vue (1)

105-119: Simplify the custom validator logic.

The validation logic can be simplified for better readability and maintainability.

       eventName: [
         {
           pattern: REGEXP_EVENT_NAME,
           message: eventNameTip,
-          validator: (rule: any /* IFormInnerRule */, value: string, callback: (e?: Error) => void) => {
-            if (isUpdateEvent.value) return callback()
-            if (!rule.pattern.test(value)) {
-              callback(new Error(rule.message))
-            } else {
-              callback()
-            }
-          },
+          validator: (rule: any, value: string, callback: (e?: Error) => void) => {
+            // Skip validation for update events
+            if (isUpdateEvent.value) {
+              return callback()
+            }
+            // Apply pattern validation for regular events
+            const isValid = rule.pattern.test(value)
+            callback(isValid ? undefined : new Error(rule.message))
+          },
           trigger: 'change'
         }
       ]
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4828607 and 9499d53.

📒 Files selected for processing (1)
  • packages/plugins/block/src/BlockEventForm.vue (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: push-check
🔇 Additional comments (6)
packages/plugins/block/src/BlockEventForm.vue (6)

42-42: LGTM: Imports are correctly structured.

All new imports are properly organized and necessary for the new functionality.

Also applies to: 44-51


57-59: LGTM: Component registration is correct.

The new components are properly registered and follow the established pattern.


62-66: LGTM: Reactive state initialization looks good.

The reactive state object is well-structured and uses appropriate getter functions for initialization.


96-96: LGTM: Clean computed property implementation.

The isUpdateEvent computed property is simple, efficient, and clearly serves its purpose.


136-136: LGTM: Return statement properly includes new properties.

All new reactive properties and methods are correctly included in the return statement.

Also applies to: 143-145


158-186: LGTM: CSS styles are well-structured and accessible.

The styles provide good visual feedback and follow accessibility best practices by properly styling disabled states and hover effects.

@chilingling
Copy link
Member

截屏2025-06-10 19 25 15
屏幕宽度窄的时候,会被遮挡,可以考虑下 suffix 插槽实现,或者是增加白色背景

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Screenshot 2025-06-10 19 25 15
When the screen width is narrow, it will be blocked. You can consider using the suffix slot, or add a white background.

- 将 popover 触发方式从 hover 改为 manual,让showPopover正确响应
- 修复不安全的 hasOwnProperty
@chilingling
Copy link
Member

image

需要监听外部点击事件,在恰当的时机关闭该 popup

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


image

You need to listen for external click events and close the popup at the right time.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/plugins/block/src/BlockEventForm.vue (1)

116-120: Type-safety & error-handling for usePropertysToBeEvent still missing

The earlier review already requested a typed signature plus guard logic; the current code is unchanged.
Please address the original suggestion (see past comments).

🧹 Nitpick comments (2)
packages/plugins/block/src/BlockEventForm.vue (2)

5-13: Popover never closes on outside-click → switch off manual trigger

With trigger="manual" the popover stays open until the user re-clicks the icon or the collapse watcher fires.
This violates the UX feedback recorded in the PR description (“popup should close when clicking outside”).
Let TinyPopover handle this natively instead of rebuilding it ourselves.

-<tiny-popover v-model="state.showPopover" placement="bottom-end" trigger="manual">
+<tiny-popover
+  v-model="state.showPopover"
+  placement="bottom-end"
+  trigger="click"           <!-- built-in outside-click handling -->
+  @clickoutside="state.showPopover = false"
+>

Small change, large usability win.


177-181: Redundant selector in :deep rule

.tiny-input__inner.tiny-input__inner duplicates the class name.

-  :deep(.tiny-input__inner.tiny-input__inner) {
+  :deep(.tiny-input__inner) {

Minor tidy-up, no functional impact.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6de4b5c and 2361540.

📒 Files selected for processing (2)
  • packages/plugins/block/src/BlockEventForm.vue (5 hunks)
  • packages/plugins/block/src/BlockSetting.vue (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/plugins/block/src/BlockSetting.vue

Comment on lines +65 to +69
const state = reactive({
showPopover: false,
propertys: getEditBlockPropertyList(),
events: getEditBlockEvents()
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

propertys and events snapshot on mount → lose reactivity later

Both lists are fetched once and frozen inside state.
Any subsequent changes (e.g. user edits the block-schema in another panel) won’t propagate to the popover.

-const state = reactive({
-  showPopover: false,
-  propertys: getEditBlockPropertyList(),
-  events: getEditBlockEvents()
-})
+const propertys = computed(() => getEditBlockPropertyList())
+const events    = computed(() => getEditBlockEvents())
+
+const state = reactive({
+  showPopover: false
+})

Adapt template/computed usages to propertys.value / events.value.
Fixes stale data without extra watchers.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const state = reactive({
showPopover: false,
propertys: getEditBlockPropertyList(),
events: getEditBlockEvents()
})
// replace the original block:
-const state = reactive({
- showPopover: false,
- propertys: getEditBlockPropertyList(),
- events: getEditBlockEvents()
-})
// with:
const propertys = computed(() => getEditBlockPropertyList())
const events = computed(() => getEditBlockEvents())
const state = reactive({
showPopover: false
})
🤖 Prompt for AI Agents
In packages/plugins/block/src/BlockEventForm.vue around lines 65 to 69, the
state object initializes propertys and events by calling
getEditBlockPropertyList() and getEditBlockEvents() once, losing reactivity on
updates. To fix this, change propertys and events to refs holding the lists, and
update all template and computed references to use propertys.value and
events.value to maintain reactivity without adding watchers.

Comment on lines +127 to +135
validator: (rule: any /* IFormInnerRule */, value: string, callback: (e?: Error) => void) => {
if (isUpdateEvent.value) return callback()
if (!rule.pattern.test(value)) {
callback(new Error(rule.message))
} else {
callback()
}
},
trigger: 'change'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validation skips all onUpdate: cases, including malformed names

Currently any string that merely starts with onUpdate: passes, even onUpdate: (empty property).
Consider enforcing onUpdate:<validProp> instead of bypassing the regex completely.

-if (isUpdateEvent.value) return callback()
+if (isUpdateEvent.value) {
+  const matched = /^onUpdate:[a-zA-Z_$][\w$]*$/.test(value)
+  return matched ? callback() : callback(new Error('无效的 onUpdate 事件名'))
+}

Prevents silent acceptance of invalid update events.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
validator: (rule: any /* IFormInnerRule */, value: string, callback: (e?: Error) => void) => {
if (isUpdateEvent.value) return callback()
if (!rule.pattern.test(value)) {
callback(new Error(rule.message))
} else {
callback()
}
},
trigger: 'change'
validator: (rule: any /* IFormInnerRule */, value: string, callback: (e?: Error) => void) => {
if (isUpdateEvent.value) {
const matched = /^onUpdate:[a-zA-Z_$][\w$]*$/.test(value)
return matched
? callback()
: callback(new Error('无效的 onUpdate 事件名'))
}
if (!rule.pattern.test(value)) {
callback(new Error(rule.message))
} else {
callback()
}
},
trigger: 'change'
🤖 Prompt for AI Agents
In packages/plugins/block/src/BlockEventForm.vue around lines 127 to 135, the
validator function currently skips validation for all strings starting with
"onUpdate:", allowing invalid or empty event names to pass. Modify the validator
to enforce that strings beginning with "onUpdate:" must be followed by a valid
property name matching the regex pattern, rather than bypassing validation
entirely. This ensures only properly formatted update events are accepted.

@chilingling
Copy link
Member

  1. 建议弹窗收起的监听不仅仅是监听事件设置项的收起。可以尝试监听全局的点击收起,或者是使用 TinyPopover 的 click,会自动收起。

问题示例1:点击之后不收起设置设置弹窗,点击具体的属性设置,弹窗位置显示在了属性设置的面板。(属性设置面板被拉长了)
image

问题示例2:
删除当前编辑事件,弹窗不收起
截屏2025-06-19 14 30 09

@0x7A7A6572
Copy link
Contributor Author

之前有尝试过,TinyPopover 的 click 也解决不了这问题,监听面板全局的收起变化可以,或者用回TinyPopover 的 hover(确认不会自动关闭),我先按照全局收起变化的方案修改

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


I have tried it before, and the click of TinyPopover cannot solve this problem. You can listen to the global folding changes of the panel, or use the TinyPopover hover (confirm that it will not be closed automatically). I will first modify it according to the global folding changes plan.

@0x7A7A6572
Copy link
Contributor Author

全局收起还不够,如 问题示例1 ,或者是其他的会更改布局的操作,无法得到好的解决,再多加事件监听反而偏离主题了,有什么好的建议吗,舍弃一部分的操作体验使用 hover 可能好一些?

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


It is not enough to close the globally. For example, in question example 1, or other operations that will change the layout, which cannot be solved well. Adding more event monitoring will deviate from the topic. Are there any good suggestions? It may be better to abandon some of the operation experience and use hover?

添加showPopover状态控制悬浮框的显示,通过对 popover内容显隐使 popover 失去焦点,以达成关闭动作
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants