Skip to content
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

perf: optimization codemirror component #2451

Merged
merged 1 commit into from
Feb 28, 2025
Merged

Conversation

wangdan-fit2cloud
Copy link
Contributor

What this PR does / why we need it?

Summary of your change

Please indicate you've done the following:

  • Made sure tests are passing and test coverage is added if needed.
  • Made sure commit message follow the rule of Conventional Commits specification.
  • Considered the docs impact and opened a new docs issue or PR with docs changes if needed.

Copy link

f2c-ci-robot bot commented Feb 28, 2025

Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link

f2c-ci-robot bot commented Feb 28, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@@ -212,6 +203,7 @@ function submitDialog(val: string) {
const replyNodeFormRef = ref()
const nodeCascaderRef = ref()
const nodeCascaderRef2 = ref()

const validate = async () => {
// console.log(replyNodeFormRef.value.validate())
let ps = [
Copy link
Contributor

Choose a reason for hiding this comment

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

The provided code has several issues and improvements that can be made:

  1. hide-required-asterisk Property: This property was added to an incorrect context (require-asterisk-position="right" is on a b-form-group, but here it's being set on the outer el-form). It should be removed since it doesn't have any effect in this scenario.

  2. Conditional Rendering of Variable Assignation Options:

    • The custom variable input fields are wrapped inside two conditions that prevent rendering if item.source === 'referring'. However, when the user chooses 'reference', they still need to see at least the placeholder and cascading selection widget, so remove these conditional renders.
    <!-- Remove the below lines -->
    <!-- <div v-if="item.source === 'referring'" class="flex"> ... </div> -->
    <!-- <NodeCascader ref="nodeCascaderRef2" ... /> -->
    
  3. Custom Input Field Type Selection Logic:

    • Set default values for different types to ensure proper behavior:
      • For "string", initialize with an empty string rather than null.
        <el-input v-model="item.value" :placeholder="$t('common.inputPlaceholder')" show-word-limit clearable @wheel="wheel"></el-input>
      • For "num", initialize with zero.
        <el-input-number v-model="item.value"></el-input-number>
    <!-- Ensure correct initialization before changing value -->
    item.type === "string" && (item.value = ""),
    item.type === "num" && (item.value = 0),
    item.type === "json" && (item.value = '{}'),
  4. Error Handling for Invalid JSON:

    • Improve error handling for invalid JSON by providing more specific validation logic. Instead of always using new Error to indicate failure, handle parsing errors correctly based on the actual reason.
    const isValidJSON = (val: string): boolean => {
      try {
        JSON.parse(val);
        return true;
      } catch (error) {
        console.error(`Invalid JSON format: ${error.message}`);
        return false;
      }
    };
  5. Improve UX for Custom JSON Input:

    • Allow users to quickly paste JSON into the field directly or provide copy-paste buttons if applicable.
    <el-input
      v-model="item.value"
      type="textarea"
      autosize
      @paste="handlePaste"
      @focus="(val) => { focusedJsonInput = val }"
      @blur="resetFocusJsonInput()"
    ></el-input>
    <el-button @click="copyToJsonString()">Copy to String</el-button>
  6. Add Event Listeners to Node Cascaders:

    • Ensure all necessary event listeners such as select events are properly initialized when creating components.
    // Initialize node cascade component after creating refs
    watch(() => form_data.variable_list, () => {
      nodeCascaderRef.value?.refresh(); // Re-initiate cascader when variable list changes
    });
  7. Optimize Form Validation Execution:

    • Run validation only when needed instead of always executing on blur like v-blur.
    const validateField = async (fieldKey: string) => {
      await replyNodeFormRef.value.validate([fieldKey]);
    };
    
    const addVariableListenerToInputs = () => {
      [...document.querySelectorAll('.el-form-item__input-wrap .el-input')]
        .filter(el => el instanceof HTMLElement)
        .forEach(inputEl => {
          inputEl.addEventListener('input', async () => {
            const key = Array.from(
              document
                .querySelectorAll<HTMLInputElement>(
                  `.el-form-item[data-index="${indexOfItemInVariablesArray}"].el-form-item`
                )
              ).map(inputWrapper => inputWrapper.querySelector(':scope > div:nth-child(2)'))[0]
                ?.getAttribute('data-key');
            
            if (!key || !form_data[key]) {
              return; 
            }
    
            await validateField(key); // Call validation only on change
          });
        });
    
        [...document.querySelectorAll('.el-form-item__content div:last-child .el-form'])
          .filter((wrapper: HTMLDivElement) => wrapper.children.length >= 19)
          .forEach(form =>
            [".el-form", ".el-select-dropdown", ".el-date-picker"] &&
              Array.from(form.childNodes).some(node => node.matches(".el-form"))
              ? form.addEventListener("scroll", () =>
                requestAnimationFrame(validateField)
              )
              : null
          );
    };

These suggestions will help improve the readability and functionality of the Vue.js application while addressing common design principles.

@wangdan-fit2cloud wangdan-fit2cloud merged commit 89792d5 into main Feb 28, 2025
4 checks passed
@wangdan-fit2cloud wangdan-fit2cloud deleted the pr@main/codemirror branch February 28, 2025 14:42
right: 10px;
}
}
</style>
Copy link
Contributor

Choose a reason for hiding this comment

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

The code you've provided appears clean and organized for use with Vue.js along with vue-codemirror. It introduces several improvements over the original:

  1. State Management Using Computed and Watch: The data property is now managed using both Computed properties (computed) and Watchers to efficiently keep the codemirror value synced between props and internal states.

  2. Fullscreen Dialog Integration: A new El-dialog component (El-dialog's "full-screen" mode) has been added to display the same Codemirror instance in an overlay when triggered through a button click.

  3. Data Cloning and Update Handling: In the fullscreen view, the current value of the CodeMirror editor is cloned into another variable (cloneContent). When editing stops, this content is then passed back via events to update the parent component.

  4. Enhanced Styling**: Added CSS to ensure that only the main container takes up the full width while maintaining readability within its boundaries.

While these changes make the implementation more flexible and interactive, remember it might be beneficial to thoroughly test all user flows involving the pop-up dialog to verify smooth working and proper error handling in case anything goes wrong during runtime.

position: relative;
}
</style>
<style lang="scss"></style>
Copy link
Contributor

Choose a reason for hiding this comment

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

The code looks generally correct but has a few improvements that can be made:

  • Remove the append-to-body attribute from the <el-dialog> component. It's not necessary in this context.
  • Use CSS grid instead of flexbox to align the form items and buttons more cleanly.
  • Add some padding to the .mb-8 class to make it look better.
  • Consider adding validation error messages directly inside the input fields, as opposed to using separate message placeholders.

Here is updated version of the code with these improvements:

<style lang="scss">

.mb-8 {
  margin-bottom: 1rem;
}

.field-item {
  display: grid;
  gap: 0.5rem;

  & > .form-label-group {
    width: 35%;
  }

  & > .form-input-group {
    width: 65%;
  }
}

</style>
... (rest of the template remains the same)
</template>
<script setup lang="ts">
...
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants