refactor: structure of the setting extension (#616)

#### What type of PR is this?

/kind improvement
/milestone 2.0
/kind api-change

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

重构 Setting 模型的结构,适配 https://github.com/halo-dev/halo/pull/2440

todo list:

- [x] 更新 `@halo-dev/api-client`

#### Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/2414

#### Special notes for your reviewer:

测试方式:

1. 本地 admin 仓库切换到当前 PR 的分支,halo 仓库切换到 https://github.com/halo-dev/halo/pull/2440 PR 的分支。
2. 测试后台各个表单功能是否正常。
3. 主题设置表单可使用 https://github.com/halo-sigs/theme-anatole/pull/2 PR 的分支进行测试。

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

```release-note
None
```
pull/617/head
Ryan Wang 2022-09-22 16:26:13 +08:00 committed by GitHub
parent 36bb28cd0e
commit f2f657b55c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 81 additions and 72 deletions

View File

@ -34,7 +34,7 @@
"@formkit/themes": "1.0.0-beta.10",
"@formkit/vue": "1.0.0-beta.10",
"@halo-dev/admin-shared": "workspace:*",
"@halo-dev/api-client": "^0.0.23",
"@halo-dev/api-client": "^0.0.25",
"@halo-dev/components": "workspace:*",
"@halo-dev/richtext-editor": "^0.0.0-alpha.7",
"@tiptap/extension-character-count": "2.0.0-beta.31",

View File

@ -7,9 +7,8 @@ import { apiClient } from "../utils/api-client";
// libs
import cloneDeep from "lodash.clonedeep";
import merge from "lodash.merge";
import type { FormKitSetting, FormKitSettingSpec } from "../types/formkit";
import type { ConfigMap } from "@halo-dev/api-client";
import type { FormKitSchemaNode } from "@formkit/core";
import type { ConfigMap, Setting, SettingForm } from "@halo-dev/api-client";
import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
const initialConfigMap: ConfigMap = {
apiVersion: "v1alpha1",
@ -21,7 +20,7 @@ const initialConfigMap: ConfigMap = {
};
interface useSettingFormReturn {
settings: Ref<FormKitSetting | undefined>;
setting: Ref<Setting | undefined>;
configMap: Ref<ConfigMap>;
configMapFormData: Ref<Record<string, Record<string, string>> | undefined>;
saving: Ref<boolean>;
@ -35,7 +34,7 @@ export function useSettingForm(
settingName: Ref<string | undefined>,
configMapName: Ref<string | undefined>
): useSettingFormReturn {
const settings = ref<FormKitSetting | undefined>();
const setting = ref<Setting>();
const configMap = ref<ConfigMap>(cloneDeep(initialConfigMap));
const configMapFormData = ref<
Record<string, Record<string, string>> | undefined
@ -45,29 +44,32 @@ export function useSettingForm(
const handleFetchSettings = async () => {
if (!settingName.value) {
settings.value = undefined;
setting.value = undefined;
return;
}
try {
const response = await apiClient.extension.setting.getv1alpha1Setting({
const { data } = await apiClient.extension.setting.getv1alpha1Setting({
name: settingName.value,
});
settings.value = response.data as FormKitSetting;
setting.value = data;
// init configMapFormData
if (!configMapFormData.value) {
const { spec: schemaGroups } = settings.value;
const { forms } = setting.value.spec;
const initialConfigMapFormData: Record<
string,
Record<string, string>
> = {};
schemaGroups.forEach((schemaGroup) => {
initialConfigMapFormData[schemaGroup.group] = {};
const formSchema = schemaGroup.formSchema as FormKitSchemaNode[];
forms.forEach((form) => {
initialConfigMapFormData[form.group] = {};
const formSchema = form.formSchema as (
| FormKitSchemaCondition
| FormKitSchemaNode
)[];
formSchema.forEach((schema) => {
// @ts-ignore
if ("name" in schema && "$formkit" in schema) {
initialConfigMapFormData[schemaGroup.group][schema.name] =
initialConfigMapFormData[form.group][schema.name] =
schema.value || undefined;
}
});
@ -75,7 +77,7 @@ export function useSettingForm(
configMapFormData.value = cloneDeep(initialConfigMapFormData);
}
} catch (e) {
console.error(e);
console.error("Failed to fetch setting", e);
}
};
@ -98,20 +100,20 @@ export function useSettingForm(
if (data) {
// merge objects value
const { spec: schemaGroups } = settings.value || {};
const { forms } = setting.value?.spec || {};
schemaGroups?.forEach((schemaGroup) => {
forms?.forEach((form) => {
if (!configMapFormData.value) {
return;
}
configMapFormData.value[schemaGroup.group] = merge(
configMapFormData.value[schemaGroup.group] || {},
JSON.parse(data[schemaGroup.group] || "{}")
configMapFormData.value[form.group] = merge(
configMapFormData.value[form.group] || {},
JSON.parse(data[form.group] || "{}")
);
});
}
} catch (e) {
console.error(e);
console.error("Failed to fetch configMap", e);
}
};
@ -123,7 +125,7 @@ export function useSettingForm(
configMap.value.metadata.name = configMapName.value;
}
settings?.value?.spec.forEach((item: FormKitSettingSpec) => {
setting.value?.spec.forms.forEach((item: SettingForm) => {
// @ts-ignore
configMap.value.data[item.group] = JSON.stringify(
configMapFormData?.value?.[item.group]
@ -141,7 +143,7 @@ export function useSettingForm(
});
}
} catch (e) {
console.error(e);
console.error("Failed to save configMap", e);
} finally {
await handleFetchSettings();
await handleFetchConfigMap();
@ -150,13 +152,13 @@ export function useSettingForm(
};
const handleReset = () => {
settings.value = undefined;
setting.value = undefined;
configMap.value = cloneDeep(initialConfigMap);
configMapFormData.value = undefined;
};
return {
settings,
setting,
configMap,
configMapFormData,
saving,

View File

@ -1,6 +1,5 @@
export * from "./types/plugin";
export * from "./types/menus";
export * from "./types/formkit";
export * from "./core/plugins";
export * from "./states/pages";
export * from "./states/attachment-selector";

View File

@ -1,10 +0,0 @@
import type { Setting, SettingSpec } from "@halo-dev/api-client";
import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
export interface FormKitSettingSpec extends Omit<SettingSpec, "formSchema"> {
formSchema: FormKitSchemaCondition | FormKitSchemaNode[];
}
export interface FormKitSetting extends Omit<Setting, "spec"> {
spec: Array<FormKitSettingSpec>;
}

View File

@ -14,7 +14,7 @@ importers:
'@formkit/themes': 1.0.0-beta.10
'@formkit/vue': 1.0.0-beta.10
'@halo-dev/admin-shared': workspace:*
'@halo-dev/api-client': ^0.0.23
'@halo-dev/api-client': ^0.0.25
'@halo-dev/components': workspace:*
'@halo-dev/richtext-editor': ^0.0.0-alpha.7
'@iconify-json/mdi': ^1.1.33
@ -96,7 +96,7 @@ importers:
'@formkit/themes': 1.0.0-beta.10_tailwindcss@3.1.8
'@formkit/vue': 1.0.0-beta.10_jhzixbi2r7n2xnmwczrcaimaey
'@halo-dev/admin-shared': link:packages/shared
'@halo-dev/api-client': 0.0.23
'@halo-dev/api-client': 0.0.25
'@halo-dev/components': link:packages/components
'@halo-dev/richtext-editor': 0.0.0-alpha.7_vue@3.2.39
'@tiptap/extension-character-count': 2.0.0-beta.31
@ -1890,8 +1890,8 @@ packages:
- windicss
dev: false
/@halo-dev/api-client/0.0.23:
resolution: {integrity: sha512-YI+uGnHvGgKvt6HRtwf/AI73gQCDT1/vS4c3vsaTzDm9h66joL4ST0t1xSLuc1IXVmtf9ktggInqEktUgVko0Q==}
/@halo-dev/api-client/0.0.25:
resolution: {integrity: sha512-USCCsKam7wH6vExP3SrTBz+vvOndRWPek2CZSfv0FeE8T+TNDR/X/wNRy3BPl//O0wf7TkJUgFyhgbRf+z02YA==}
dev: false
/@halo-dev/richtext-editor/0.0.0-alpha.7_vue@3.2.39:

View File

@ -5,7 +5,12 @@ import cloneDeep from "lodash.clonedeep";
import { computed, ref, watch, watchEffect } from "vue";
import { apiClient, useSettingForm } from "@halo-dev/admin-shared";
import { v4 as uuid } from "uuid";
import { reset, submitForm } from "@formkit/core";
import {
reset,
submitForm,
type FormKitSchemaCondition,
type FormKitSchemaNode,
} from "@formkit/core";
import { useMagicKeys } from "@vueuse/core";
import { setFocus } from "@/formkit/utils/focus";
@ -51,7 +56,7 @@ const settingName = computed(
const configMapName = computed(() => formState.value.spec.configMapRef?.name);
const {
settings,
setting,
configMapFormData,
saving,
handleFetchConfigMap,
@ -61,11 +66,14 @@ const {
} = useSettingForm(settingName, configMapName);
const formSchema = computed(() => {
if (!settings?.value?.spec) {
if (!setting.value) {
return undefined;
}
return settings.value.spec.find((item) => item.group === "default")
?.formSchema;
const { forms } = setting.value.spec;
return forms.find((item) => item.group === "default")?.formSchema as (
| FormKitSchemaCondition
| FormKitSchemaNode
)[];
});
watchEffect(() => {
@ -75,7 +83,7 @@ watchEffect(() => {
});
watchEffect(() => {
if (configMapName.value && settings.value) {
if (configMapName.value && setting.value) {
handleFetchConfigMap();
}
});

View File

@ -12,6 +12,7 @@ import type { Theme } from "@halo-dev/api-client";
// hooks
import { useSettingForm } from "@halo-dev/admin-shared";
import { useRouteParams } from "@vueuse/router";
import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
const group = useRouteParams<string>("group");
@ -21,7 +22,7 @@ const settingName = computed(() => selectedTheme?.value?.spec.settingName);
const configMapName = computed(() => selectedTheme?.value?.spec.configMapName);
const {
settings,
setting,
configMapFormData,
saving,
handleFetchConfigMap,
@ -30,11 +31,14 @@ const {
} = useSettingForm(settingName, configMapName);
const formSchema = computed(() => {
if (!settings?.value?.spec) {
if (!setting.value) {
return;
}
return settings.value.spec.find((item) => item.group === group?.value)
?.formSchema;
const { forms } = setting.value.spec;
return forms.find((item) => item.group === group?.value)?.formSchema as (
| FormKitSchemaCondition
| FormKitSchemaNode
)[];
});
await handleFetchSettings();

View File

@ -10,7 +10,6 @@ import cloneDeep from "lodash.clonedeep";
// hooks
import { useThemeLifeCycle } from "../composables/use-theme";
// types
import type { FormKitSettingSpec } from "@halo-dev/admin-shared";
import { BasicLayout, useSettingForm } from "@halo-dev/admin-shared";
// components
@ -26,7 +25,7 @@ import {
VTabbar,
} from "@halo-dev/components";
import ThemeListModal from "../components/ThemeListModal.vue";
import type { Theme } from "@halo-dev/api-client";
import type { SettingForm, Theme } from "@halo-dev/api-client";
interface ThemeTab {
id: string;
@ -58,7 +57,7 @@ const { loading, isActivated, activatedTheme, handleActiveTheme } =
const settingName = computed(() => selectedTheme.value?.spec.settingName);
const configMapName = computed(() => selectedTheme.value?.spec.configMapName);
const { settings, handleFetchSettings } = useSettingForm(
const { setting, handleFetchSettings } = useSettingForm(
settingName,
configMapName
);
@ -85,10 +84,11 @@ watch(
tabs.value = cloneDeep(initialTabs);
await handleFetchSettings();
if (settings.value && settings.value.spec) {
if (setting.value) {
const { forms } = setting.value.spec;
tabs.value = [
...tabs.value,
...settings.value.spec.map((item: FormKitSettingSpec) => {
...forms.map((item: SettingForm) => {
return {
id: item.group,
label: item.label || "",

View File

@ -11,6 +11,7 @@ import { VButton } from "@halo-dev/components";
// types
import type { Plugin } from "@halo-dev/api-client";
import { useRouteParams } from "@vueuse/router";
import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
const name = useRouteParams<string>("name");
const group = useRouteParams<string>("group");
@ -21,7 +22,7 @@ const settingName = computed(() => plugin?.value?.spec.settingName);
const configMapName = computed(() => plugin?.value?.spec.configMapName);
const {
settings,
setting,
configMapFormData,
saving,
handleFetchSettings,
@ -30,11 +31,14 @@ const {
} = useSettingForm(settingName, configMapName);
const formSchema = computed(() => {
if (!settings?.value?.spec) {
if (!setting.value) {
return;
}
return settings.value.spec.find((item) => item.group === group.value)
?.formSchema;
const { forms } = setting.value.spec;
return forms.find((item) => item.group === group.value)?.formSchema as (
| FormKitSchemaCondition
| FormKitSchemaNode
)[];
});
const handleFetchPlugin = async () => {

View File

@ -16,8 +16,7 @@ import { BasicLayout } from "@halo-dev/admin-shared";
// types
import type { Ref } from "vue";
import type { Plugin } from "@halo-dev/api-client";
import type { FormKitSettingSpec } from "@halo-dev/admin-shared";
import type { Plugin, SettingForm } from "@halo-dev/api-client";
interface PluginTab {
id: string;
@ -51,7 +50,7 @@ provide<Ref<string | undefined>>("activeTab", activeTab);
const settingName = computed(() => plugin.value?.spec.settingName);
const configMapName = computed(() => plugin.value?.spec.configMapName);
const { settings, handleFetchSettings } = useSettingForm(
const { setting, handleFetchSettings } = useSettingForm(
settingName,
configMapName
);
@ -101,10 +100,11 @@ onMounted(async () => {
tabs.value = cloneDeep(initialTabs);
if (settings.value && settings.value.spec) {
if (setting.value) {
const { forms } = setting.value.spec;
tabs.value = [
...tabs.value,
...settings.value.spec.map((item: FormKitSettingSpec) => {
...forms.map((item: SettingForm) => {
return {
id: item.group,
label: item.label || "",

View File

@ -8,11 +8,12 @@ import { VButton } from "@halo-dev/components";
// hooks
import { useSettingForm } from "@halo-dev/admin-shared";
import { useRouteParams } from "@vueuse/router";
import type { FormKitSchemaCondition, FormKitSchemaNode } from "@formkit/core";
const group = useRouteParams<string>("group");
const {
settings,
setting,
configMapFormData,
saving,
handleFetchConfigMap,
@ -21,11 +22,11 @@ const {
} = useSettingForm(ref("system"), ref("system"));
const formSchema = computed(() => {
if (!settings?.value?.spec) {
if (!setting.value) {
return;
}
return settings.value.spec.find((item) => item.group === group?.value)
?.formSchema;
return setting.value.spec.forms.find((item) => item.group === group?.value)
?.formSchema as (FormKitSchemaCondition | FormKitSchemaNode)[];
});
await handleFetchSettings();

View File

@ -5,7 +5,6 @@ import { ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
// types
import type { FormKitSettingSpec } from "@halo-dev/admin-shared";
import { BasicLayout, useSettingForm } from "@halo-dev/admin-shared";
// components
@ -15,6 +14,7 @@ import {
VTabbar,
IconSettings,
} from "@halo-dev/components";
import type { SettingForm } from "@halo-dev/api-client";
interface SettingTab {
id: string;
@ -28,7 +28,7 @@ interface SettingTab {
const tabs = ref<SettingTab[]>([] as SettingTab[]);
const activeTab = ref("");
const { settings, handleFetchSettings } = useSettingForm(
const { setting, handleFetchSettings } = useSettingForm(
ref("system"),
ref("system")
);
@ -47,8 +47,9 @@ const handleTabChange = (id: string) => {
onMounted(async () => {
await handleFetchSettings();
if (settings.value && settings.value.spec) {
tabs.value = settings.value.spec.map((item: FormKitSettingSpec) => {
if (setting.value) {
const { forms } = setting.value.spec;
tabs.value = forms.map((item: SettingForm) => {
return {
id: item.group,
label: item.label || "",