From 0d25abab798c005266a1c0b4eeba957d232d4328 Mon Sep 17 00:00:00 2001 From: vnugent Date: Sat, 16 Dec 2023 02:40:03 -0500 Subject: move blog admin state to pinia store plugin --- front-end/src/store/cmnextAdminPlugin.ts | 176 +++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 front-end/src/store/cmnextAdminPlugin.ts (limited to 'front-end/src/store/cmnextAdminPlugin.ts') diff --git a/front-end/src/store/cmnextAdminPlugin.ts b/front-end/src/store/cmnextAdminPlugin.ts new file mode 100644 index 0000000..a4741ab --- /dev/null +++ b/front-end/src/store/cmnextAdminPlugin.ts @@ -0,0 +1,176 @@ +// Copyright (C) 2023 Vaughn Nugent +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +import 'pinia' +import { MaybeRef, Ref, computed, ref, toRef } from 'vue'; +import { PiniaPluginContext, PiniaPlugin } from 'pinia' +import { find, isEqual } from 'lodash-es'; +import { useRouter } from 'vue-router'; +import { useContent, ContentApi, ContentMeta, + PostMeta, PostApi, BlogChannel, ChannelApi, usePosts, useChannels, + createBlogContext +} from '@vnuge/cmnext-admin'; +import { useRouteQuery } from '@vueuse/router'; +import { useAxios } from '@vnuge/vnlib.browser'; +import { useScriptTag } from '@vueuse/core'; +import { type ReactiveBlogStore, createReactiveBlogApi, QueryType, SortType } from './sharedTypes'; +import { AxiosProgressEvent } from 'axios'; + +export type PostStore = ReactiveBlogStore & PostApi + +export interface ChannelStore extends ReactiveBlogStore, ChannelApi { + editId: string + readonly editChannel: BlogChannel | undefined; +} + +export interface ContentStore extends ReactiveBlogStore, ContentApi { +} + +export interface BlogAdminState{ + content: ContentStore + posts: PostStore + channels: ChannelStore + uploadProgress: number; + waitForEditor(): Promise; + queryState:{ + sort: SortType; + search: string; + pageSize: number; + } +} + +declare module 'pinia' { + export interface PiniaCustomProperties extends BlogAdminState { + } +} + +export const cmnextAdminPlugin = (router: ReturnType, ckEditorUrl: string, pageSize: MaybeRef): PiniaPlugin => { + + return ({ store }: PiniaPluginContext): BlogAdminState => { + + //setup filter search query + const search = useRouteQuery(QueryType.Filter, '', { mode: 'replace', router }); + + //Get sort order query + const sort = useRouteQuery(QueryType.Sort, SortType.CreatedTime, { mode: 'replace', router }); + + const uploadProgress = ref(0) + + const axios = useAxios({ + onUploadProgress: (e: AxiosProgressEvent) => { + uploadProgress.value = Math.round((e.loaded * 100) / e.total!) + }, + //Set to 60 second timeout + timeout: 60 * 1000 + }) + + const initCkEditor = () => { + //Setup cke editor + if ('CKEDITOR' in window === false) { + //Load scripts + const ckEditorTag = useScriptTag(ckEditorUrl) + //Store the wait result on the window for the editor script to wait + const loadPromise = ckEditorTag.load(true); + + return async (): Promise => { + await loadPromise; + } + } + return (): Promise => Promise.resolve() + } + + const blogContext = createBlogContext({ + axios, + channelUrl: '/blog/channels', + postUrl: '/blog/posts', + contentUrl: '/blog/content', + }) + + const channels = (() => { + + //Create channel api + const api = createReactiveBlogApi( + useChannels(blogContext), + { + query: QueryType.Channel, + channelId: undefined, + router, + sort, + search, + pageSize + } + ) + + //route query for the selected channel + const editId = useRouteQuery(QueryType.ChannelEdit, '', { mode: 'push', router }); + + //Compute the selected items from their ids + const editChannel = computed(() => find(api.all.value, c => isEqual(c.id, editId.value))) + + return{ + ...api, + editId, + editChannel + } + })() + + const getContentStore = (): ContentStore => { + //Create post api + return createReactiveBlogApi( + useContent(blogContext, channels.selectedId), + { + query: QueryType.Content, + channelId: toRef(channels.selectedId), + router, + sort, + search, + pageSize + }, + ) + } + + const getPostStore = (): PostStore => { + + //Create post api + return createReactiveBlogApi( + usePosts(blogContext, channels.selectedId), + { + query: QueryType.Post, + channelId: toRef(channels.selectedId), + router, + sort, + search, + pageSize + } + ) + } + + //Load the editor script + const waitForEditor = initCkEditor() + + return { + content: getContentStore(), + posts: getPostStore(), + channels, + uploadProgress, + waitForEditor, + queryState: { + sort, + search, + pageSize + } + } + } +} \ No newline at end of file -- cgit