diff --git a/package.json b/package.json index 247197080..03d1e1171 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@formkit/inputs": "^1.0.0-beta.11", "@formkit/themes": "^1.0.0-beta.11", "@formkit/vue": "^1.0.0-beta.11", - "@halo-dev/api-client": "^0.0.41", + "@halo-dev/api-client": "^0.0.43", "@halo-dev/components": "workspace:*", "@halo-dev/console-shared": "workspace:*", "@halo-dev/richtext-editor": "^0.0.0-alpha.11", diff --git a/packages/components/src/components/status/StatusDot.vue b/packages/components/src/components/status/StatusDot.vue index 6624bf690..ddb79994b 100644 --- a/packages/components/src/components/status/StatusDot.vue +++ b/packages/components/src/components/status/StatusDot.vue @@ -40,7 +40,7 @@ const classes = computed(() => { } .status-dot-text { - @apply text-gray-500; + @apply text-gray-500 text-xs; } &.status-dot-animate { diff --git a/packages/components/src/icons/icons.ts b/packages/components/src/icons/icons.ts index d50146f47..8dbe498c0 100644 --- a/packages/components/src/icons/icons.ts +++ b/packages/components/src/icons/icons.ts @@ -52,6 +52,8 @@ import IconReplyLine from "~icons/ri/reply-line"; import IconExternalLinkLine from "~icons/ri/external-link-line"; import IconRefreshLine from "~icons/ri/refresh-line"; import IconWindowLine from "~icons/ri/window-line"; +import IconSendPlaneFill from "~icons/ri/send-plane-fill"; +import IconRocketLine from "~icons/ri/rocket-line"; export { IconDashboard, @@ -108,4 +110,6 @@ export { IconExternalLinkLine, IconRefreshLine, IconWindowLine, + IconSendPlaneFill, + IconRocketLine, }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 335f763fd..17d31f513 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: '@formkit/inputs': ^1.0.0-beta.11 '@formkit/themes': ^1.0.0-beta.11 '@formkit/vue': ^1.0.0-beta.11 - '@halo-dev/api-client': ^0.0.41 + '@halo-dev/api-client': ^0.0.43 '@halo-dev/components': workspace:* '@halo-dev/console-shared': workspace:* '@halo-dev/richtext-editor': ^0.0.0-alpha.11 @@ -108,7 +108,7 @@ importers: '@formkit/inputs': 1.0.0-beta.11 '@formkit/themes': 1.0.0-beta.11_tailwindcss@3.2.1 '@formkit/vue': 1.0.0-beta.11_vjnbgdptsk6bkj7ab5a6mk2cwm - '@halo-dev/api-client': 0.0.41 + '@halo-dev/api-client': 0.0.43 '@halo-dev/components': link:packages/components '@halo-dev/console-shared': link:packages/shared '@halo-dev/richtext-editor': 0.0.0-alpha.11_vue@3.2.41 @@ -1953,8 +1953,8 @@ packages: - windicss dev: false - /@halo-dev/api-client/0.0.41: - resolution: {integrity: sha512-YpwoIyT+6BjNEfhQqZPSG7dewmC9AE7wxc/uaIRcVZdKr0C4GLmbiBKGOFFnVWIYr42islhMWjqYCGaiJSzkUg==} + /@halo-dev/api-client/0.0.43: + resolution: {integrity: sha512-bCh5P7AYCYA/nVbAB/t62acrtOaDs8UItFe4JmK1qfeb5vOmFT2FT9jeJFj4ABqa4t4xJxy9hnoxNm6H+iB3IQ==} dev: false /@halo-dev/richtext-editor/0.0.0-alpha.11_vue@3.2.41: diff --git a/src/constants/labels.ts b/src/constants/labels.ts index a903d8112..c5df31e24 100644 --- a/src/constants/labels.ts +++ b/src/constants/labels.ts @@ -11,6 +11,16 @@ export enum roleLabels { // post export enum postLabels { DELETED = "content.halo.run/deleted", + PUBLISHED = "content.halo.run/published", + OWNER = "content.halo.run/owner", + VISIBLE = "content.halo.run/visible", + PHASE = "content.halo.run/phase", +} + +// singlePage +export enum singlePageLabels { + DELETED = "content.halo.run/deleted", + PUBLISHED = "content.halo.run/published", OWNER = "content.halo.run/owner", VISIBLE = "content.halo.run/visible", PHASE = "content.halo.run/phase", diff --git a/src/modules/contents/pages/SinglePageEditor.vue b/src/modules/contents/pages/SinglePageEditor.vue index fe1790b42..541c9d5b3 100644 --- a/src/modules/contents/pages/SinglePageEditor.vue +++ b/src/modules/contents/pages/SinglePageEditor.vue @@ -2,6 +2,8 @@ import { VPageHeader, IconPages, + IconSettings, + IconSendPlaneFill, VSpace, VButton, IconSave, @@ -9,12 +11,15 @@ import { import DefaultEditor from "@/components/editor/DefaultEditor.vue"; import SinglePageSettingModal from "./components/SinglePageSettingModal.vue"; import PostPreviewModal from "../posts/components/PostPreviewModal.vue"; -import type { SinglePageRequest } from "@halo-dev/api-client"; +import type { SinglePage, SinglePageRequest } from "@halo-dev/api-client"; import { v4 as uuid } from "uuid"; import { computed, onMounted, ref } from "vue"; import { apiClient } from "@/utils/api-client"; import { useRouteQuery } from "@vueuse/router"; import cloneDeep from "lodash.clonedeep"; +import { useRouter } from "vue-router"; + +const router = useRouter(); const initialFormState: SinglePageRequest = { page: { @@ -24,7 +29,7 @@ const initialFormState: SinglePageRequest = { template: "", cover: "", deleted: false, - published: false, + publish: false, publishTime: "", pinned: false, allowComment: true, @@ -52,6 +57,7 @@ const initialFormState: SinglePageRequest = { const formState = ref(cloneDeep(initialFormState)); const saving = ref(false); +const publishing = ref(false); const settingModal = ref(false); const previewModal = ref(false); @@ -77,10 +83,21 @@ const handleSave = async () => { } if (isUpdateMode.value) { + // Get latest single page + const { data: latestSinglePage } = + await apiClient.extension.singlePage.getcontentHaloRunV1alpha1SinglePage( + { + name: formState.value.page.metadata.name, + } + ); + + formState.value.page = latestSinglePage; + const { data } = await apiClient.singlePage.updateDraftSinglePage({ name: formState.value.page.metadata.name, singlePageRequest: formState.value, }); + formState.value.page = data; } else { const { data } = await apiClient.singlePage.draftSinglePage({ @@ -89,6 +106,7 @@ const handleSave = async () => { formState.value.page = data; routeQueryName.value = data.metadata.name; } + await handleFetchContent(); } catch (error) { console.error("Failed to save single page", error); @@ -97,6 +115,76 @@ const handleSave = async () => { } }; +const handlePublish = async () => { + try { + publishing.value = true; + + // Set rendered content + formState.value.content.content = formState.value.content.raw; + + if (isUpdateMode.value) { + const { headSnapshot } = formState.value.page.spec; + const { name: singlePageName } = formState.value.page.metadata; + const { data: latestContent } = + await apiClient.content.updateSnapshotContent({ + snapshotName: headSnapshot as string, + contentRequest: { + raw: formState.value.content.raw as string, + content: formState.value.content.content as string, + rawType: formState.value.content.rawType as string, + headSnapshotName: headSnapshot, + subjectRef: { + kind: "SinglePage", + version: "v1alpha1", + group: "content.halo.run", + name: singlePageName, + }, + }, + }); + + // Get latest single page + const { data: latestSinglePage } = + await apiClient.extension.singlePage.getcontentHaloRunV1alpha1SinglePage( + { + name: formState.value.page.metadata.name, + } + ); + + formState.value.page = latestSinglePage; + formState.value.page.spec.publish = true; + formState.value.page.spec.headSnapshot = latestContent.snapshotName; + formState.value.page.spec.releaseSnapshot = + formState.value.page.spec.headSnapshot; + + await apiClient.extension.singlePage.updatecontentHaloRunV1alpha1SinglePage( + { + name: singlePageName, + singlePage: formState.value.page, + } + ); + } else { + formState.value.page.spec.publish = true; + await apiClient.singlePage.draftSinglePage({ + singlePageRequest: formState.value, + }); + } + + router.push({ name: "SinglePages" }); + } catch (error) { + console.error("Failed to publish single page", error); + } finally { + publishing.value = false; + } +}; + +const handlePublishClick = () => { + if (isUpdateMode.value) { + handlePublish(); + } else { + settingModal.value = true; + } +}; + const handleFetchContent = async () => { if (!formState.value.page.spec.headSnapshot) { return; @@ -108,14 +196,33 @@ const handleFetchContent = async () => { formState.value.content = data; }; -const onSettingSaved = (page: SinglePageRequest) => { +const handleOpenSettingModal = async () => { + const { data: latestSinglePage } = + await apiClient.extension.singlePage.getcontentHaloRunV1alpha1SinglePage({ + name: formState.value.page.metadata.name, + }); + formState.value.page = latestSinglePage; + settingModal.value = true; +}; + +const onSettingSaved = (page: SinglePage) => { // Set route query parameter if (!isUpdateMode.value) { - routeQueryName.value = page.page.metadata.name; + routeQueryName.value = page.metadata.name; } - formState.value = page; + formState.value.page = page; settingModal.value = false; + + if (!isUpdateMode.value) { + handleSave(); + } +}; + +const onSettingPublished = (singlePage: SinglePage) => { + formState.value.page = singlePage; + settingModal.value = false; + handlePublish(); }; onMounted(async () => { @@ -135,8 +242,11 @@ onMounted(async () => {