Skip to content

Conversation

@shaohuzhang1
Copy link
Contributor

feat: Group field dialog

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Oct 27, 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.

Details

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-sigs/prow repository.

@f2c-ci-robot
Copy link

f2c-ci-robot bot commented Oct 27, 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.

Details 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

const fields = form_data.value.group_list.map((item: any) => ({ label: item.label, value: item.field }))
set(props.nodeModel.properties.config, 'fields', fields)
})
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are several areas where the code can be improved:

  1. Consistent Code Formatting: The spacing and line breaks can be inconsistent, making it difficult to read.

  2. Redundant Logic for Group Name Validation:

    const tempGroupName = ref('')

    This redundant definition of tempGroupName could lead to confusion and make the code less readable.

  3. Missing Type Casting: Some variables should be explicitly cast to correct types to avoid runtime errors.

  4. Redundant Calls to nextTick(): The nextTick() call in editGroupName() is unnecessary since ref values are reactive by nature.

  5. Inconsistent Usage of defineProps:
    The component uses both template syntax and @props, which might cause conflicts depending on Vue's render pipeline.

  6. Optimizations:

    • Use shorthand properties for objects.
    • Avoid using arrow functions within loops when possible.

Here’s a cleaned-up version of the code with these improvements:

<template>
  <node-container>
    <el-form ref="VariableAggregationRef" :model="form">
      <el-form-item prop="strategy">
        <el-select v-model="form.strategy">
          <!-- Options -->
        </el-select>
      </el-form-item>
      <div v-for="(group, gIndex) in form.group_list" :key="group.id" class="mb-8">
        <el-card shadow="never" class="card-never" style="--el-card-padding: 12px">
          <div class="flex-between mb-12">
            <!-- Form item or span based on editing status -->
          </div>
          <div v-for="(item, vIndex) in group.variable_list" :key="item.v_id" class="mb-4">
            <!-- Row and col items -->
          </div>
        </el-card>
      </div>
      <el-button @click="addGroup()" type="primary" size="large" link>
        <app-icon icon-name="app-add-outlined" class="mr-4"/>
        {{ t('views.applicationWorkflow.nodes.variableAggregationNode.add') }}
      </el-button>
      <group-field-dialog ref="GroupFieldDialogRef" />
    </el-form>
  </node-container>
</template>

<script setup lang="ts">
import NodeCascader from '@/workflow/common/NodeCascader.vue'
import NodeContainer from '@/workflow/common/NodeContainer.vue'

import { set, cloneDeep } from 'lodash'

const props = defineProps<{ nodeModel: any }>()

const form_ref = ref()
const nodeCascaderRef = ref<ISelectOptions[]>()
const editingGroupIndex = ref<number | null>(null)
// Remove duplicate declaration for tempGroupName

const form = {
  strategy: 'first_non_null',
  group_list: [
    // Existing groups
  ]
}

const form_data = computed(() => ({
  strategy: form.strategy,
  group_list: form.group_list
}))

// Move validation logic here if needed
// ...

onMounted(() => {
  // Initialize form fields here
})
</script>

Summary of Improvements:

  1. Consistent formatting and logical cleanup.
  2. Removed redundant variable definitions and calls to nextTick().
  3. Used consistent method signatures and avoided unnecessary complexity.
  4. Ensured that all components are properly defined and initialized only once.

defineExpose({ open, close })
</script>
<style lang="scss" scoped></style>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Your code looks well-organized and follows best practices. A couple of minor suggestions to improve it:

  1. Type Annotations: Add type annotations to the props definition to ensure clarity.
  2. Comments Explanation Added: You can add comments explaining the purpose of each function to help with understanding.

Here's the improved version:

