halo/ui/console-src/modules/interface/themes/ThemeDetail.vue

249 lines
8.0 KiB
Vue
Raw Normal View History

<script lang="ts" setup>
// types
import type { Ref } from "vue";
// core libs
import { inject, ref } from "vue";
import { useThemeLifeCycle } from "./composables/use-theme";
// components
import {
Dialog,
IconMore,
Toast,
VAvatar,
VDescription,
VDescriptionItem,
VDropdown,
VDropdownDivider,
VDropdownItem,
VStatusDot,
VTag,
} from "@halo-dev/components";
feat: add support for theme management (halo-dev/console#592) Signed-off-by: Ryan Wang <i@ryanc.cc> <!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? /kind feature /milestone 2.0 <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind optimization 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> #### What this PR does / why we need it: 添加基础的主题管理支持,适配 https://github.com/halo-dev/halo/pull/2280 /hold until https://github.com/halo-dev/halo/pull/2280 merge #### Which issue(s) this PR fixes: <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> None #### Screenshots: |<img width="1564" alt="image" src="https://user-images.githubusercontent.com/21301288/182314023-546d5fe1-03bb-4c7e-af36-6730ab051931.png">|<img width="1564" alt="image" src="https://user-images.githubusercontent.com/21301288/182314339-6c13b60a-cddc-449d-a06f-faaa53f76335.png">| | ---- | ---- | |<img width="1564" alt="image" src="https://user-images.githubusercontent.com/21301288/182314487-4c551208-938c-4582-bce6-7f589f278e8f.png">| | <!-- 如果此 PR 有 UI 的改动,最好截图说明这个 PR 的改动。 If there are UI changes to this PR, it is best to take a screenshot to illustrate the changes to this PR. eg. Before: ![screenshot-before](https://user-images.githubusercontent.com/screenshot.png) After: ![screenshot-after](https://user-images.githubusercontent.com/screenshot.png) --> #### Special notes for your reviewer: None #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note None ```
2022-08-03 03:30:13 +00:00
import type { Theme } from "@halo-dev/api-client";
import { apiClient } from "@/utils/api-client";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const selectedTheme = inject<Ref<Theme | undefined>>("selectedTheme", ref());
const themesModal = inject<Ref<boolean>>("themesModal");
const { isActivated, getFailedMessage, handleResetSettingConfig } =
useThemeLifeCycle(selectedTheme);
async function handleClearCache() {
Dialog.warning({
title: t("core.theme.operations.clear_templates_cache.title"),
description: t("core.theme.operations.clear_templates_cache.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
async onConfirm() {
if (!selectedTheme.value) {
console.error("No selected or activated theme");
return;
}
await apiClient.theme.invalidateCache({
name: selectedTheme.value?.metadata.name,
});
Toast.success(t("core.common.toast.operation_success"));
},
});
}
const handleReloadTheme = async () => {
Dialog.warning({
title: t("core.theme.operations.reload.title"),
description: t("core.theme.operations.reload.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
onConfirm: async () => {
try {
if (!selectedTheme?.value) {
return;
}
await apiClient.theme.reload({
name: selectedTheme.value.metadata.name as string,
});
Toast.success(t("core.theme.operations.reload.toast_success"));
window.location.reload();
} catch (e) {
console.error("Failed to reload theme setting", e);
}
},
});
};
</script>
<template>
<Transition mode="out-in" name="fade">
<div class="overflow-hidden rounded-b-base">
<div class="bg-white px-4 py-4 sm:px-6">
<div class="group flex items-center justify-between">
<div class="flex flex-row items-center gap-3">
<VAvatar
:key="selectedTheme?.metadata.name"
:alt="selectedTheme?.spec.displayName"
:src="selectedTheme?.spec.logo"
size="lg"
/>
<div>
<h3 class="text-lg font-medium leading-6 text-gray-900">
{{ selectedTheme?.spec.displayName }}
</h3>
<p class="mt-1 flex max-w-2xl items-center gap-2">
<span class="text-sm text-gray-500">
{{ selectedTheme?.spec.version }}
</span>
<VTag>
{{
isActivated
? t("core.common.status.activated")
: t("core.common.status.not_activated")
}}
</VTag>
<VStatusDot
v-if="getFailedMessage()"
v-tooltip="getFailedMessage()"
state="warning"
animate
/>
</p>
</div>
</div>
<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>
<VDropdownItem @click="themesModal = true">
{{ $t("core.common.buttons.upgrade") }}
</VDropdownItem>
<VDropdownDivider />
<VDropdownItem type="danger" @click="handleReloadTheme">
{{ $t("core.theme.operations.reload.button") }}
</VDropdownItem>
<VDropdownItem type="danger" @click="handleClearCache">
{{ $t("core.theme.operations.clear_templates_cache.button") }}
</VDropdownItem>
<VDropdownItem type="danger" @click="handleResetSettingConfig">
{{ $t("core.common.buttons.reset") }}
</VDropdownItem>
</template>
</VDropdown>
</div>
feat: add theme settings support (halo-dev/console#593) Signed-off-by: Ryan Wang <i@ryanc.cc> <!-- Thanks for sending a pull request! Here are some tips for you: 1. 如果这是你的第一次,请阅读我们的贡献指南:<https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>。 1. If this is your first time, please read our contributor guidelines: <https://github.com/halo-dev/halo/blob/master/CONTRIBUTING.md>. 2. 请根据你解决问题的类型为 Pull Request 添加合适的标签。 2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. 3. 请确保你已经添加并运行了适当的测试。 3. Ensure you have added or ran the appropriate tests for your PR. --> #### What type of PR is this? /kind feature /milestone 2.0 <!-- 添加其中一个类别: Add one of the following kinds: /kind bug /kind cleanup /kind documentation /kind feature /kind optimization 适当添加其中一个或多个类别(可选): Optionally add one or more of the following kinds if applicable: /kind api-change /kind deprecation /kind failing-test /kind flake /kind regression --> #### What this PR does / why we need it: 为主题添加设置表单支持,适配 https://github.com/halo-dev/halo/pull/2299 /hold until https://github.com/halo-dev/halo/pull/2299 merge #### Which issue(s) this PR fixes: Fixes https://github.com/halo-dev/halo/issues/2298 <!-- PR 合并时自动关闭 issue。 Automatically closes linked issue when PR is merged. 用法:`Fixes #<issue 号>`,或者 `Fixes (粘贴 issue 完整链接)` Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> #### Screenshots: |<img width="1564" alt="image" src="https://user-images.githubusercontent.com/21301288/182583412-f14a890e-25ee-418c-b921-0924f94c0d1b.png">|<img width="1564" alt="image" src="https://user-images.githubusercontent.com/21301288/182583525-26fe165c-2dd0-4068-9d52-659dc626367a.png">| | ---- | ---- | <!-- 如果此 PR 有 UI 的改动,最好截图说明这个 PR 的改动。 If there are UI changes to this PR, it is best to take a screenshot to illustrate the changes to this PR. eg. Before: ![screenshot-before](https://user-images.githubusercontent.com/screenshot.png) After: ![screenshot-after](https://user-images.githubusercontent.com/screenshot.png) --> #### Special notes for your reviewer: 测试方式: 1. Halo 后端需要 checkout 到 https://github.com/halo-dev/halo/pull/2299 分支。 2. 将被测主题放置在 `~/halo-next/themes`,可以使用 https://github.com/ruibaby/theme-astro-starter 3. 使用主题内的 `theme.yaml` 和 `settings.yaml` 创建 `Theme` 和 `Setting` 的资源。 4. admin 需要 checkout 到当前 PR 的分支,启动开发服务之后在主题列表即可启用该主题。 5. 测试保存和更新主题配置。 #### Does this PR introduce a user-facing change? <!-- 如果当前 Pull Request 的修改不会造成用户侧的任何变更,在 `release-note` 代码块儿中填写 `NONE`。 否则请填写用户侧能够理解的 Release Note。如果当前 Pull Request 包含破坏性更新(Break Change), Release Note 需要以 `action required` 开头。 If no, just write "NONE" in the release-note block below. If yes, a release note is required: Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required". --> ```release-note None ```
2022-08-04 01:44:13 +00:00
</div>
<div class="border-t border-gray-200">
<VDescription>
<VDescriptionItem
label="ID"
:content="selectedTheme?.metadata.name"
/>
<VDescriptionItem
:label="$t('core.theme.detail.fields.description')"
:content="
selectedTheme?.spec.description || $t('core.common.text.none')
"
></VDescriptionItem>
<VDescriptionItem :label="$t('core.theme.detail.fields.author')">
<a
v-if="selectedTheme?.spec.author"
:href="selectedTheme.spec.author.website || '#'"
class="hover:text-gray-600"
target="_blank"
>
{{ selectedTheme.spec.author.name }}
</a>
<span v-else>
{{ $t("core.common.text.none") }}
</span>
</VDescriptionItem>
<VDescriptionItem
:label="$t('core.theme.detail.fields.version')"
:content="selectedTheme?.spec.version"
/>
<VDescriptionItem
:label="$t('core.theme.detail.fields.requires')"
:content="selectedTheme?.spec.requires"
/>
<VDescriptionItem :label="$t('core.theme.detail.fields.homepage')">
<a
v-if="selectedTheme?.spec.homepage"
:href="selectedTheme.spec.homepage"
class="hover:text-gray-600"
target="_blank"
>
{{ selectedTheme.spec.homepage }}
</a>
<span v-else>
{{ $t("core.common.text.none") }}
</span>
</VDescriptionItem>
<VDescriptionItem :label="$t('core.theme.detail.fields.repo')">
<a
v-if="selectedTheme?.spec.repo"
:href="selectedTheme.spec.repo"
class="hover:text-gray-600"
target="_blank"
>
{{ selectedTheme.spec.repo }}
</a>
<span v-else>
{{ $t("core.common.text.none") }}
</span>
</VDescriptionItem>
<VDescriptionItem :label="$t('core.theme.detail.fields.issues')">
<a
v-if="selectedTheme?.spec.issues"
:href="selectedTheme.spec.issues"
class="hover:text-gray-600"
target="_blank"
>
{{ selectedTheme.spec.issues }}
</a>
<span v-else>
{{ $t("core.common.text.none") }}
</span>
</VDescriptionItem>
<VDescriptionItem :label="$t('core.theme.detail.fields.license')">
<ul
v-if="
selectedTheme?.spec.license &&
selectedTheme?.spec.license.length
"
class="list-inside"
:class="{ 'list-disc': selectedTheme?.spec.license.length > 1 }"
>
<li
v-for="(license, index) in selectedTheme.spec.license"
:key="index"
>
<a v-if="license.url" :href="license.url" target="_blank">
{{ license.name }}
</a>
<span v-else>
{{ license.name }}
</span>
</li>
</ul>
<span v-else>
{{ $t("core.common.text.none") }}
</span>
</VDescriptionItem>
<VDescriptionItem
:label="$t('core.theme.detail.fields.storage_location')"
:content="selectedTheme?.status?.location"
/>
</VDescription>
</div>
</div>
</Transition>
</template>