mirror of https://github.com/halo-dev/halo
				
				
				
			feat: add AnnotationsForm Component to edit extension annotations (halo-dev/console#770)
#### What type of PR is this? /kind feature #### What this PR does / why we need it: 提供一个 Annotations 编辑组件,支持由主题或者插件提供表单定义,也支持使用者自定义 key-value,用于扩展资源字段。 #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2858 #### Screenshots: <img width="789" alt="image" src="https://user-images.githubusercontent.com/21301288/209517622-80111fd2-8e79-480f-8ca0-9f7073300b2b.png"> #### Special notes for your reviewer: 测试方式: 1. 将一下内容放到任意一个主题下,后缀为 `yaml`,文件名随意。 ```yaml spec: targetRef: group: content.halo.run kind: Post formSchema: - $formkit: "text" name: "download" label: "下载地址" - $formkit: "text" name: "version" label: "版本" apiVersion: v1alpha1 kind: AnnotationSetting metadata: generateName: annotation- ``` 3. 后端需要使用 https://github.com/halo-dev/halo/pull/3028 4. 测试为文章设置 Annotations 和自定义的 Annotations。 5. 检查是否可以设置正常。 #### Does this PR introduce a user-facing change? ```release-note 文章设置支持设置元数据。 ```pull/3445/head
							parent
							
								
									fb1465484a
								
							
						
					
					
						commit
						edd2d90c5b
					
				| 
						 | 
				
			
			@ -39,8 +39,9 @@
 | 
			
		|||
    "@formkit/inputs": "^1.0.0-beta.12",
 | 
			
		||||
    "@formkit/themes": "^1.0.0-beta.12",
 | 
			
		||||
    "@formkit/utils": "^1.0.0-beta.12",
 | 
			
		||||
    "@formkit/validation": "1.0.0-beta.12",
 | 
			
		||||
    "@formkit/vue": "^1.0.0-beta.12",
 | 
			
		||||
    "@halo-dev/api-client": "^0.0.62",
 | 
			
		||||
    "@halo-dev/api-client": "0.0.64",
 | 
			
		||||
    "@halo-dev/components": "workspace:*",
 | 
			
		||||
    "@halo-dev/console-shared": "workspace:*",
 | 
			
		||||
    "@halo-dev/richtext-editor": "^0.0.0-alpha.17",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,8 +11,9 @@ importers:
 | 
			
		|||
      '@formkit/inputs': ^1.0.0-beta.12
 | 
			
		||||
      '@formkit/themes': ^1.0.0-beta.12
 | 
			
		||||
      '@formkit/utils': ^1.0.0-beta.12
 | 
			
		||||
      '@formkit/validation': 1.0.0-beta.12
 | 
			
		||||
      '@formkit/vue': ^1.0.0-beta.12
 | 
			
		||||
      '@halo-dev/api-client': ^0.0.62
 | 
			
		||||
      '@halo-dev/api-client': 0.0.64
 | 
			
		||||
      '@halo-dev/components': workspace:*
 | 
			
		||||
      '@halo-dev/console-shared': workspace:*
 | 
			
		||||
      '@halo-dev/richtext-editor': ^0.0.0-alpha.17
 | 
			
		||||
| 
						 | 
				
			
			@ -105,8 +106,9 @@ importers:
 | 
			
		|||
      '@formkit/inputs': 1.0.0-beta.12-e579559
 | 
			
		||||
      '@formkit/themes': 1.0.0-beta.12-e579559_tailwindcss@3.2.4
 | 
			
		||||
      '@formkit/utils': 1.0.0-beta.12-e579559
 | 
			
		||||
      '@formkit/validation': 1.0.0-beta.12
 | 
			
		||||
      '@formkit/vue': 1.0.0-beta.12-e579559_ior6jr3fpijijuwpr34w2i25va
 | 
			
		||||
      '@halo-dev/api-client': 0.0.62
 | 
			
		||||
      '@halo-dev/api-client': 0.0.64
 | 
			
		||||
      '@halo-dev/components': link:packages/components
 | 
			
		||||
      '@halo-dev/console-shared': link:packages/shared
 | 
			
		||||
      '@halo-dev/richtext-editor': 0.0.0-alpha.17_vue@3.2.45
 | 
			
		||||
| 
						 | 
				
			
			@ -1874,6 +1876,12 @@ packages:
 | 
			
		|||
      '@floating-ui/core': 0.3.1
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/core/1.0.0-beta.12:
 | 
			
		||||
    resolution: {integrity: sha512-/Pod7k4N58eDOG+0LE0ccV7BOYD5sEA4RqaRNJn9m6Jg9nF/JATmSNL46kVCH3mV6sSoV045L3Zir8//rya0Lw==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@formkit/utils': 1.0.0-beta.12
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/core/1.0.0-beta.12-e579559:
 | 
			
		||||
    resolution: {integrity: sha512-y90ubMcFr6WtAjZqUOLgA3p4jm024f6R7iDRVKHsmdwSKm1/GZl4D+Yo2k8DL40xM7NbZhIvK40MiEC0pNZ3ig==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -1901,6 +1909,13 @@ packages:
 | 
			
		|||
      '@formkit/core': 1.0.0-beta.12-e579559
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/observer/1.0.0-beta.12:
 | 
			
		||||
    resolution: {integrity: sha512-kXVWUkjbNsymwv50QuI5thjlCknGy8azPlzepTDj3fsuZANuHG8qaj3W5h9mY6cCgvil4d4WeBz5f54iJsaEXA==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@formkit/core': 1.0.0-beta.12
 | 
			
		||||
      '@formkit/utils': 1.0.0-beta.12
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/observer/1.0.0-beta.12-e579559:
 | 
			
		||||
    resolution: {integrity: sha512-6Nki4VmUN3OyU70N6AIttvn/ScZXq5mwv11BIYLgfsfiMI5zoiflmNHrD7yf4KTUVvz16ThJB5nRGIXlnUnH3Q==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -1934,10 +1949,21 @@ packages:
 | 
			
		|||
      tailwindcss: 3.2.4_postcss@8.4.19
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/utils/1.0.0-beta.12:
 | 
			
		||||
    resolution: {integrity: sha512-L2P221teC+58Y1A4TZpJsLt/Y+WErLxbBt4hH6XhokssVX7mYR56YWienY9StN5jmiGVWtcK1+riXCb0n1aMOA==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/utils/1.0.0-beta.12-e579559:
 | 
			
		||||
    resolution: {integrity: sha512-4yTz4IRzPX3G08aAO+ZfEuBYfy6OSgk3csx3TBhOcL6NzyIbJkTc2ZsxaUYXgY6FOVclazLGMKM5+jBitMOL5Q==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/validation/1.0.0-beta.12:
 | 
			
		||||
    resolution: {integrity: sha512-ZSD5llsfSqXfIYMtSeeDwx7h421JCKobi00RxpGJkuHgpnAi3oxTJB7J6u+3pMrO9BqcidGtk5G/rk9F4fCNEw==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
      '@formkit/core': 1.0.0-beta.12
 | 
			
		||||
      '@formkit/observer': 1.0.0-beta.12
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@formkit/validation/1.0.0-beta.12-e579559:
 | 
			
		||||
    resolution: {integrity: sha512-f/S0LefikeBZRxKkjx1fD7RODXMHglg6+B1NUYEKsEKc3ySjH/V9/XroaPszXfkupAnVBSTjZXG7T9hmn39VVA==}
 | 
			
		||||
    dependencies:
 | 
			
		||||
| 
						 | 
				
			
			@ -1966,8 +1992,8 @@ packages:
 | 
			
		|||
      - windicss
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@halo-dev/api-client/0.0.62:
 | 
			
		||||
    resolution: {integrity: sha512-LVoAH4/+8iHxqHf7X6Ax3wy+IRSB2Tm9IC3zhfGdnbrdgyn/NnnpRIhTCKo6cK0Sr2j/3W4Pvmc0xCWNVzNAyw==}
 | 
			
		||||
  /@halo-dev/api-client/0.0.64:
 | 
			
		||||
    resolution: {integrity: sha512-zzhTdRi4p7nRsWG7u85YCkoHZLHsbpuWeBCwLl5FSXxY8ruKuiOo0FypkS7Ll7505XASk4MJL6rsyeX+l7rLmQ==}
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /@halo-dev/richtext-editor/0.0.0-alpha.17_vue@3.2.45:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,231 @@
 | 
			
		|||
<script lang="ts" setup>
 | 
			
		||||
import {
 | 
			
		||||
  reset,
 | 
			
		||||
  submitForm,
 | 
			
		||||
  type FormKitNode,
 | 
			
		||||
  type FormKitSchemaCondition,
 | 
			
		||||
  type FormKitSchemaNode,
 | 
			
		||||
} from "@formkit/core";
 | 
			
		||||
import { computed, nextTick, onMounted, ref, watch } from "vue";
 | 
			
		||||
import { apiClient } from "@/utils/api-client";
 | 
			
		||||
import type { AnnotationSetting } from "@halo-dev/api-client";
 | 
			
		||||
import cloneDeep from "lodash.clonedeep";
 | 
			
		||||
import { getValidationMessages } from "@formkit/validation";
 | 
			
		||||
import { useThemeStore } from "@/stores/theme";
 | 
			
		||||
 | 
			
		||||
const themeStore = useThemeStore();
 | 
			
		||||
 | 
			
		||||
function keyValidationRule(node: FormKitNode) {
 | 
			
		||||
  return !annotations?.[node.value as string];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const props = withDefaults(
 | 
			
		||||
  defineProps<{
 | 
			
		||||
    group: string;
 | 
			
		||||
    kind: string;
 | 
			
		||||
    value?: {
 | 
			
		||||
      [key: string]: string;
 | 
			
		||||
    } | null;
 | 
			
		||||
  }>(),
 | 
			
		||||
  {
 | 
			
		||||
    value: null,
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const annotationSettings = ref<AnnotationSetting[]>([] as AnnotationSetting[]);
 | 
			
		||||
 | 
			
		||||
const avaliableAnnotationSettings = computed(() => {
 | 
			
		||||
  return annotationSettings.value.filter((setting) => {
 | 
			
		||||
    if (!setting.metadata.labels?.["theme.halo.run/theme-name"]) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
      setting.metadata.labels?.["theme.halo.run/theme-name"] ===
 | 
			
		||||
      themeStore.activatedTheme?.metadata.name
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleFetchAnnotationSettings = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    const { data } =
 | 
			
		||||
      await apiClient.extension.annotationSetting.listv1alpha1AnnotationSetting(
 | 
			
		||||
        {
 | 
			
		||||
          labelSelector: [
 | 
			
		||||
            `halo.run/target-ref=${[props.group, props.kind].join("/")}`,
 | 
			
		||||
          ],
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    annotationSettings.value = data.items;
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.log("Failed to fetch annotation settings", error);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const annotations = ref<{
 | 
			
		||||
  [key: string]: string;
 | 
			
		||||
}>({});
 | 
			
		||||
const customAnnotationsState = ref<{ key: string; value: string }[]>([]);
 | 
			
		||||
 | 
			
		||||
const customAnnotations = computed(() => {
 | 
			
		||||
  return customAnnotationsState.value.reduce((acc, cur) => {
 | 
			
		||||
    acc[cur.key] = cur.value;
 | 
			
		||||
    return acc;
 | 
			
		||||
  }, {} as { [key: string]: string });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleProcessCustomAnnotations = () => {
 | 
			
		||||
  let formSchemas: FormKitSchemaNode[] = [];
 | 
			
		||||
 | 
			
		||||
  avaliableAnnotationSettings.value.forEach((annotationSetting) => {
 | 
			
		||||
    formSchemas = formSchemas.concat(
 | 
			
		||||
      annotationSetting.spec?.formSchema as FormKitSchemaNode[]
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  customAnnotationsState.value = Object.entries(props.value || {})
 | 
			
		||||
    .map(([key, value]) => {
 | 
			
		||||
      const fromThemeSpec = formSchemas.some((item) => {
 | 
			
		||||
        if (typeof item === "object" && "$formkit" in item) {
 | 
			
		||||
          return item.name === key;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
      });
 | 
			
		||||
      if (!fromThemeSpec) {
 | 
			
		||||
        return {
 | 
			
		||||
          key,
 | 
			
		||||
          value,
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    .filter((item) => item) as { key: string; value: string }[];
 | 
			
		||||
 | 
			
		||||
  annotations.value = Object.entries(props.value || {})
 | 
			
		||||
    .map(([key, value]) => {
 | 
			
		||||
      const fromThemeSpec = formSchemas.some((item) => {
 | 
			
		||||
        if (typeof item === "object" && "$formkit" in item) {
 | 
			
		||||
          return item.name === key;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
      });
 | 
			
		||||
      if (fromThemeSpec) {
 | 
			
		||||
        return {
 | 
			
		||||
          key,
 | 
			
		||||
          value,
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    .filter((item) => item)
 | 
			
		||||
    .reduce((acc, cur) => {
 | 
			
		||||
      if (cur) {
 | 
			
		||||
        acc[cur.key] = cur.value;
 | 
			
		||||
      }
 | 
			
		||||
      return acc;
 | 
			
		||||
    }, {} as { [key: string]: string });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
onMounted(async () => {
 | 
			
		||||
  annotations.value = cloneDeep(props.value) || {};
 | 
			
		||||
  await handleFetchAnnotationSettings();
 | 
			
		||||
  handleProcessCustomAnnotations();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => props.value,
 | 
			
		||||
  (value) => {
 | 
			
		||||
    reset("specForm");
 | 
			
		||||
    reset("customForm");
 | 
			
		||||
    annotations.value = cloneDeep(props.value) || {};
 | 
			
		||||
    if (value) {
 | 
			
		||||
      handleProcessCustomAnnotations();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
// submit
 | 
			
		||||
 | 
			
		||||
const specFormInvalid = ref(true);
 | 
			
		||||
const customFormInvalid = ref(true);
 | 
			
		||||
 | 
			
		||||
const handleSubmit = async () => {
 | 
			
		||||
  submitForm("specForm");
 | 
			
		||||
  submitForm("customForm");
 | 
			
		||||
  await nextTick();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onSpecFormSubmitCheck = async (node?: FormKitNode) => {
 | 
			
		||||
  if (!node) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  const validations = getValidationMessages(node);
 | 
			
		||||
  specFormInvalid.value = validations.size > 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onCustomFormSubmitCheck = async (node?: FormKitNode) => {
 | 
			
		||||
  if (!node) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  const validations = getValidationMessages(node);
 | 
			
		||||
  customFormInvalid.value = validations.size > 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
defineExpose({
 | 
			
		||||
  handleSubmit,
 | 
			
		||||
  specFormInvalid,
 | 
			
		||||
  customFormInvalid,
 | 
			
		||||
  annotations,
 | 
			
		||||
  customAnnotations,
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="flex flex-col gap-3 divide-y divide-gray-100">
 | 
			
		||||
    <FormKit
 | 
			
		||||
      v-if="annotations && avaliableAnnotationSettings.length > 0"
 | 
			
		||||
      id="specForm"
 | 
			
		||||
      v-model="annotations"
 | 
			
		||||
      type="form"
 | 
			
		||||
      :preserve="true"
 | 
			
		||||
      @submit-invalid="onSpecFormSubmitCheck"
 | 
			
		||||
      @submit="specFormInvalid = false"
 | 
			
		||||
    >
 | 
			
		||||
      <template
 | 
			
		||||
        v-for="(annotationSetting, index) in avaliableAnnotationSettings"
 | 
			
		||||
      >
 | 
			
		||||
        <FormKitSchema
 | 
			
		||||
          v-if="annotationSetting.spec?.formSchema"
 | 
			
		||||
          :key="index"
 | 
			
		||||
          :schema="annotationSetting.spec?.formSchema as (FormKitSchemaCondition| FormKitSchemaNode[])"
 | 
			
		||||
        />
 | 
			
		||||
      </template>
 | 
			
		||||
    </FormKit>
 | 
			
		||||
    <FormKit
 | 
			
		||||
      v-if="annotations"
 | 
			
		||||
      id="customForm"
 | 
			
		||||
      type="form"
 | 
			
		||||
      :preserve="true"
 | 
			
		||||
      :form-class="`${avaliableAnnotationSettings.length ? 'py-4' : ''}`"
 | 
			
		||||
      @submit-invalid="onCustomFormSubmitCheck"
 | 
			
		||||
      @submit="customFormInvalid = false"
 | 
			
		||||
    >
 | 
			
		||||
      <FormKit v-model="customAnnotationsState" type="repeater" label="自定义">
 | 
			
		||||
        <FormKit
 | 
			
		||||
          type="text"
 | 
			
		||||
          label="Key"
 | 
			
		||||
          name="key"
 | 
			
		||||
          validation="required|keyValidationRule"
 | 
			
		||||
          :validation-rules="{ keyValidationRule }"
 | 
			
		||||
          :validation-messages="{
 | 
			
		||||
            keyValidationRule: '当前 Key 已被占用',
 | 
			
		||||
          }"
 | 
			
		||||
        ></FormKit>
 | 
			
		||||
        <FormKit
 | 
			
		||||
          type="text"
 | 
			
		||||
          label="Value"
 | 
			
		||||
          name="value"
 | 
			
		||||
          validation="required"
 | 
			
		||||
        ></FormKit>
 | 
			
		||||
      </FormKit>
 | 
			
		||||
    </FormKit>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import { useThemeCustomTemplates } from "@/modules/interface/themes/composables/
 | 
			
		|||
import { postLabels } from "@/constants/labels";
 | 
			
		||||
import { randomUUID } from "@/utils/id";
 | 
			
		||||
import { toDatetimeLocal, toISOString } from "@/utils/date";
 | 
			
		||||
import AnnotationsForm from "@/components/form/AnnotationsForm.vue";
 | 
			
		||||
import { submitForm } from "@formkit/core";
 | 
			
		||||
 | 
			
		||||
const initialFormState: Post = {
 | 
			
		||||
| 
						 | 
				
			
			@ -107,6 +108,21 @@ const handlePublishClick = () => {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
const handleSave = async () => {
 | 
			
		||||
  annotationsFormRef.value?.handleSubmit();
 | 
			
		||||
  await nextTick();
 | 
			
		||||
 | 
			
		||||
  const { customAnnotations, annotations, customFormInvalid, specFormInvalid } =
 | 
			
		||||
    annotationsFormRef.value || {};
 | 
			
		||||
 | 
			
		||||
  if (customFormInvalid || specFormInvalid) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  formState.value.metadata.annotations = {
 | 
			
		||||
    ...annotations,
 | 
			
		||||
    ...customAnnotations,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if (props.onlyEmit) {
 | 
			
		||||
    emit("saved", formState.value);
 | 
			
		||||
    return;
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +220,8 @@ const publishTime = computed(() => {
 | 
			
		|||
const onPublishTimeChange = (value: string) => {
 | 
			
		||||
  formState.value.spec.publishTime = value ? toISOString(value) : undefined;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const annotationsFormRef = ref<InstanceType<typeof AnnotationsForm>>();
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <VModal
 | 
			
		||||
| 
						 | 
				
			
			@ -350,6 +368,27 @@ const onPublishTimeChange = (value: string) => {
 | 
			
		|||
      </div>
 | 
			
		||||
    </FormKit>
 | 
			
		||||
 | 
			
		||||
    <div class="py-5">
 | 
			
		||||
      <div class="border-t border-gray-200"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="md:grid md:grid-cols-4 md:gap-6">
 | 
			
		||||
      <div class="md:col-span-1">
 | 
			
		||||
        <div class="sticky top-0">
 | 
			
		||||
          <span class="text-base font-medium text-gray-900"> 元数据 </span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="mt-5 divide-y divide-gray-100 md:col-span-3 md:mt-0">
 | 
			
		||||
        <AnnotationsForm
 | 
			
		||||
          :key="formState.metadata.name"
 | 
			
		||||
          ref="annotationsFormRef"
 | 
			
		||||
          :value="formState.metadata.annotations"
 | 
			
		||||
          kind="Post"
 | 
			
		||||
          group="content.halo.run"
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <template #footer>
 | 
			
		||||
      <VSpace>
 | 
			
		||||
        <template v-if="publishSupport">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ import {
 | 
			
		|||
  V1alpha1RoleBindingApi,
 | 
			
		||||
  V1alpha1SettingApi,
 | 
			
		||||
  V1alpha1UserApi,
 | 
			
		||||
  V1alpha1AnnotationSettingApi,
 | 
			
		||||
} from "@halo-dev/api-client";
 | 
			
		||||
import type { AxiosError, AxiosInstance } from "axios";
 | 
			
		||||
import axios from "axios";
 | 
			
		||||
| 
						 | 
				
			
			@ -157,6 +158,11 @@ function setupApiClient(axios: AxiosInstance) {
 | 
			
		|||
          axios
 | 
			
		||||
        ),
 | 
			
		||||
      },
 | 
			
		||||
      annotationSetting: new V1alpha1AnnotationSettingApi(
 | 
			
		||||
        undefined,
 | 
			
		||||
        baseURL,
 | 
			
		||||
        axios
 | 
			
		||||
      ),
 | 
			
		||||
    },
 | 
			
		||||
    // custom endpoints
 | 
			
		||||
    user: new ApiConsoleHaloRunV1alpha1UserApi(undefined, baseURL, axios),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue