-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
/
InstalledThemes.vue
113 lines (105 loc) · 3.13 KB
/
InstalledThemes.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<script lang="ts" setup>
import {
IconAddCircle,
VButton,
VEmpty,
VSpace,
VLoading,
} from "@halo-dev/components";
import ThemePreviewModal from "../preview/ThemePreviewModal.vue";
import ThemeListItem from "../ThemeListItem.vue";
import { ref, inject, type Ref } from "vue";
import type { Theme } from "@halo-dev/api-client";
import { apiClient } from "@/utils/api-client";
import { useQuery } from "@tanstack/vue-query";
import { useThemeStore } from "@/stores/theme";
const themeStore = useThemeStore();
const selectedTheme = inject<Ref<Theme | undefined>>("selectedTheme", ref());
const activeTabId = inject<Ref<string>>("activeTabId", ref(""));
function handleSelectTheme(theme: Theme) {
selectedTheme.value = theme;
}
const {
data: themes,
isLoading,
isFetching,
refetch,
} = useQuery<Theme[]>({
queryKey: ["installed-themes"],
queryFn: async () => {
const { data } = await apiClient.theme.listThemes({
page: 0,
size: 0,
uninstalled: false,
});
return data.items.sort((a, b) => {
const activatedThemeName = themeStore.activatedTheme?.metadata.name;
if (a.metadata.name === activatedThemeName) {
return -1;
}
if (b.metadata.name === activatedThemeName) {
return 1;
}
return 0;
});
},
refetchInterval(data) {
const deletingThemes = data?.filter(
(theme) => !!theme.metadata.deletionTimestamp
);
return deletingThemes?.length ? 1000 : false;
},
});
// preview
const previewVisible = ref(false);
const selectedPreviewTheme = ref<Theme>();
const handleOpenPreview = (theme: Theme) => {
selectedPreviewTheme.value = theme;
previewVisible.value = true;
};
</script>
<template>
<div id="installed-themes-wrapper">
<VLoading v-if="isLoading" />
<Transition v-else-if="!themes?.length" appear name="fade">
<VEmpty
:message="$t('core.theme.list_modal.empty.message')"
:title="$t('core.theme.list_modal.empty.title')"
>
<template #actions>
<VSpace>
<VButton :loading="isFetching" @click="refetch()">
{{ $t("core.common.buttons.refresh") }}
</VButton>
<VButton
v-permission="['system:themes:manage']"
type="primary"
@click="activeTabId = 'local-upload'"
>
<template #icon>
<IconAddCircle class="h-full w-full" />
</template>
{{ $t("core.theme.common.buttons.install") }}
</VButton>
</VSpace>
</template>
</VEmpty>
</Transition>
<Transition v-else appear name="fade">
<ul class="box-border h-full w-full space-y-3" role="list">
<li v-for="theme in themes" :key="theme.metadata.name">
<ThemeListItem
:theme="theme"
:is-selected="theme.metadata.name === selectedTheme?.metadata?.name"
@select="handleSelectTheme"
@preview="handleOpenPreview(theme)"
/>
</li>
</ul>
</Transition>
<ThemePreviewModal
v-model:visible="previewVisible"
:theme="selectedPreviewTheme"
/>
</div>
</template>