refactor: update attachment policy form using new configMap API (#7531)

#### What type of PR is this?

/area ui
/kind improvement
/milestone 2.21.x

#### What this PR does / why we need it:

Update attachment policy form using new configMap API

#### Does this PR introduce a user-facing change?

```release-note
None
```
pull/7533/head v2.21.0-beta.2
Ryan Wang 2025-06-10 17:58:35 +08:00 committed by GitHub
parent 2469043248
commit bfbca99f1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 105 additions and 85 deletions

View File

@ -68,12 +68,18 @@ spec:
value: ARCHIVE value: ARCHIVE
- $formkit: checkbox - $formkit: checkbox
name: alwaysRenameFilename name: alwaysRenameFilename
id: alwaysRenameFilename
label: 是否总是重命名文件名 label: 是否总是重命名文件名
help: 勾选后上传后的文件名将被重命名 help: 勾选后上传后的文件名将被重命名
value: false
- $formkit: group - $formkit: group
if: $alwaysRenameFilename if: $get(alwaysRenameFilename).value
id: renameStrategy
name: renameStrategy name: renameStrategy
label: 重命名策略 label: 重命名策略
value:
method: RANDOM
randomLength: 32
children: children:
- $formkit: radio - $formkit: radio
name: method name: method
@ -87,8 +93,9 @@ spec:
value: TIMESTAMP value: TIMESTAMP
- $formkit: number - $formkit: number
number: integer number: integer
if: $renameStrategy.renameMethod === RANDOM if: "$value.method === RANDOM"
name: randomLength name: randomLength
id: randomLength
label: 随机文件名长度 label: 随机文件名长度
help: 默认值为 32。因为文件名的长度限制随机文件名的长度范围为 [8, 64]。 help: 默认值为 32。因为文件名的长度限制随机文件名的长度范围为 [8, 64]。
validation: "between:8,64" validation: "between:8,64"

View File

@ -1,15 +1,16 @@
<script lang="ts" setup> <script lang="ts" setup>
import SubmitButton from "@/components/button/SubmitButton.vue"; import SubmitButton from "@/components/button/SubmitButton.vue";
import { setFocus } from "@/formkit/utils/focus"; import { setFocus } from "@/formkit/utils/focus";
import { useSettingFormConvert } from "@console/composables/use-setting-form"; import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
import type { Policy } from "@halo-dev/api-client"; import type { Policy } from "@halo-dev/api-client";
import { coreApiClient } from "@halo-dev/api-client"; import { consoleApiClient, coreApiClient } from "@halo-dev/api-client";
import { Toast, VButton, VLoading, VModal, VSpace } from "@halo-dev/components"; import { Toast, VButton, VLoading, VModal, VSpace } from "@halo-dev/components";
import { useQuery } from "@tanstack/vue-query"; import { useQuery } from "@tanstack/vue-query";
import { cloneDeep } from "lodash-es";
import { computed, onMounted, ref, toRaw, toRefs } from "vue"; import { computed, onMounted, ref, toRaw, toRefs } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
const CONFIG_MAP_GROUP = "default";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
policy?: Policy; policy?: Policy;
@ -31,55 +32,36 @@ const { t } = useI18n();
const modal = ref<InstanceType<typeof VModal> | null>(null); const modal = ref<InstanceType<typeof VModal> | null>(null);
const formState = ref<Policy>({ const isUpdateMode = computed(() => !!props.policy);
spec: {
displayName: "",
templateName: "",
configMapName: "",
},
apiVersion: "storage.halo.run/v1alpha1",
kind: "Policy",
metadata: {
name: "",
generateName: "attachment-policy-",
},
});
const isUpdateMode = !!props.policy;
onMounted(async () => { onMounted(async () => {
if (props.policy) {
formState.value = cloneDeep(props.policy);
}
if (props.templateName) {
formState.value.spec.templateName = props.templateName;
}
setFocus("displayNameInput"); setFocus("displayNameInput");
}); });
const templateName = computed(() => {
return props.policy?.spec.templateName || props.templateName;
});
const { data: policyTemplate } = useQuery({ const { data: policyTemplate } = useQuery({
queryKey: [ queryKey: ["core:attachment:policy-template", templateName],
"core:attachment:policy-template",
formState.value.spec.templateName,
],
cacheTime: 0, cacheTime: 0,
queryFn: async () => { queryFn: async () => {
if (!templateName.value) {
throw new Error("No template name found");
}
const { data } = const { data } =
await coreApiClient.storage.policyTemplate.getPolicyTemplate({ await coreApiClient.storage.policyTemplate.getPolicyTemplate({
name: formState.value.spec.templateName, name: templateName.value,
}); });
return data; return data;
}, },
retry: 0, retry: 0,
enabled: computed(() => !!formState.value.spec.templateName), enabled: computed(() => !!templateName.value),
}); });
const { data: setting, isLoading } = useQuery({ const { data: setting, isLoading } = useQuery({
queryKey: [ queryKey: ["core:attachment:policy-template:setting", policyTemplate],
"core:attachment:policy-template:setting",
policyTemplate.value?.spec?.settingName,
],
cacheTime: 0, cacheTime: 0,
queryFn: async () => { queryFn: async () => {
if (!policyTemplate.value?.spec?.settingName) { if (!policyTemplate.value?.spec?.settingName) {
@ -96,61 +78,72 @@ const { data: setting, isLoading } = useQuery({
enabled: computed(() => !!policyTemplate.value?.spec?.settingName), enabled: computed(() => !!policyTemplate.value?.spec?.settingName),
}); });
const { data: configMap } = useQuery({ const { data: configMapGroupData } = useQuery({
queryKey: [ queryKey: ["core:attachment:policy-template:configMap", policy],
"core:attachment:policy-template:configMap",
policy.value?.spec.configMapName,
],
cacheTime: 0, cacheTime: 0,
initialData: {
data: {},
apiVersion: "v1alpha1",
kind: "ConfigMap",
metadata: {
generateName: "configMap-",
name: "",
},
},
retry: 0, retry: 0,
queryFn: async () => { queryFn: async () => {
if (!policy.value?.spec.configMapName) { if (!policy.value) {
throw new Error("No configMap found"); return {};
} }
const { data } = await coreApiClient.configMap.getConfigMap({
name: policy.value?.spec.configMapName, const { data } =
}); await consoleApiClient.storage.policy.getPolicyConfigByGroup({
return data; name: policy.value.metadata.name,
group: CONFIG_MAP_GROUP,
});
return (data || {}) as Record<string, unknown>;
}, },
enabled: computed(() => !!policy.value?.spec.configMapName),
}); });
const { configMapFormData, formSchema, convertToSave } = useSettingFormConvert( const formSchema = computed(() => {
setting, if (!setting.value) {
configMap, return;
ref("default") }
); const { forms } = setting.value.spec;
return forms.find((item) => item.group === CONFIG_MAP_GROUP)?.formSchema as (
| FormKitSchemaCondition
| FormKitSchemaNode
)[];
});
const submitting = ref(false); const isSubmitting = ref(false);
const handleSave = async () => { const handleSave = async (data: {
displayName: string;
[key: string]: unknown;
}) => {
console.log(data);
try { try {
submitting.value = true; isSubmitting.value = true;
const configMapToUpdate = convertToSave(); if (isUpdateMode.value) {
if (isUpdateMode) { if (!policy.value) {
await coreApiClient.configMap.updateConfigMap({ throw new Error("No policy found");
name: configMap.value.metadata.name, }
configMap: configMapToUpdate,
await consoleApiClient.storage.policy.updatePolicyConfigByGroup({
name: policy.value.metadata.name,
group: CONFIG_MAP_GROUP,
body: data,
}); });
await coreApiClient.storage.policy.updatePolicy({ await coreApiClient.storage.policy.updatePolicy({
name: formState.value.metadata.name, name: policy.value.metadata.name,
policy: formState.value, policy: {
...policy.value,
spec: {
...policy.value.spec,
displayName: data.displayName,
},
},
}); });
} else { } else {
const { data: policies } = const { data: policies } =
await coreApiClient.storage.policy.listPolicy(); await coreApiClient.storage.policy.listPolicy();
const hasDisplayNameDuplicate = policies.items.some( const hasDisplayNameDuplicate = policies.items.some(
(policy) => policy.spec.displayName === formState.value.spec.displayName (policy) => policy.spec.displayName === data.displayName
); );
if (hasDisplayNameDuplicate) { if (hasDisplayNameDuplicate) {
@ -159,15 +152,36 @@ const handleSave = async () => {
); );
return; return;
} }
const { data: newConfigMap } = const { data: newConfigMap } =
await coreApiClient.configMap.createConfigMap({ await coreApiClient.configMap.createConfigMap({
configMap: configMapToUpdate, configMap: {
data: {
[CONFIG_MAP_GROUP]: JSON.stringify(data),
},
apiVersion: "v1alpha1",
kind: "ConfigMap",
metadata: {
generateName: "configMap-",
name: "",
},
},
}); });
formState.value.spec.configMapName = newConfigMap.metadata.name;
await coreApiClient.storage.policy.createPolicy({ await coreApiClient.storage.policy.createPolicy({
policy: formState.value, policy: {
spec: {
displayName: data.displayName,
templateName: templateName.value as string,
configMapName: newConfigMap.metadata.name,
},
apiVersion: "storage.halo.run/v1alpha1",
kind: "Policy",
metadata: {
name: "",
generateName: "attachment-policy-",
},
},
}); });
} }
@ -176,7 +190,7 @@ const handleSave = async () => {
} catch (e) { } catch (e) {
console.error("Failed to save attachment policy", e); console.error("Failed to save attachment policy", e);
} finally { } finally {
submitting.value = false; isSubmitting.value = false;
} }
}; };
@ -200,11 +214,10 @@ const modalTitle = props.policy
<VLoading v-if="isLoading" /> <VLoading v-if="isLoading" />
<template v-else> <template v-else>
<FormKit <FormKit
v-if="formSchema && configMapFormData" v-if="formSchema && configMapGroupData"
id="attachment-policy-form" id="attachment-policy-form"
v-model="configMapFormData['default']" :value="toRaw(configMapGroupData) || {}"
name="attachment-policy-form" name="attachment-policy-form"
:actions="false"
:preserve="true" :preserve="true"
type="form" type="form"
:config="{ validationVisibility: 'submit' }" :config="{ validationVisibility: 'submit' }"
@ -212,7 +225,7 @@ const modalTitle = props.policy
> >
<FormKit <FormKit
id="displayNameInput" id="displayNameInput"
v-model="formState.spec.displayName" :value="policy?.spec.displayName"
:label=" :label="
$t( $t(
'core.attachment.policy_editing_modal.fields.display_name.label' 'core.attachment.policy_editing_modal.fields.display_name.label'
@ -224,7 +237,7 @@ const modalTitle = props.policy
></FormKit> ></FormKit>
<FormKitSchema <FormKitSchema
:schema="toRaw(formSchema)" :schema="toRaw(formSchema)"
:data="configMapFormData['default']" :data="toRaw(configMapGroupData) || {}"
/> />
</FormKit> </FormKit>
</template> </template>
@ -233,7 +246,7 @@ const modalTitle = props.policy
<template #footer> <template #footer>
<VSpace> <VSpace>
<SubmitButton <SubmitButton
:loading="submitting" :loading="isSubmitting"
type="secondary" type="secondary"
:text="$t('core.common.buttons.submit')" :text="$t('core.common.buttons.submit')"
@submit="$formkit.submit('attachment-policy-form')" @submit="$formkit.submit('attachment-policy-form')"