mirror of https://github.com/halo-dev/halo
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
parent
2469043248
commit
bfbca99f1b
|
@ -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"
|
||||||
|
|
|
@ -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')"
|
||||||
|
|
Loading…
Reference in New Issue