mirror of https://github.com/halo-dev/halo
feat: add dropdown component to refactor the action buttons (#3576)
#### What type of PR is this? /kind improvement /area console /milestone 2.4.x #### What this PR does / why we need it: 在 `@halo-dev/components` 添加 Dropdown 组件用于统一 Console 端所有下拉框的样式和表现,同时方便插件使用。 <img width="1408" alt="image" src="https://user-images.githubusercontent.com/21301288/227758168-ed6f40ef-8627-4d5a-8a4a-476badf5196d.png"> <img width="992" alt="image" src="https://user-images.githubusercontent.com/21301288/227758184-01bf61a0-f778-4ba8-aaea-f6b99715b577.png"> #### Which issue(s) this PR fixes: Fixes #2987 #### Does this PR introduce a user-facing change? ```release-note Console 端添加 Dropdown 组件以统一所有下拉框的样式和表现。 ```pull/3561/head
parent
fb2bc4252d
commit
9a00a74f06
|
@ -66,7 +66,6 @@
|
|||
"dayjs": "^1.11.6",
|
||||
"emoji-mart": "^5.3.3",
|
||||
"fastq": "^1.15.0",
|
||||
"floating-vue": "2.0.0-beta.20",
|
||||
"fuse.js": "^6.6.2",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"@codemirror/legacy-modes": "^6.3.0",
|
||||
"@codemirror/state": "^6.1.4",
|
||||
"@codemirror/view": "^6.5.1",
|
||||
"codemirror": "^6.0.1"
|
||||
"codemirror": "^6.0.1",
|
||||
"floating-vue": "2.0.0-beta.20"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,3 +17,5 @@ export * from "./components/status";
|
|||
export * from "./components/entity";
|
||||
export * from "./components/toast";
|
||||
export * from "./components/loading";
|
||||
export * from "./components/dropdown";
|
||||
export * from "./components/tooltip";
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts" setup>
|
||||
import { VButton } from "@/components/button";
|
||||
import { VDropdown, VDropdownItem, VDropdownDivider } from "./index";
|
||||
</script>
|
||||
<template>
|
||||
<Story title="Dropdown">
|
||||
<template #default>
|
||||
<VDropdown>
|
||||
<VButton>Hello</VButton>
|
||||
<template #popper>
|
||||
<VDropdownItem>删除</VDropdownItem>
|
||||
<VDropdownDivider></VDropdownDivider>
|
||||
<VDropdownItem>删除</VDropdownItem>
|
||||
<VDropdownItem>编辑</VDropdownItem>
|
||||
</template>
|
||||
</VDropdown>
|
||||
</template>
|
||||
</Story>
|
||||
</template>
|
|
@ -0,0 +1,43 @@
|
|||
<script lang="ts" setup>
|
||||
import { Dropdown as FloatingDropdown, type Placement } from "floating-vue";
|
||||
import "floating-vue/dist/style.css";
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
placement?: Placement;
|
||||
triggers?: string[];
|
||||
classes?: string[];
|
||||
}>(),
|
||||
{
|
||||
placement: "bottom",
|
||||
triggers: () => ["click"],
|
||||
classes: () => [],
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: "show"): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FloatingDropdown
|
||||
:placement="placement"
|
||||
:triggers="triggers"
|
||||
@show="emit('show')"
|
||||
>
|
||||
<slot />
|
||||
<template #popper>
|
||||
<div
|
||||
class="min-w-[13rem] p-1.5"
|
||||
:class="classes"
|
||||
role="menu"
|
||||
aria-orientation="vertical"
|
||||
aria-labelledby="menu-button"
|
||||
tabindex="-1"
|
||||
>
|
||||
<slot name="popper" />
|
||||
</div>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</template>
|
|
@ -0,0 +1,5 @@
|
|||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<div class="my-1 h-[1px] w-full bg-gray-100"></div>
|
||||
</template>
|
|
@ -0,0 +1,54 @@
|
|||
<script lang="ts" setup>
|
||||
import { VClosePopper } from "floating-vue";
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
selected?: boolean;
|
||||
type: "default" | "danger";
|
||||
}>(),
|
||||
{
|
||||
selected: false,
|
||||
type: "default",
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-close-popper
|
||||
class="dropdown-item-wrapper"
|
||||
:class="[`dropdown-item-wrapper--${type}${selected ? '--selected' : ''}`]"
|
||||
role="menuitem"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div class="flex items-center gap-3">
|
||||
<slot name="prefix-icon" />
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<slot name="suffix-icon"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.dropdown-item-wrapper {
|
||||
@apply flex w-full cursor-pointer justify-between items-center gap-1 rounded px-4 py-2 text-sm;
|
||||
|
||||
&--default {
|
||||
@apply text-gray-700 hover:bg-gray-100 hover:text-gray-900;
|
||||
|
||||
&--selected {
|
||||
@apply bg-gray-100 text-gray-900;
|
||||
}
|
||||
}
|
||||
|
||||
&--danger {
|
||||
@apply text-red-500 hover:bg-red-50 hover:text-red-700;
|
||||
|
||||
&--selected {
|
||||
@apply bg-red-50 text-red-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,4 @@
|
|||
export { default as VDropdown } from "./Dropdown.vue";
|
||||
export { default as VDropdownItem } from "./DropdownItem.vue";
|
||||
export { default as VDropdownDivider } from "./DropdownDivider.vue";
|
||||
export { VClosePopper } from "floating-vue";
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts" setup>
|
||||
import { VSpace } from "../space";
|
||||
import { IconMore } from "../../icons/icons";
|
||||
import { computed } from "vue";
|
||||
import { VDropdown } from "../dropdown";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
isSelected?: boolean;
|
||||
|
@ -35,7 +36,7 @@ const classes = computed(() => {
|
|||
<slot name="end" />
|
||||
</div>
|
||||
<div v-if="$slots.dropdownItems" class="entity-dropdown">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="entity-dropdown-trigger group-hover:bg-gray-200/60"
|
||||
:class="{ '!bg-gray-300/60': isSelected }"
|
||||
|
@ -44,13 +45,9 @@ const classes = computed(() => {
|
|||
<IconMore />
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-48 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<slot name="dropdownItems"></slot>
|
||||
</VSpace>
|
||||
</div>
|
||||
<slot name="dropdownItems"></slot>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="$slots.footer">
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export { VTooltip } from "floating-vue";
|
||||
import "./style.css";
|
|
@ -0,0 +1,3 @@
|
|||
.v-popper--theme-tooltip {
|
||||
pointer-events: none;
|
||||
}
|
|
@ -18,6 +18,9 @@ export default defineConfig({
|
|||
insertTypesEntry: true,
|
||||
}),
|
||||
],
|
||||
define: {
|
||||
"process.env": process.env,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||
|
|
|
@ -65,7 +65,6 @@ importers:
|
|||
eslint-plugin-cypress: ^2.12.1
|
||||
eslint-plugin-vue: ^9.8.0
|
||||
fastq: ^1.15.0
|
||||
floating-vue: 2.0.0-beta.20
|
||||
fuse.js: ^6.6.2
|
||||
husky: ^8.0.2
|
||||
jsdom: ^20.0.3
|
||||
|
@ -139,7 +138,6 @@ importers:
|
|||
dayjs: 1.11.6
|
||||
emoji-mart: 5.3.3
|
||||
fastq: 1.15.0
|
||||
floating-vue: 2.0.0-beta.20_vue@3.2.45
|
||||
fuse.js: 6.6.2
|
||||
jsencrypt: 3.3.2
|
||||
lodash.clonedeep: 4.5.0
|
||||
|
@ -243,6 +241,7 @@ importers:
|
|||
'@histoire/plugin-vue': ^0.11.7
|
||||
'@iconify-json/ri': ^1.1.4
|
||||
codemirror: ^6.0.1
|
||||
floating-vue: 2.0.0-beta.20
|
||||
histoire: ^0.11.7
|
||||
unplugin-icons: ^0.14.14
|
||||
vite-plugin-dts: ^1.7.1
|
||||
|
@ -259,6 +258,7 @@ importers:
|
|||
'@codemirror/state': 6.1.4
|
||||
'@codemirror/view': 6.5.1
|
||||
codemirror: 6.0.1_@lezer+common@1.0.1
|
||||
floating-vue: 2.0.0-beta.20_vue@3.2.45
|
||||
vue: 3.2.45
|
||||
vue-router: 4.1.6_vue@3.2.45
|
||||
devDependencies:
|
||||
|
@ -2645,8 +2645,8 @@ packages:
|
|||
dependencies:
|
||||
'@babel/parser': 7.21.2
|
||||
'@babel/traverse': 7.21.2
|
||||
'@intlify/message-compiler': 9.3.0-beta.16
|
||||
'@intlify/shared': 9.3.0-beta.16
|
||||
'@intlify/message-compiler': 9.3.0-beta.17
|
||||
'@intlify/shared': 9.3.0-beta.17
|
||||
jsonc-eslint-parser: 1.4.1
|
||||
source-map: 0.6.1
|
||||
vue-i18n: 9.2.2_vue@3.2.45
|
||||
|
@ -2677,11 +2677,11 @@ packages:
|
|||
'@intlify/shared': 9.2.2
|
||||
source-map: 0.6.1
|
||||
|
||||
/@intlify/message-compiler/9.3.0-beta.16:
|
||||
resolution: {integrity: sha512-CGQI3xRcs1ET75eDQ0DUy3MRYOqTauRIIgaMoISKiF83gqRWg93FqN8lGMKcpBqaF4tI0JhsfosCaGiBL9+dnw==}
|
||||
/@intlify/message-compiler/9.3.0-beta.17:
|
||||
resolution: {integrity: sha512-i7hvVIRk1Ax2uKa9xLRJCT57to08OhFMhFXXjWN07rmx5pWQYQ23MfX1xgggv9drnWTNhqEiD+u4EJeHoS5+Ww==}
|
||||
engines: {node: '>= 14'}
|
||||
dependencies:
|
||||
'@intlify/shared': 9.3.0-beta.16
|
||||
'@intlify/shared': 9.3.0-beta.17
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
|
@ -2689,8 +2689,8 @@ packages:
|
|||
resolution: {integrity: sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==}
|
||||
engines: {node: '>= 14'}
|
||||
|
||||
/@intlify/shared/9.3.0-beta.16:
|
||||
resolution: {integrity: sha512-kXbm4svALe3lX+EjdJxfnabOphqS4yQ1Ge/iIlR8tvUiYRCoNz3hig1M4336iY++Dfx5ytEQJPNjIcknNIuvig==}
|
||||
/@intlify/shared/9.3.0-beta.17:
|
||||
resolution: {integrity: sha512-mscf7RQsUTOil35jTij4KGW1RC9SWQjYScwLxP53Ns6g24iEd5HN7ksbt9O6FvTmlQuX77u+MXpBdfJsGqizLQ==}
|
||||
engines: {node: '>= 14'}
|
||||
dev: true
|
||||
|
||||
|
@ -2710,7 +2710,7 @@ packages:
|
|||
optional: true
|
||||
dependencies:
|
||||
'@intlify/bundle-utils': 5.0.1_vue-i18n@9.2.2
|
||||
'@intlify/shared': 9.3.0-beta.16
|
||||
'@intlify/shared': 9.3.0-beta.17
|
||||
'@rollup/pluginutils': 5.0.2_rollup@2.79.1
|
||||
'@vue/compiler-sfc': 3.2.47
|
||||
debug: 4.3.4
|
||||
|
@ -2770,7 +2770,7 @@ packages:
|
|||
resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==}
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.2
|
||||
'@jridgewell/trace-mapping': 0.3.15
|
||||
'@jridgewell/trace-mapping': 0.3.17
|
||||
dev: true
|
||||
|
||||
/@jridgewell/sourcemap-codec/1.4.14:
|
||||
|
@ -10097,7 +10097,7 @@ packages:
|
|||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.2
|
||||
acorn: 8.8.1
|
||||
acorn: 8.8.2
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
dev: true
|
||||
|
|
|
@ -102,12 +102,4 @@ body {
|
|||
*::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.v-popper__popper {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.v-popper--theme-tooltip {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Category } from "@halo-dev/api-client";
|
||||
import { VEntity, VEntityField } from "@halo-dev/components";
|
||||
import { VEntity, VEntityField, VDropdown } from "@halo-dev/components";
|
||||
import { setFocus } from "@/formkit/utils/focus";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import Fuse from "fuse.js";
|
||||
|
@ -71,7 +71,7 @@ const searchResults = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FloatingDropdown @show="onDropdownShow">
|
||||
<VDropdown :classes="['!p-0']" @show="onDropdownShow">
|
||||
<slot />
|
||||
<template #popper>
|
||||
<div class="h-96 w-80">
|
||||
|
@ -120,5 +120,5 @@ const searchResults = computed(() => {
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</template>
|
||||
|
|
|
@ -3,7 +3,12 @@ import {
|
|||
useEditorExtensionPoints,
|
||||
type EditorProvider,
|
||||
} from "@/composables/use-editor-extension-points";
|
||||
import { VAvatar, VSpace, IconExchange } from "@halo-dev/components";
|
||||
import {
|
||||
VAvatar,
|
||||
IconExchange,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
|
@ -22,7 +27,7 @@ const { editorProviders } = useEditorExtensionPoints();
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="group flex w-full cursor-pointer items-center gap-2 rounded p-1 hover:bg-gray-100"
|
||||
>
|
||||
|
@ -33,30 +38,17 @@ const { editorProviders } = useEditorExtensionPoints();
|
|||
<IconExchange class="h-4 w-4 text-gray-600 group-hover:text-gray-900" />
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-48 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<div
|
||||
v-for="(editorProvider, index) in editorProviders"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="group flex w-full cursor-pointer items-center gap-2 rounded p-1 hover:bg-gray-100"
|
||||
:class="{
|
||||
'bg-gray-100': editorProvider.name === provider?.name,
|
||||
}"
|
||||
@click="emit('select', editorProvider)"
|
||||
>
|
||||
<VAvatar :src="editorProvider.logo" size="xs"></VAvatar>
|
||||
<div
|
||||
class="text-sm text-gray-600 group-hover:text-gray-900"
|
||||
:class="{
|
||||
'text-gray-900': editorProvider.name === provider?.name,
|
||||
}"
|
||||
>
|
||||
{{ editorProvider.displayName }}
|
||||
</div>
|
||||
</div>
|
||||
</VSpace>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(editorProvider, index) in editorProviders"
|
||||
:key="index"
|
||||
:selected="provider?.name === editorProvider.name"
|
||||
@click="emit('select', editorProvider)"
|
||||
>
|
||||
<template #prefix-icon>
|
||||
<VAvatar :src="editorProvider.logo" size="xs"></VAvatar>
|
||||
</template>
|
||||
{{ editorProvider.displayName }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Tag } from "@halo-dev/api-client";
|
||||
import { VEntity, VEntityField } from "@halo-dev/components";
|
||||
import { VEntity, VEntityField, VDropdown } from "@halo-dev/components";
|
||||
import { setFocus } from "@/formkit/utils/focus";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import Fuse from "fuse.js";
|
||||
|
@ -69,7 +69,7 @@ const searchResults = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FloatingDropdown @show="onDropdownShow">
|
||||
<VDropdown :classes="['!p-0']" @show="onDropdownShow">
|
||||
<slot />
|
||||
<template #popper>
|
||||
<div class="h-96 w-80">
|
||||
|
@ -117,5 +117,5 @@ const searchResults = computed(() => {
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</template>
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<script lang="ts" setup>
|
||||
import type { User } from "@halo-dev/api-client";
|
||||
import { useUserFetch } from "@/modules/system/users/composables/use-user";
|
||||
import { VAvatar, VEntity, VEntityField } from "@halo-dev/components";
|
||||
import {
|
||||
VAvatar,
|
||||
VDropdown,
|
||||
VEntity,
|
||||
VEntityField,
|
||||
} from "@halo-dev/components";
|
||||
import { setFocus } from "@/formkit/utils/focus";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import Fuse from "fuse.js";
|
||||
|
@ -66,7 +71,7 @@ const searchResults = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<FloatingDropdown @show="onDropdownShow">
|
||||
<VDropdown :classes="['!p-0']" @show="onDropdownShow">
|
||||
<slot />
|
||||
<template #popper>
|
||||
<div class="h-96 w-80">
|
||||
|
@ -114,5 +119,5 @@ const searchResults = computed(() => {
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</template>
|
||||
|
|
|
@ -5,9 +5,9 @@ import {
|
|||
IconUserSettings,
|
||||
VTag,
|
||||
VAvatar,
|
||||
VSpace,
|
||||
VButton,
|
||||
Dialog,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import { RoutesMenu } from "@/components/menu/RoutesMenu";
|
||||
import type { MenuGroupType, MenuItemType } from "@halo-dev/console-shared";
|
||||
|
@ -273,36 +273,26 @@ onMounted(() => {
|
|||
</VTag>
|
||||
</div>
|
||||
</div>
|
||||
<FloatingDropdown
|
||||
<VDropdown
|
||||
class="profile-control cursor-pointer rounded p-1 transition-all hover:bg-gray-100"
|
||||
>
|
||||
<IconMore />
|
||||
<template #popper>
|
||||
<div class="w-48 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
:route="{
|
||||
name: 'UserDetail',
|
||||
params: { name: '-' },
|
||||
}"
|
||||
>
|
||||
{{ $t("core.sidebar.operations.profile.button") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="handleLogout"
|
||||
>
|
||||
{{ $t("core.sidebar.operations.logout.button") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
@click="
|
||||
$router.push({
|
||||
name: 'UserDetail',
|
||||
params: { name: '-' },
|
||||
})
|
||||
"
|
||||
>
|
||||
{{ $t("core.sidebar.operations.profile.button") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="handleLogout">
|
||||
{{ $t("core.sidebar.operations.logout.button") }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
|
|
@ -21,6 +21,8 @@ import {
|
|||
VEntityField,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import LazyImage from "@/components/image/LazyImage.vue";
|
||||
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
|
||||
|
@ -421,33 +423,25 @@ onMounted(() => {
|
|||
$t("core.attachment.operations.deselect_items.button")
|
||||
}}
|
||||
</VButton>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<VButton>
|
||||
{{ $t("core.attachment.operations.move.button") }}
|
||||
</VButton>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(group, index) in groups"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleMove(group)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ group.spec.displayName }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(group, index) in groups"
|
||||
:key="index"
|
||||
@click="handleMove(group)"
|
||||
>
|
||||
{{ group.spec.displayName }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</VSpace>
|
||||
</div>
|
||||
<div class="mt-4 flex sm:mt-0">
|
||||
<VSpace spacing="lg">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -461,28 +455,16 @@ onMounted(() => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(policy, index) in policies"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedPolicy?.metadata.name ===
|
||||
policy.metadata.name,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSelectPolicy(policy)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ policy.spec.displayName }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(policy, index) in policies"
|
||||
:key="index"
|
||||
:selected="policy === selectedPolicy"
|
||||
@click="handleSelectPolicy(policy)"
|
||||
>
|
||||
{{ policy.spec.displayName }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<UserDropdownSelector
|
||||
v-model:selected="selectedUser"
|
||||
@select="handleSelectUser"
|
||||
|
@ -499,7 +481,7 @@ onMounted(() => {
|
|||
</div>
|
||||
</UserDropdownSelector>
|
||||
<!-- TODO: add filter by ref support -->
|
||||
<FloatingDropdown v-if="false">
|
||||
<VDropdown v-if="false">
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -509,25 +491,11 @@ onMounted(() => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
>
|
||||
<span class="truncate">未被引用</span>
|
||||
</li>
|
||||
<li
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
>
|
||||
<span class="truncate">文章</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem> 未被引用 </VDropdownItem>
|
||||
<VDropdownItem> 文章 </VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<FloatingDropdown>
|
||||
</VDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -539,21 +507,16 @@ onMounted(() => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
<span class="truncate">{{ sortItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
:selected="sortItem.value === selectedSortItem?.value"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
{{ sortItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div
|
||||
v-for="(item, index) in viewTypes"
|
||||
|
@ -810,14 +773,12 @@ onMounted(() => {
|
|||
"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
<VDropdownItem
|
||||
type="danger"
|
||||
@click="handleDelete(attachment)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -8,8 +8,8 @@ import {
|
|||
IconAddCircle,
|
||||
IconMore,
|
||||
Toast,
|
||||
VButton,
|
||||
VSpace,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
VStatusDot,
|
||||
} from "@halo-dev/components";
|
||||
import AttachmentGroupEditingModal from "./AttachmentGroupEditingModal.vue";
|
||||
|
@ -255,67 +255,39 @@ onMounted(async () => {
|
|||
animate
|
||||
/>
|
||||
</div>
|
||||
<FloatingDropdown
|
||||
v-if="!readonly"
|
||||
v-permission="['system:attachments:manage']"
|
||||
>
|
||||
<VDropdown v-if="!readonly" v-permission="['system:attachments:manage']">
|
||||
<IconMore @click.stop />
|
||||
<template #popper>
|
||||
<div class="w-48 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenEditingModal(group)"
|
||||
<VDropdownItem @click="handleOpenEditingModal(group)">
|
||||
{{ $t("core.attachment.group_list.operations.rename.button") }}
|
||||
</VDropdownItem>
|
||||
<VDropdown placement="right" :triggers="['click']">
|
||||
<VDropdownItem type="danger">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VDropdownItem>
|
||||
<template #popper>
|
||||
<VDropdownItem
|
||||
v-close-popper.all
|
||||
type="danger"
|
||||
@click="handleDelete(group)"
|
||||
>
|
||||
{{ $t("core.attachment.group_list.operations.rename.button") }}
|
||||
</VButton>
|
||||
<FloatingDropdown
|
||||
class="w-full"
|
||||
placement="right"
|
||||
:triggers="['click']"
|
||||
{{ $t("core.attachment.group_list.operations.delete.button") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-close-popper.all
|
||||
type="danger"
|
||||
@click="handleDeleteWithAttachments(group)"
|
||||
>
|
||||
<VButton block type="danger">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
<template #popper>
|
||||
<div class="w-52 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper.all
|
||||
block
|
||||
type="danger"
|
||||
size="sm"
|
||||
@click="handleDelete(group)"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
"core.attachment.group_list.operations.delete.button"
|
||||
)
|
||||
}}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper.all
|
||||
block
|
||||
type="danger"
|
||||
size="sm"
|
||||
@click="handleDeleteWithAttachments(group)"
|
||||
>
|
||||
{{
|
||||
$t(
|
||||
"core.attachment.group_list.operations.delete_with_attachments.button"
|
||||
)
|
||||
}}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</div>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VSpace>
|
||||
</div>
|
||||
{{
|
||||
$t(
|
||||
"core.attachment.group_list.operations.delete_with_attachments.button"
|
||||
)
|
||||
}}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VDropdown>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
<div
|
||||
v-if="!loading && !readonly"
|
||||
|
|
|
@ -9,6 +9,8 @@ import {
|
|||
VEntity,
|
||||
VEntityField,
|
||||
VStatusDot,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
Toast,
|
||||
} from "@halo-dev/components";
|
||||
import AttachmentPolicyEditingModal from "./AttachmentPolicyEditingModal.vue";
|
||||
|
@ -126,28 +128,20 @@ const onEditingModalClose = () => {
|
|||
@update:visible="onVisibleChange"
|
||||
>
|
||||
<template #actions>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<span v-tooltip="$t('core.common.buttons.new')">
|
||||
<IconAddCircle />
|
||||
</span>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(policyTemplate, index) in policyTemplates"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ policyTemplate.spec?.displayName }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(policyTemplate, index) in policyTemplates"
|
||||
:key="index"
|
||||
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
|
||||
>
|
||||
{{ policyTemplate.spec?.displayName }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</template>
|
||||
<VEmpty
|
||||
v-if="!policies?.length && !isLoading"
|
||||
|
@ -159,7 +153,7 @@ const onEditingModalClose = () => {
|
|||
<VButton @click="handleFetchPolicies">
|
||||
{{ $t("core.common.buttons.refresh") }}
|
||||
</VButton>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<VButton type="secondary">
|
||||
<template #icon>
|
||||
<IconAddCircle class="h-full w-full" />
|
||||
|
@ -167,23 +161,15 @@ const onEditingModalClose = () => {
|
|||
{{ $t("core.common.buttons.new") }}
|
||||
</VButton>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(policyTemplate, index) in policyTemplates"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ policyTemplate.spec?.displayName }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(policyTemplate, index) in policyTemplates"
|
||||
:key="index"
|
||||
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
|
||||
>
|
||||
{{ policyTemplate.spec?.displayName }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</VSpace>
|
||||
</template>
|
||||
</VEmpty>
|
||||
|
@ -219,22 +205,12 @@ const onEditingModalClose = () => {
|
|||
</VEntityField>
|
||||
</template>
|
||||
<template #dropdownItems>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenEditingModal(policy)"
|
||||
>
|
||||
<VDropdownItem @click="handleOpenEditingModal(policy)">
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDelete(policy)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem type="danger" @click="handleDelete(policy)">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<script lang="ts" setup>
|
||||
import { VModal, IconAddCircle, VAlert } from "@halo-dev/components";
|
||||
import {
|
||||
VModal,
|
||||
IconAddCircle,
|
||||
VAlert,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import UppyUpload from "@/components/upload/UppyUpload.vue";
|
||||
import { ref, watch } from "vue";
|
||||
import type { Policy, PolicyTemplate } from "@halo-dev/api-client";
|
||||
|
@ -175,7 +181,7 @@ watch(
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex h-full cursor-pointer items-center rounded-base bg-gray-100 p-2 text-gray-500 transition-all hover:bg-gray-200 hover:text-gray-900 hover:shadow-sm"
|
||||
>
|
||||
|
@ -187,23 +193,15 @@ watch(
|
|||
<IconAddCircle />
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(policyTemplate, index) in policyTemplates"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ policyTemplate.spec?.displayName }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(policyTemplate, index) in policyTemplates"
|
||||
:key="index"
|
||||
@click="handleOpenCreateNewPolicyModal(policyTemplate)"
|
||||
>
|
||||
{{ policyTemplate.spec?.displayName }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
<div v-if="!policies?.length" class="mb-3">
|
||||
<VAlert
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
VEmpty,
|
||||
Dialog,
|
||||
VLoading,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
Toast,
|
||||
} from "@halo-dev/components";
|
||||
import CommentListItem from "./components/CommentListItem.vue";
|
||||
|
@ -384,7 +386,7 @@ const handleApproveInBatch = async () => {
|
|||
</div>
|
||||
<div class="mt-4 flex sm:mt-0">
|
||||
<VSpace spacing="lg">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -396,28 +398,18 @@ const handleApproveInBatch = async () => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(filterItem, index) in ApprovedFilterItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedApprovedFilterItem.value ===
|
||||
filterItem.value,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleApprovedFilterItemChange(filterItem)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ filterItem.label }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(filterItem, index) in ApprovedFilterItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
selectedApprovedFilterItem.value === filterItem.value
|
||||
"
|
||||
@click="handleApprovedFilterItemChange(filterItem)"
|
||||
>
|
||||
{{ filterItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<UserDropdownSelector
|
||||
v-model:selected="selectedUser"
|
||||
@select="handleSelectUser"
|
||||
|
@ -433,7 +425,7 @@ const handleApproveInBatch = async () => {
|
|||
</span>
|
||||
</div>
|
||||
</UserDropdownSelector>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -445,27 +437,18 @@ const handleApproveInBatch = async () => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(filterItem, index) in SortFilterItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedSortFilterItem.value === filterItem.value,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSortFilterItemChange(filterItem)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ filterItem.label }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(filterItem, index) in SortFilterItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
selectedSortFilterItem.value === filterItem.value
|
||||
"
|
||||
@click="handleSortFilterItemChange(filterItem)"
|
||||
>
|
||||
{{ filterItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div
|
||||
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
IconExternalLinkLine,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
VTag,
|
||||
} from "@halo-dev/components";
|
||||
import ReplyCreationModal from "./ReplyCreationModal.vue";
|
||||
|
@ -386,26 +387,18 @@ const subjectRefResult = computed(() => {
|
|||
v-if="currentUserHasPermission(['system:comments:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
<VDropdownItem
|
||||
v-if="!comment?.comment.spec.approved"
|
||||
v-close-popper
|
||||
type="secondary"
|
||||
block
|
||||
@click="handleApprove"
|
||||
>
|
||||
{{ $t("core.comment.operations.approve_comment_in_batch.button") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
type="secondary"
|
||||
block
|
||||
@click="handleApproveReplyInBatch"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="handleApproveReplyInBatch">
|
||||
{{ $t("core.comment.operations.approve_applies_in_batch.button") }}
|
||||
</VButton>
|
||||
<VButton v-close-popper block type="danger" @click="handleDelete">
|
||||
</VDropdownItem>
|
||||
<VDropdownItem type="danger" @click="handleDelete">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
|
||||
<template v-if="showReplies" #footer>
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
VButton,
|
||||
IconMotionLine,
|
||||
Toast,
|
||||
VDropdown,
|
||||
} from "@halo-dev/components";
|
||||
import SubmitButton from "@/components/button/SubmitButton.vue";
|
||||
import type {
|
||||
|
@ -172,14 +173,14 @@ watchEffect(() => {
|
|||
></FormKit>
|
||||
</FormKit>
|
||||
<div class="mt-2 flex justify-end">
|
||||
<FloatingDropdown>
|
||||
<VDropdown :classes="['!p-0']">
|
||||
<IconMotionLine
|
||||
class="h-5 w-5 cursor-pointer text-gray-500 transition-all hover:text-gray-900"
|
||||
/>
|
||||
<template #popper>
|
||||
<div ref="emojiPickerRef"></div>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
<template #footer>
|
||||
<VSpace>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
VAvatar,
|
||||
VButton,
|
||||
VTag,
|
||||
VEntityField,
|
||||
VEntity,
|
||||
Dialog,
|
||||
VStatusDot,
|
||||
VDropdownItem,
|
||||
IconReplyLine,
|
||||
Toast,
|
||||
} from "@halo-dev/components";
|
||||
|
@ -196,25 +196,20 @@ const isHoveredReply = computed(() => {
|
|||
</VEntityField>
|
||||
</template>
|
||||
<template #dropdownItems>
|
||||
<VButton
|
||||
<VDropdownItem
|
||||
v-if="!reply?.reply.spec.approved"
|
||||
v-permission="['system:comments:manage']"
|
||||
v-close-popper
|
||||
type="secondary"
|
||||
block
|
||||
@click="handleApprove"
|
||||
>
|
||||
{{ $t("core.comment.operations.approve_reply.button") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-permission="['system:comments:manage']"
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDelete"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</template>
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
VStatusDot,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import { ref, watch } from "vue";
|
||||
import type { ListedSinglePage, SinglePage } from "@halo-dev/api-client";
|
||||
|
@ -423,22 +424,15 @@ function handleClearKeyword() {
|
|||
v-if="currentUserHasPermission(['system:singlepages:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
<VDropdownItem
|
||||
type="danger"
|
||||
@click="handleDeletePermanently(singlePage.page)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete_permanently") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="handleRecovery(singlePage.page)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="handleRecovery(singlePage.page)">
|
||||
{{ $t("core.common.buttons.recovery") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -22,6 +22,8 @@ import {
|
|||
VLoading,
|
||||
VPageHeader,
|
||||
Toast,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import SinglePageSettingModal from "./components/SinglePageSettingModal.vue";
|
||||
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
|
||||
|
@ -547,7 +549,7 @@ watch(selectedPageNames, (newValue) => {
|
|||
</div>
|
||||
<div class="mt-4 flex sm:mt-0">
|
||||
<VSpace spacing="lg">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -559,27 +561,19 @@ watch(selectedPageNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(filterItem, index) in PublishStatusItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedPublishStatusItem.value ===
|
||||
filterItem.value,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handlePublishStatusItemChange(filterItem)"
|
||||
>
|
||||
<span class="truncate">{{ filterItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(filterItem, index) in PublishStatusItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
filterItem.value === selectedPublishStatusItem.value
|
||||
"
|
||||
@click="handlePublishStatusItemChange(filterItem)"
|
||||
>
|
||||
{{ filterItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<FloatingDropdown>
|
||||
</VDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -591,27 +585,16 @@ watch(selectedPageNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(filterItem, index) in VisibleItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedVisibleItem.value === filterItem.value,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleVisibleItemChange(filterItem)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ filterItem.label }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(filterItem, index) in VisibleItems"
|
||||
:key="index"
|
||||
:selected="filterItem.value === selectedVisibleItem.value"
|
||||
@click="handleVisibleItemChange(filterItem)"
|
||||
>
|
||||
{{ filterItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<UserDropdownSelector
|
||||
v-model:selected="selectedContributor"
|
||||
@select="handleSelectUser"
|
||||
|
@ -627,7 +610,7 @@ watch(selectedPageNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
</UserDropdownSelector>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -639,21 +622,19 @@ watch(selectedPageNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
<span class="truncate">{{ sortItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
sortItem.sort === selectedSortItem?.sort &&
|
||||
sortItem.sortOrder === selectedSortItem?.sortOrder
|
||||
"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
{{ sortItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div
|
||||
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
|
||||
|
@ -837,22 +818,15 @@ watch(selectedPageNames, (newValue) => {
|
|||
v-if="currentUserHasPermission(['system:singlepages:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenSettingModal(singlePage.page)"
|
||||
>
|
||||
<VDropdownItem @click="handleOpenSettingModal(singlePage.page)">
|
||||
{{ $t("core.common.buttons.setting") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
type="danger"
|
||||
@click="handleDelete(singlePage.page)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
VEntityField,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import PostTag from "./tags/components/PostTag.vue";
|
||||
import { ref, watch } from "vue";
|
||||
|
@ -435,22 +436,15 @@ function handleClearKeyword() {
|
|||
v-if="currentUserHasPermission(['system:posts:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
<VDropdownItem
|
||||
type="danger"
|
||||
@click="handleDeletePermanently(post.post)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete_permanently") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="handleRecovery(post.post)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="handleRecovery(post.post)">
|
||||
{{ $t("core.common.buttons.recovery") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -22,6 +22,8 @@ import {
|
|||
VEntityField,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
VDropdown,
|
||||
} from "@halo-dev/components";
|
||||
import UserDropdownSelector from "@/components/dropdown-selector/UserDropdownSelector.vue";
|
||||
import CategoryDropdownSelector from "@/components/dropdown-selector/CategoryDropdownSelector.vue";
|
||||
|
@ -580,7 +582,7 @@ watch(selectedPostNames, (newValue) => {
|
|||
</div>
|
||||
<div class="mt-4 flex sm:mt-0">
|
||||
<VSpace spacing="lg">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -592,27 +594,19 @@ watch(selectedPostNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(filterItem, index) in PublishStatusItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedPublishStatusItem.value ===
|
||||
filterItem.value,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handlePublishStatusItemChange(filterItem)"
|
||||
>
|
||||
<span class="truncate">{{ filterItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(filterItem, index) in PublishStatusItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
filterItem.value === selectedPublishStatusItem.value
|
||||
"
|
||||
@click="handlePublishStatusItemChange(filterItem)"
|
||||
>
|
||||
{{ filterItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<FloatingDropdown>
|
||||
</VDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -624,27 +618,16 @@ watch(selectedPostNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(filterItem, index) in VisibleItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedVisibleItem.value === filterItem.value,
|
||||
}"
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleVisibleItemChange(filterItem)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ filterItem.label }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(filterItem, index) in VisibleItems"
|
||||
:key="index"
|
||||
:selected="filterItem.value === selectedVisibleItem.value"
|
||||
@click="handleVisibleItemChange(filterItem)"
|
||||
>
|
||||
{{ filterItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<CategoryDropdownSelector
|
||||
v-model:selected="selectedCategory"
|
||||
@select="handleCategoryChange"
|
||||
|
@ -690,7 +673,7 @@ watch(selectedPostNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
</UserDropdownSelector>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -702,21 +685,19 @@ watch(selectedPostNames, (newValue) => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
<span class="truncate">{{ sortItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
sortItem.sort === selectedSortItem?.sort &&
|
||||
sortItem.sortOrder === selectedSortItem?.sortOrder
|
||||
"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
{{ sortItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div
|
||||
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
|
||||
|
@ -932,22 +913,12 @@ watch(selectedPostNames, (newValue) => {
|
|||
v-if="currentUserHasPermission(['system:posts:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenSettingModal(post.post)"
|
||||
>
|
||||
<VDropdownItem @click="handleOpenSettingModal(post.post)">
|
||||
{{ $t("core.common.buttons.setting") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDelete(post.post)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem type="danger" @click="handleDelete(post.post)">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
IconList,
|
||||
VButton,
|
||||
VStatusDot,
|
||||
VEntity,
|
||||
VEntityField,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import Draggable from "vuedraggable";
|
||||
import type { CategoryTree } from "../utils";
|
||||
|
@ -111,24 +111,19 @@ function onDelete(category: CategoryTree) {
|
|||
v-if="currentUserHasPermission(['system:posts:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
<VDropdownItem
|
||||
v-permission="['system:posts:manage']"
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="onOpenEditingModal(category)"
|
||||
>
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-permission="['system:posts:manage']"
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="onDelete(category)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
<CategoryListItem
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
VEntity,
|
||||
VEntityField,
|
||||
VLoading,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import TagEditingModal from "./components/TagEditingModal.vue";
|
||||
import PostTag from "./components/PostTag.vue";
|
||||
|
@ -242,24 +243,19 @@ onMounted(async () => {
|
|||
v-if="currentUserHasPermission(['system:posts:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
<VDropdownItem
|
||||
v-permission="['system:posts:manage']"
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenEditingModal(tag)"
|
||||
>
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-permission="['system:posts:manage']"
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDelete(tag)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
IconList,
|
||||
VButton,
|
||||
VTag,
|
||||
VStatusDot,
|
||||
VEntity,
|
||||
VEntityField,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import Draggable from "vuedraggable";
|
||||
import { ref } from "vue";
|
||||
|
@ -130,30 +130,15 @@ function getMenuItemRefDisplayName(menuItem: MenuTreeItem) {
|
|||
v-if="currentUserHasPermission(['system:menus:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="onOpenEditingModal(menuItem)"
|
||||
>
|
||||
<VDropdownItem @click="onOpenEditingModal(menuItem)">
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="onOpenCreateByParentModal(menuItem)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="onOpenCreateByParentModal(menuItem)">
|
||||
{{ $t("core.menu.operations.add_sub_menu_item.button") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="onDelete(menuItem)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem type="danger" @click="onDelete(menuItem)">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
<MenuItemListItem
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
VTag,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import MenuEditingModal from "./MenuEditingModal.vue";
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
|
@ -258,30 +259,15 @@ onMounted(handleFetchPrimaryMenuName);
|
|||
v-if="currentUserHasPermission(['system:menus:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleSetPrimaryMenu(menu)"
|
||||
>
|
||||
<VDropdownItem @click="handleSetPrimaryMenu(menu)">
|
||||
{{ $t("core.menu.operations.set_primary.button") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="handleOpenEditingModal(menu)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="handleOpenEditingModal(menu)">
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDeleteMenu(menu)"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem type="danger" @click="handleDeleteMenu(menu)">
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -10,11 +10,13 @@ import {
|
|||
VSpace,
|
||||
VTag,
|
||||
IconMore,
|
||||
VButton,
|
||||
Dialog,
|
||||
VAvatar,
|
||||
Toast,
|
||||
VStatusDot,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
VDropdownDivider,
|
||||
} from "@halo-dev/components";
|
||||
import ThemeUploadModal from "./components/ThemeUploadModal.vue";
|
||||
|
||||
|
@ -102,43 +104,25 @@ const onUpgradeModalClose = () => {
|
|||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<FloatingDropdown v-permission="['system:themes:manage']">
|
||||
<VDropdown v-permission="['system:themes:manage']">
|
||||
<div
|
||||
class="cursor-pointer rounded p-1 transition-all hover:text-blue-600 group-hover:bg-gray-100"
|
||||
>
|
||||
<IconMore />
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-48 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="upgradeModal = true"
|
||||
>
|
||||
{{ $t("core.common.buttons.upgrade") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="handleReloadTheme"
|
||||
>
|
||||
{{ $t("core.theme.operations.reload.button") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleResetSettingConfig"
|
||||
>
|
||||
{{ $t("core.common.buttons.reset") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</div>
|
||||
<VDropdownItem @click="upgradeModal = true">
|
||||
{{ $t("core.common.buttons.upgrade") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownDivider />
|
||||
<VDropdownItem type="danger" @click="handleReloadTheme">
|
||||
{{ $t("core.theme.operations.reload.button") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownItem type="danger" @click="handleResetSettingConfig">
|
||||
{{ $t("core.common.buttons.reset") }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-gray-200">
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
IconGitHub,
|
||||
VButton,
|
||||
VSpace,
|
||||
VTag,
|
||||
VEntity,
|
||||
VEntityField,
|
||||
VStatusDot,
|
||||
Dialog,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
VDropdown,
|
||||
VDropdownDivider,
|
||||
} from "@halo-dev/components";
|
||||
import LazyImage from "@/components/image/LazyImage.vue";
|
||||
import type { Theme } from "@halo-dev/api-client";
|
||||
|
@ -192,58 +193,40 @@ const handleUninstall = async (theme: Theme, deleteExtensions?: boolean) => {
|
|||
v-if="currentUserHasPermission(['system:themes:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-if="!isActivated"
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleActiveTheme"
|
||||
>
|
||||
<VDropdownItem v-if="!isActivated" @click="handleActiveTheme">
|
||||
{{ $t("core.common.buttons.active") }}
|
||||
</VButton>
|
||||
<VButton v-close-popper block type="default" @click="emit('upgrade')">
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="emit('upgrade')">
|
||||
{{ $t("core.common.buttons.upgrade") }}
|
||||
</VButton>
|
||||
<VButton v-close-popper block type="default" @click="emit('preview')">
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="emit('preview')">
|
||||
{{ $t("core.common.buttons.preview") }}
|
||||
</VButton>
|
||||
<FloatingDropdown class="w-full" placement="right" :triggers="['click']">
|
||||
<VButton block type="danger">
|
||||
</VDropdownItem>
|
||||
<VDropdownDivider />
|
||||
<VDropdown placement="right" :triggers="['click']">
|
||||
<VDropdownItem type="danger">
|
||||
{{ $t("core.common.buttons.uninstall") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
<template #popper>
|
||||
<div class="w-52 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper.all
|
||||
block
|
||||
type="danger"
|
||||
@click="handleUninstall(theme)"
|
||||
>
|
||||
{{ $t("core.common.buttons.uninstall") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper.all
|
||||
block
|
||||
type="danger"
|
||||
@click="handleUninstall(theme, true)"
|
||||
>
|
||||
{{
|
||||
$t("core.theme.operations.uninstall_and_delete_config.button")
|
||||
}}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-close-popper.all
|
||||
type="danger"
|
||||
@click="handleUninstall(theme)"
|
||||
>
|
||||
{{ $t("core.common.buttons.uninstall") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-close-popper.all
|
||||
type="danger"
|
||||
@click="handleUninstall(theme, true)"
|
||||
>
|
||||
{{ $t("core.theme.operations.uninstall_and_delete_config.button") }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleResetSettingConfig"
|
||||
>
|
||||
</VDropdown>
|
||||
<VDropdownItem type="danger" @click="handleResetSettingConfig">
|
||||
{{ $t("core.common.buttons.reset") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</template>
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
<script lang="ts" setup>
|
||||
import LazyImage from "@/components/image/LazyImage.vue";
|
||||
import type { Theme } from "@halo-dev/api-client";
|
||||
import { VEntity, VEntityField, VTag, VButton } from "@halo-dev/components";
|
||||
import {
|
||||
VEntity,
|
||||
VEntityField,
|
||||
VTag,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import { toRefs } from "vue";
|
||||
import { useThemeLifeCycle } from "../../composables/use-theme";
|
||||
|
||||
|
@ -75,23 +80,12 @@ const { isActivated, handleActiveTheme } = useThemeLifeCycle(theme);
|
|||
</template>
|
||||
|
||||
<template #dropdownItems>
|
||||
<VButton
|
||||
v-if="!isActivated"
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleActiveTheme"
|
||||
>
|
||||
<VDropdownItem v-if="!isActivated" @click="handleActiveTheme">
|
||||
{{ $t("core.common.buttons.active") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="default"
|
||||
@click="emit('open-settings')"
|
||||
>
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="emit('open-settings')">
|
||||
{{ $t("core.common.buttons.setting") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</template>
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
VPagination,
|
||||
VSpace,
|
||||
VLoading,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import PluginListItem from "./components/PluginListItem.vue";
|
||||
import PluginUploadModal from "./components/PluginUploadModal.vue";
|
||||
|
@ -226,7 +228,7 @@ const { data, isLoading, isFetching, refetch } = useQuery<Plugin[]>({
|
|||
</div>
|
||||
<div class="mt-4 flex sm:mt-0">
|
||||
<VSpace spacing="lg">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -238,26 +240,19 @@ const { data, isLoading, isFetching, refetch } = useQuery<Plugin[]>({
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-52 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(enabledItem, index) in EnabledItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
:class="{
|
||||
'bg-gray-100':
|
||||
selectedEnabledItem?.value === enabledItem.value,
|
||||
}"
|
||||
@click="handleEnabledItemChange(enabledItem)"
|
||||
>
|
||||
<span class="truncate">{{ enabledItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(enabledItem, index) in EnabledItems"
|
||||
:key="index"
|
||||
:selected="
|
||||
enabledItem.value === selectedEnabledItem?.value
|
||||
"
|
||||
@click="handleEnabledItemChange(enabledItem)"
|
||||
>
|
||||
{{ enabledItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<FloatingDropdown>
|
||||
</VDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -269,21 +264,16 @@ const { data, isLoading, isFetching, refetch } = useQuery<Plugin[]>({
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
<span class="truncate">{{ sortItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
:selected="sortItem.value === selectedSortItem?.value"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
{{ sortItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div
|
||||
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import {
|
||||
VButton,
|
||||
VSpace,
|
||||
VSwitch,
|
||||
VTag,
|
||||
|
@ -10,6 +9,8 @@ import {
|
|||
VAvatar,
|
||||
Dialog,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
VDropdown,
|
||||
} from "@halo-dev/components";
|
||||
import PluginUploadModal from "./PluginUploadModal.vue";
|
||||
import { ref, toRefs } from "vue";
|
||||
|
@ -169,49 +170,29 @@ const getFailedMessage = (plugin: Plugin) => {
|
|||
v-if="currentUserHasPermission(['system:plugins:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="upgradeModal = true"
|
||||
>
|
||||
<VDropdownItem @click="upgradeModal = true">
|
||||
{{ $t("core.common.buttons.upgrade") }}
|
||||
</VButton>
|
||||
<FloatingDropdown class="w-full" placement="left" :triggers="['click']">
|
||||
<VButton block type="danger">
|
||||
</VDropdownItem>
|
||||
<VDropdown placement="left" :triggers="['click']">
|
||||
<VDropdownItem type="danger">
|
||||
{{ $t("core.common.buttons.uninstall") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
<template #popper>
|
||||
<div class="w-52 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper.all
|
||||
block
|
||||
type="danger"
|
||||
@click="uninstall"
|
||||
>
|
||||
{{ $t("core.common.buttons.uninstall") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper.all
|
||||
block
|
||||
type="danger"
|
||||
@click="uninstall(true)"
|
||||
>
|
||||
{{ $t("core.plugin.list.actions.uninstall_and_delete_config") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</div>
|
||||
<VDropdownItem v-close-popper.all type="danger" @click="uninstall">
|
||||
{{ $t("core.common.buttons.uninstall") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-close-popper.all
|
||||
type="danger"
|
||||
@click="uninstall(true)"
|
||||
>
|
||||
{{ $t("core.plugin.list.actions.uninstall_and_delete_config") }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleResetSettingConfig"
|
||||
>
|
||||
</VDropdown>
|
||||
<VDropdownItem type="danger" @click="handleResetSettingConfig">
|
||||
{{ $t("core.common.buttons.reset") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</template>
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
VEntityField,
|
||||
VLoading,
|
||||
Toast,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import RoleEditingModal from "./components/RoleEditingModal.vue";
|
||||
|
||||
|
@ -249,29 +250,24 @@ const handleDelete = async (role: Role) => {
|
|||
v-if="currentUserHasPermission(['system:roles:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
<VDropdownItem
|
||||
v-if="!isSystemReserved(role)"
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenEditingModal(role)"
|
||||
>
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-if="!isSystemReserved(role)"
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDelete(role)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
<VButton v-close-popper block @click="handleCloneRole(role)">
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="handleCloneRole(role)">
|
||||
{{
|
||||
$t("core.role.operations.create_based_on_this_role.button")
|
||||
}}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -20,6 +20,9 @@ import {
|
|||
Toast,
|
||||
IconRefreshLine,
|
||||
VEmpty,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
VDropdownDivider,
|
||||
} from "@halo-dev/components";
|
||||
import UserEditingModal from "./components/UserEditingModal.vue";
|
||||
import UserPasswordChangeModal from "./components/UserPasswordChangeModal.vue";
|
||||
|
@ -391,7 +394,7 @@ onMounted(() => {
|
|||
</div>
|
||||
<div class="mt-4 flex sm:mt-0">
|
||||
<VSpace spacing="lg">
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -403,28 +406,23 @@ onMounted(() => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-52 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(role, index) in roles"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleRoleChange(role)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{
|
||||
role.metadata.annotations?.[
|
||||
rbacAnnotations.DISPLAY_NAME
|
||||
] || role.metadata.name
|
||||
}}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(role, index) in roles"
|
||||
:key="index"
|
||||
:selected="
|
||||
selectedRole?.metadata.name === role.metadata.name
|
||||
"
|
||||
@click="handleRoleChange(role)"
|
||||
>
|
||||
{{
|
||||
role.metadata.annotations?.[
|
||||
rbacAnnotations.DISPLAY_NAME
|
||||
] || role.metadata.name
|
||||
}}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
<FloatingDropdown>
|
||||
</VDropdown>
|
||||
<VDropdown>
|
||||
<div
|
||||
class="flex cursor-pointer select-none items-center text-sm text-gray-700 hover:text-black"
|
||||
>
|
||||
|
@ -436,21 +434,16 @@ onMounted(() => {
|
|||
</span>
|
||||
</div>
|
||||
<template #popper>
|
||||
<div class="w-72 p-4">
|
||||
<ul class="space-y-1">
|
||||
<li
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
v-close-popper
|
||||
class="flex cursor-pointer items-center rounded px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
<span class="truncate">{{ sortItem.label }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<VDropdownItem
|
||||
v-for="(sortItem, index) in SortItems"
|
||||
:key="index"
|
||||
:selected="selectedSortItem?.value === sortItem.value"
|
||||
@click="handleSortItemChange(sortItem)"
|
||||
>
|
||||
{{ sortItem.label }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div
|
||||
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
|
||||
|
@ -575,44 +568,33 @@ onMounted(() => {
|
|||
v-if="currentUserHasPermission(['system:users:manage'])"
|
||||
#dropdownItems
|
||||
>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="handleOpenCreateModal(user.user)"
|
||||
>
|
||||
<VDropdownItem @click="handleOpenCreateModal(user.user)">
|
||||
{{ $t("core.user.operations.update_profile.title") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
@click="handleOpenPasswordChangeModal(user.user)"
|
||||
>
|
||||
{{ $t("core.user.operations.change_password.title") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-if="
|
||||
userStore.currentUser?.metadata.name !==
|
||||
user.user.metadata.name
|
||||
"
|
||||
v-close-popper
|
||||
block
|
||||
@click="handleOpenGrantPermissionModal(user.user)"
|
||||
>
|
||||
{{ $t("core.user.operations.grant_permission.title") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
</VDropdownItem>
|
||||
<VDropdownItem
|
||||
v-if="
|
||||
userStore.currentUser?.metadata.name !==
|
||||
user.user.metadata.name
|
||||
"
|
||||
v-close-popper
|
||||
block
|
||||
type="danger"
|
||||
@click="handleDelete(user.user)"
|
||||
>
|
||||
{{ $t("core.common.buttons.delete") }}
|
||||
</VButton>
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</VEntity>
|
||||
</li>
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
<script lang="ts" setup>
|
||||
import BasicLayout from "@/layouts/BasicLayout.vue";
|
||||
import { apiClient } from "@/utils/api-client";
|
||||
import { VButton, VSpace, VTabbar, VAvatar } from "@halo-dev/components";
|
||||
import {
|
||||
VButton,
|
||||
VTabbar,
|
||||
VAvatar,
|
||||
VDropdown,
|
||||
VDropdownItem,
|
||||
} from "@halo-dev/components";
|
||||
import {
|
||||
computed,
|
||||
onMounted,
|
||||
|
@ -141,32 +147,19 @@ const handleTabChange = (id: string) => {
|
|||
currentUserHasPermission(['system:users:manage']) || isCurrentUser
|
||||
"
|
||||
>
|
||||
<FloatingDropdown>
|
||||
<VDropdown>
|
||||
<VButton type="default">
|
||||
{{ $t("core.common.buttons.edit") }}
|
||||
</VButton>
|
||||
<template #popper>
|
||||
<div class="w-48 p-2">
|
||||
<VSpace class="w-full" direction="column">
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
type="secondary"
|
||||
@click="editingModal = true"
|
||||
>
|
||||
{{ $t("core.user.detail.actions.update_profile.title") }}
|
||||
</VButton>
|
||||
<VButton
|
||||
v-close-popper
|
||||
block
|
||||
@click="passwordChangeModal = true"
|
||||
>
|
||||
{{ $t("core.user.detail.actions.change_password.title") }}
|
||||
</VButton>
|
||||
</VSpace>
|
||||
</div>
|
||||
<VDropdownItem @click="editingModal = true">
|
||||
{{ $t("core.user.detail.actions.update_profile.title") }}
|
||||
</VDropdownItem>
|
||||
<VDropdownItem @click="passwordChangeModal = true">
|
||||
{{ $t("core.user.detail.actions.change_password.title") }}
|
||||
</VDropdownItem>
|
||||
</template>
|
||||
</FloatingDropdown>
|
||||
</VDropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { App } from "vue";
|
||||
import { Dropdown, Menu, Tooltip, VClosePopper, VTooltip } from "floating-vue";
|
||||
import "floating-vue/dist/style.css";
|
||||
import { VClosePopper, VTooltip } from "@halo-dev/components";
|
||||
// @ts-ignore
|
||||
import VueGridLayout from "vue-grid-layout";
|
||||
import { defaultConfig, plugin as FormKit } from "@formkit/vue";
|
||||
|
@ -17,7 +16,4 @@ export function setupComponents(app: App) {
|
|||
|
||||
app.directive("tooltip", VTooltip);
|
||||
app.directive("close-popper", VClosePopper);
|
||||
app.component("FloatingDropdown", Dropdown);
|
||||
app.component("FloatingTooltip", Tooltip);
|
||||
app.component("FloatingMenu", Menu);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue