From 2ac0c525def85fea8c645bdcfa59ca81c01e7726 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Tue, 11 Oct 2022 15:33:51 +0800 Subject: [PATCH] feat: add support for selecting parent menu item when creating menu item Signed-off-by: Ryan Wang --- src/modules/interface/menus/Menus.vue | 20 ++++- .../menus/components/MenuItemEditingModal.vue | 78 ++++++++++++++++--- .../menus/components/MenuItemListItem.vue | 14 ++++ 3 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/modules/interface/menus/Menus.vue b/src/modules/interface/menus/Menus.vue index 2265a40cd..4ee101ac8 100644 --- a/src/modules/interface/menus/Menus.vue +++ b/src/modules/interface/menus/Menus.vue @@ -28,8 +28,9 @@ import { useDebounceFn } from "@vueuse/core"; const menuItems = ref([] as MenuItem[]); const menuTreeItems = ref([] as MenuTreeItem[]); -const selectedMenu = ref(); -const selectedMenuItem = ref(null); +const selectedMenu = ref(); +const selectedMenuItem = ref(); +const selectedParentMenuItem = ref(); const loading = ref(false); const menuListRef = ref(); const menuItemEditingModal = ref(); @@ -66,6 +67,16 @@ const handleOpenEditingModal = (menuItem: MenuTreeItem) => { menuItemEditingModal.value = true; }; +const handleOpenCreateByParentModal = (menuItem: MenuTreeItem) => { + selectedParentMenuItem.value = convertMenuTreeItemToMenuItem(menuItem); + menuItemEditingModal.value = true; +}; + +const onMenuItemEditingModalClose = () => { + selectedParentMenuItem.value = undefined; + selectedMenuItem.value = undefined; +}; + const onMenuItemSaved = async (menuItem: MenuItem) => { const menuToUpdate = cloneDeep(selectedMenu.value); @@ -143,7 +154,9 @@ const handleDelete = async (menuItem: MenuTreeItem) => { @@ -214,6 +227,7 @@ const handleDelete = async (menuItem: MenuTreeItem) => { @change="handleUpdateInBatch" @delete="handleDelete" @open-editing="handleOpenEditingModal" + @open-create-by-parent="handleOpenCreateByParentModal" /> diff --git a/src/modules/interface/menus/components/MenuItemEditingModal.vue b/src/modules/interface/menus/components/MenuItemEditingModal.vue index c2970b24a..259ea2cc8 100644 --- a/src/modules/interface/menus/components/MenuItemEditingModal.vue +++ b/src/modules/interface/menus/components/MenuItemEditingModal.vue @@ -2,7 +2,7 @@ import { VButton, VModal, VSpace } from "@halo-dev/components"; import SubmitButton from "@/components/button/SubmitButton.vue"; import { computed, ref, watch } from "vue"; -import type { MenuItem, Post, SinglePage } from "@halo-dev/api-client"; +import type { Menu, MenuItem, Post, SinglePage } from "@halo-dev/api-client"; import { v4 as uuid } from "uuid"; import { apiClient } from "@/utils/api-client"; import { reset } from "@formkit/core"; @@ -10,15 +10,20 @@ import cloneDeep from "lodash.clonedeep"; import { usePostCategory } from "@/modules/contents/posts/categories/composables/use-post-category"; import { usePostTag } from "@/modules/contents/posts/tags/composables/use-post-tag"; import { setFocus } from "@/formkit/utils/focus"; +import type { FormKitOptionsProp } from "@formkit/inputs"; const props = withDefaults( defineProps<{ visible: boolean; - menuItem: MenuItem | null; + menu?: Menu; + parentMenuItem: MenuItem; + menuItem?: MenuItem; }>(), { visible: false, - menuItem: null, + menu: undefined, + parentMenuItem: undefined, + menuItem: undefined, } ); @@ -42,6 +47,8 @@ const initialFormState: MenuItem = { }, }; +const menuItemMap = ref(); +const selectedParentMenuItem = ref(""); const formState = ref(cloneDeep(initialFormState)); const saving = ref(false); @@ -49,6 +56,25 @@ const isUpdateMode = computed(() => { return !!formState.value.metadata.creationTimestamp; }); +const handleFetchMenuItems = async () => { + try { + const { data } = await apiClient.extension.menuItem.listv1alpha1MenuItem({ + fieldSelector: [`name=(${props.menu?.spec.menuItems?.join(",")})`], + }); + menuItemMap.value = [ + { label: "无", value: undefined }, + ...data.items.map((menuItem) => { + return { + label: menuItem.status?.displayName as string, + value: menuItem.metadata.name, + }; + }), + ]; + } catch (error) { + console.log("Failed to fetch menu items", error); + } +}; + const handleSaveMenuItem = async () => { try { saving.value = true; @@ -81,6 +107,25 @@ const handleSaveMenuItem = async () => { await apiClient.extension.menuItem.createv1alpha1MenuItem({ menuItem: formState.value, }); + + // if parent menu item is selected, add the new menu item to the parent menu item + if (selectedParentMenuItem.value) { + const { data: menuItemToUpdate } = + await apiClient.extension.menuItem.getv1alpha1MenuItem({ + name: selectedParentMenuItem.value, + }); + + menuItemToUpdate.spec.children = [ + ...(menuItemToUpdate.spec.children || []), + data.metadata.name, + ]; + + await apiClient.extension.menuItem.updatev1alpha1MenuItem({ + name: menuItemToUpdate.metadata.name, + menuItem: menuItemToUpdate, + }); + } + onVisibleChange(false); emit("saved", data); } @@ -103,6 +148,7 @@ const handleResetForm = () => { formState.value.metadata.name = uuid(); selectedMenuItemSource.value = menuItemSources[0].value; selectedRef.value = ""; + selectedParentMenuItem.value = ""; reset("menuitem-form"); }; @@ -110,6 +156,7 @@ watch( () => props.visible, (visible) => { if (visible) { + selectedParentMenuItem.value = props.parentMenuItem?.metadata.name; setFocus("displayNameInput"); if (!props.menuItem) { @@ -287,6 +334,7 @@ watch( () => props.visible, (newValue) => { if (newValue) { + handleFetchMenuItems(); handleFetchCategories(); handleFetchTags(); handleFetchPosts(); @@ -310,6 +358,14 @@ watch( :config="{ validationVisibility: 'submit' }" @submit="handleSaveMenuItem" > + + - + /> + /> + + /> + /> + /> + /> + />