Skip to content

Commit

Permalink
feat: add supports for clone post
Browse files Browse the repository at this point in the history
  • Loading branch information
ruibaby committed Oct 19, 2024
1 parent 3abcf72 commit 5e8e828
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 9 deletions.
3 changes: 3 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
"@halo-dev/api-client": "^2.20.0",
"@halo-dev/components": "^2.20.0",
"@halo-dev/console-shared": "^2.20.0",
"@tanstack/vue-query": "4",
"@vueuse/core": "^11.1.0",
"@vueuse/router": "^11.1.0",
"axios": "^1.7.7",
"gray-matter": "^4.0.3",
"js-yaml": "^4.1.0",
"lodash-es": "^4.17.21",
"markdown-it": "^14.1.0",
"markdown-it-anchor": "^9.2.0",
"turndown": "^7.2.0",
Expand All @@ -30,6 +32,7 @@
"@tsconfig/node20": "^20.1.4",
"@types/js-yaml": "^4.0.9",
"@types/jsdom": "^21.1.7",
"@types/lodash-es": "^4.17.12",
"@types/markdown-it": "^14.1.2",
"@types/node": "^20.16.12",
"@types/turndown": "^5.0.5",
Expand Down
76 changes: 76 additions & 0 deletions ui/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions ui/src/class/postCloner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { randomUUID } from "@/utils/id";
import {
consoleApiClient,
type ContentWrapper,
type Post,
type PostRequest,
} from "@halo-dev/api-client";
import { Toast } from "@halo-dev/components";
import { cloneDeep, set } from "lodash-es";

class PostCloner {
static async clonePost(post: Post): Promise<void> {
try {
const originalContent = await this.fetchPostContent(post.metadata.name);

const newPostData = this.prepareNewPostData(post, originalContent);

await consoleApiClient.content.post.draftPost({
postRequest: newPostData,
});

Toast.success("文章克隆成功,如果列表没有刷新,请手动刷新一次");
} catch (error) {
console.error("Failed to clone post", error);
Toast.error("克隆文章失败");
}
}

private static async fetchPostContent(
postName: string,
): Promise<ContentWrapper> {
const { data } = await consoleApiClient.content.post.fetchPostHeadContent({
name: postName,
});

return data;
}

private static prepareNewPostData(
originalPost: Post,
content: ContentWrapper,
): PostRequest {
const postToCreate = cloneDeep(originalPost);
set(postToCreate, "spec.baseSnapshot", "");
set(postToCreate, "spec.headSnapshot", "");
set(postToCreate, "spec.releaseSnapshot", "");
set(
postToCreate,
"spec.slug",
`${originalPost.spec.slug}-${randomUUID().split("-")[0]}`,
);
set(postToCreate, "spec.title", originalPost.spec.title + "(副本)");
set(postToCreate, "spec.publish", false);
set(postToCreate, "metadata", {
name: randomUUID(),
});

return {
post: postToCreate,
content: content,
};
}
}

export default PostCloner;
14 changes: 10 additions & 4 deletions ui/src/class/postOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ export class PostOperations {
toType,
);

const convertedContent = converter.convert(post, content);
const convertedRawContent = converter.convert(post, content);

try {
await this.updatePostContent(post, toType, convertedContent);
await this.updatePostContent(
post,
toType,
convertedRawContent,
content.content || "",
);
Toast.success("转换完成");
} catch (error) {
if (error instanceof AxiosError) {
Expand All @@ -44,6 +49,7 @@ export class PostOperations {
private static async updatePostContent(
post: Post,
rawType: string,
raw: string,
content: string,
): Promise<void> {
const published = post.spec.publish;
Expand All @@ -52,8 +58,8 @@ export class PostOperations {
name: post.metadata.name,
content: {
rawType,
raw: content,
content,
raw: raw,
content: content,
},
});

Expand Down
24 changes: 24 additions & 0 deletions ui/src/components/PostCloneDropdownItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import PostCloner from "@/class/postCloner";
import type { ListedPost } from "@halo-dev/api-client";
import { VDropdownItem } from "@halo-dev/components";
import { useQueryClient } from "@tanstack/vue-query";
const queryClient = useQueryClient();
const { post } = defineProps<{
post: ListedPost;
}>();
async function handleClone() {
await PostCloner.clonePost(post.post);
// It may be that the index creation operation cannot obtain the new list in time.
setTimeout(() => {
queryClient.invalidateQueries({ queryKey: ["posts"] });
}, 1000);
}
</script>
<template>
<VDropdownItem @click="handleClone"> 克隆 </VDropdownItem>
</template>
16 changes: 11 additions & 5 deletions ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { markRaw } from "vue";
import { ContentExporter } from "./class/contentExporter";
import { PostOperations } from "./class/postOperations";
import ConverterEditor from "./components/ConverterEditor.vue";
import PostCloneDropdownItem from "./components/PostCloneDropdownItem.vue";

export default definePlugin({
components: {},
Expand Down Expand Up @@ -36,20 +37,19 @@ export default definePlugin({
},
];
},
// @ts-expect-error
"post:list-item:operation:create": () => {
// @ts-expect-error don't important
// Needs upstream to fix this issue
"post:list-item:operation:create": (post: ListedPost) => {
return [
{
priority: 21,
component: markRaw(VDropdownDivider),
permissions: ["system:posts:view"],
},
{
priority: 22,
component: markRaw(VDropdownItem),
label: "转换",
visible: true,
permissions: ["system:posts:view"],
children: [
{
priority: 0,
Expand Down Expand Up @@ -90,7 +90,6 @@ export default definePlugin({
component: markRaw(VDropdownItem),
label: "导出",
visible: true,
permissions: ["system:posts:view"],
children: [
{
priority: 0,
Expand All @@ -112,6 +111,13 @@ export default definePlugin({
},
],
},
{
priority: 24,
component: markRaw(PostCloneDropdownItem),
props: {
post: post,
},
},
];
},
},
Expand Down
7 changes: 7 additions & 0 deletions ui/src/utils/id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function randomUUID() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0,
v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}

0 comments on commit 5e8e828

Please sign in to comment.