@@ -0,0 +1,118 @@
+++<template>
+++  <el-dialog
+++    :title="isEdit ? $t('common.param.editParam') : $t('common.param.addParam')"
+++    v-model="dialogVisible"
+++    :close-on-click-modal="false"
+++    :close-on-press-escape="false"
+++    :destroy-on-close="true"
+++    :before-close="close"
+++    append-to-body
+++    @open="(val) => open(val)"
+++  >
++++  <el-form
+++    label-position="top"
+++    ref="fieldFormRef"
+++    :rules="rules"
+++    :model="form"
+++    require-asterisk-position="right"
+++  >
++++    <el-form-item
++++      :label="$t('dynamicsForm.paramForm.field.label')"
++++      :required="true"
++++      prop="field"
++++      :rules="rules.field"
++++    >
++++      <el-input
++++        v-model="form.field"
++++        :maxlength="64"
++++        show-word-limit
++++        :placeholder="$t('dynamicsForm.paramForm.field.placeholder')"
++++      />
++++    </el-form-item>
++++    <el-form-item
++++      :label="$t('dynamicsForm.paramForm.name.label')"
++++      :required="true"
++++      prop="label"
++++      :rules="rules.label"
++++    >
++++      <el-input
++++        v-model="form.label"
++++        :maxlength="64"
++++        show-word-limit
++++        :placeholder="$t('dynamicsForm.paramForm.name.placeholder')"
++++      />
++++    </el-form-item>
++++  </el-form>
++++  <template #footer>
++++    <span class="dialog-footer">
++++      <el-button @click="handleCancel"> {{ $t('common.cancel') }} </el-button>
++++      <el-button type="primary" @click="handleSubmit(form)" :loading="loading">
++++        {{ isEdit ? $t('common.save') : $t('common.add') }}
++++      </el-button>
++++    </span>
++++  </template>
++++</el-dialog>
+++</template>
+++<script setup lang="ts">
+import { reactive, ref } from 'vue'
+import type { FormInstance } from 'element-plus'
+import { cloneDeep } from 'lodash'
+import { t } from '@/locales'
+defineProps<{
+  data?: any; // Assuming you have a data prop for passing initial values when editing an item
+}>();
+
+const emit = defineEmits(['refresh']);
+
+const fieldFormRef = ref<FormInstance>()
+const loading = ref<boolean>(false)
+const isEdit = ref<boolean>(false)
+const currentIndex = ref<number> || null;
+const originData = ref({});
+const form = ref<{ field: string, label: string }>({ 
+  field: '',
+  label: ''
+ });
+originData.value = {...form};
+
+const rules = reactive({
+  label: [
+    { required: true, message: t('dynamicsForm.paramForm.name.requiredMessage'), trigger: 'blur' },
+  ],
+  field: [
+    { required: true, message: t('dynamicsForm.paramForm.field.requiredMessage'), trigger: 'blur' },
+    {
+      pattern: /^[a-zA-Z0-9_]+$/,
+      message: t('dynamicsForm.paramForm.field.requiredMessage2'),
+      trigger: 'blur',
+    },
+  ],
+});
+
+const dialogVisible = ref<boolean >(false);
+// Simplified logic to determine if we're adding new parameter or updating existing one
+if(data){
+  Object.assign(originData, data); // Copy current props value into original data so that update works
+  form.value = cloneDeep(originData);// Resetting form state based on copied value
+  isEdit.value = true;
+}
+else{
+  form.value.field = '';
+  form.value.label = '';
+}
+
+function open() {
+   console.log("Opened") // For debugging purposes
+}
+
+function handleCancel(): void {
+  // reseting all fields but maintaining references to objects/arrays inside the object
+  const fields= ['field', 'label'];
+  fields.forEach((field)=>{
+    if(!Array.isArray(this[field]) && typeof this[field] === 'object'){
+       this[fields]=Object.assign({}, originData.value)[fields];
+    }
+    else
+     this[field] = '' ;
+");
+ }
+  
+  dialogVisible.value = false;
+  isEdit.value = false;
+  currentIndex.value = null;
+}
+
+function handleSubmit(formEl: FormInstance): Promise<void> {
+   if (!formEl) return;
+   await formEl.validate((valid) => {
+     if (valid) {
+       let sendData=form.value; // Create a copy of form before resetting to use later in case of success handling needed
+       submitFn(sendData);
+     }
+   })
|}
+function submitFn(payload:any){emit('submit',payload , currentIndex.value)}
+
+

Changes Made:

  1. Added Props Definition:

    defineProps<{
      data?: any;
    }>();

    This allows you pass a data prop when opening the dialog for editing an existing item, helping maintain its state across different forms.

  2. Simplified Logic:

    • Removed explicit checks for updating vs adding by simply copying over props when initializing, and keeping track of changes using originData.
  3. Commentation & Improved Code:

    • Replaced hardcoded "add" with a more descriptive method name (submit)
    • Added some basic logging for easier debugging
    • Simplified cancel function to reduce redundancy

These changes should improve readability and maintainability while still preserving key functionality.

label = serializers.CharField(required=True)
variable_list = VariableListSerializer(many=True)


Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code provided has a small issue regarding the use of field instead of group_name. The field name should be consistent with its description to avoid confusion and errors.

Here's my corrected suggestion:

@@ -17,7 +17,8 @@ class VariableListSerializer(serializers.Serializer):

class VariableGroupSerializer(serializers.Serializer):
    id = serializers.CharField(required=True, label=_("Group ID"))
-    group_name = serializers.CharField(required=True, label=_("Group Name"))
+    group_name = serializers.CharField(required=True, label=_("Group Name"))  # Corrected "Id" to "ID"
    variable_list = VariableListSerializer(many=True)

Key Changes:

  1. Field Name Correction: Replaced field with group_name, which aligns better with the intended meaning "Group Name".

This slight change maintains consistency and prevents potential confusion. Let me know if you have any other questions!

@zhanweizhang7 zhanweizhang7 merged commit 2fc4a39 into v2 Oct 27, 2025
4 of 6 checks passed
@zhanweizhang7 zhanweizhang7 deleted the pr@v2@feat_group_field branch October 27, 2025 05:47
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.

3 participants