diff options
Diffstat (limited to 'lib/admin')
-rw-r--r-- | lib/admin/src/content/computedContent.ts | 14 | ||||
-rw-r--r-- | lib/admin/src/content/useContent.ts | 40 | ||||
-rw-r--r-- | lib/admin/src/posts/computedPosts.ts | 12 | ||||
-rw-r--r-- | lib/admin/src/types.ts | 22 |
4 files changed, 72 insertions, 16 deletions
diff --git a/lib/admin/src/content/computedContent.ts b/lib/admin/src/content/computedContent.ts index 65c1537..75a25f8 100644 --- a/lib/admin/src/content/computedContent.ts +++ b/lib/admin/src/content/computedContent.ts @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -import { Ref, computed } from "vue"; +import { Ref, computed, ref } from "vue"; import { find, filter, includes, isEqual, isNil, toLower } from 'lodash-es'; import { apiCall } from "@vnuge/vnlib.browser" import { ContentMeta, BlogEntity, ContentApi, ComputedBlogApi, BlogAdminContext } from "../types.js"; @@ -30,6 +30,10 @@ export interface ComputedContent extends ContentApi, ComputedBlogApi<ContentMeta * @param filter The reactive filter used to filter the content */ createReactiveSearch(filter: Ref<string>): Ref<ContentMeta[] | undefined>; + /** + * triggers a refresh of the content + */ + refresh(): void } /** @@ -41,11 +45,12 @@ export const useComputedContent = (context: BlogAdminContext): ComputedContent = //Get the content api from the context const contentApi = useContent(context); + const trigger = ref(0); const { content, post, channel } = context.getQuery(); //Watch for channel and selected id changes and get the content - const items = watchAndCompute([channel, content, post], async () => { + const items = watchAndCompute([channel, content, post, trigger], async () => { //Get all content if the channel is set, otherwise return empty array return channel.value ? await apiCall(contentApi.getAllContent) ?? [] : []; }, []); @@ -70,6 +75,10 @@ export const useComputedContent = (context: BlogAdminContext): ComputedContent = }) } + const refresh = () => { + trigger.value++; + } + return { ...contentApi, items, @@ -78,5 +87,6 @@ export const useComputedContent = (context: BlogAdminContext): ComputedContent = createReactiveSearch, selectedId: content, getQuery: context.getQuery, + refresh }; } diff --git a/lib/admin/src/content/useContent.ts b/lib/admin/src/content/useContent.ts index d23177c..47d27b8 100644 --- a/lib/admin/src/content/useContent.ts +++ b/lib/admin/src/content/useContent.ts @@ -13,8 +13,9 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -import { includes, isEmpty } from 'lodash-es'; +import { includes, isArray, isEmpty, join, map } from 'lodash-es'; import { WebMessage } from "@vnuge/vnlib.browser" +import { AxiosRequestConfig } from 'axios'; import { PostMeta, ContentMeta, ContentApi, BlogEntity, BlogAdminContext } from "../types.js"; @@ -56,14 +57,14 @@ export const useContent = (context : BlogAdminContext): ContentApi => { * @param cotentId The id of the content to get the raw value of * @returns A promise that resolves to the raw content string */ - const getContent = async (cotentId: string): Promise<string> => { + const _getContent = async (cotentId: string): Promise<string> => { const url = getUrl(); const response = await axios.get(`${url}&id=${cotentId}`); return await response.data; } const getPostContent = async (post: BlogEntity): Promise<string> => { - return await getContent(post.id); + return await _getContent(post.id); } const getAllContent = async (): Promise<ContentMeta[]> => { @@ -72,15 +73,31 @@ export const useContent = (context : BlogAdminContext): ContentApi => { return response.data; } - const deleteContent = async (content: ContentMeta): Promise<void> => { + const deleteContent = async (content: ContentMeta | ContentMeta[]): Promise<void> => { const url = getUrl(); - await axios.delete(`${url}&id=${content.id}`); + + if(isArray(content)){ + const ids = join(map(content, x => x.id)); + //bulk delete by setting multiple ids + const { data } = await axios.delete<WebMessage<string[]>>(`${url}&ids=${ids}`); + + //Delete results returns a webmessage that contains the ids of the successfully deleted items + const deleted = data.getResultOrThrow(); + if(deleted.length !== content.length){ + throw { message: 'Some items failed to delete' } + } + } + else{ + await axios.delete(`${url}&id=${content.id}`); + } + } - const uploadContent = async (file: File, name: string): Promise<ContentMeta> => { + const uploadContent = async (file: File, name: string, config?:AxiosRequestConfig): Promise<ContentMeta> => { const url = getUrl(); //Endpoint returns the new content meta for the uploaded content const { data } = await axios.put<WebMessage<ContentMeta>>(url, file, { + ...config, headers: { 'Content-Type': getContentType(file), //Set the content name header as the supplied content name @@ -103,10 +120,11 @@ export const useContent = (context : BlogAdminContext): ContentApi => { return data.getResultOrThrow(); } - const updateContent = async (content: ContentMeta, data: File): Promise<ContentMeta> => { + const updateContent = async (content: ContentMeta, data: File, config?: AxiosRequestConfig): Promise<ContentMeta> => { const url = getUrl(); const response = await axios.put<ContentMeta>(`${url}&id=${content.id}`, data, { + ...config, headers: { 'Content-Type': getContentType(data), //Set the content name header as the supplied content name @@ -136,6 +154,11 @@ export const useContent = (context : BlogAdminContext): ContentApi => { return response.data.result; } + const getContent = async (id: string): Promise<ContentMeta | undefined> => { + const index = await getAllContent(); + return index.find(x => x.id === id); + } + return { getPostContent, getAllContent, @@ -144,6 +167,7 @@ export const useContent = (context : BlogAdminContext): ContentApi => { updateContentName, updatePostContent, updateContent, - getPublicUrl + getPublicUrl, + getContent }; } diff --git a/lib/admin/src/posts/computedPosts.ts b/lib/admin/src/posts/computedPosts.ts index 44171a5..640226f 100644 --- a/lib/admin/src/posts/computedPosts.ts +++ b/lib/admin/src/posts/computedPosts.ts @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. -import { computed } from "vue"; +import { computed, ref } from "vue"; import { isEqual, find } from 'lodash-es'; import { apiCall } from "@vnuge/vnlib.browser"; import { PostMeta, ComputedPosts, BlogAdminContext } from "../types"; @@ -28,11 +28,12 @@ import { watchAndCompute } from "../helpers"; export const useComputedPosts = (context: BlogAdminContext): ComputedPosts => { //Post api around the post url and channel const postApi = usePostApi(context); + const trigger = ref(0); const { channel, post } = context.getQuery(); //Get all posts - const items = watchAndCompute([channel, post], async () => { + const items = watchAndCompute([channel, post, trigger], async () => { return channel.value ? await apiCall(postApi.getPosts) ?? [] : []; }, []) @@ -40,11 +41,16 @@ export const useComputedPosts = (context: BlogAdminContext): ComputedPosts => { return find(items.value, p => isEqual(p.id, post.value)); }) + const refresh = () => { + trigger.value++; + } + return { ...postApi, items, selectedItem, selectedId:post, - getQuery: context.getQuery + getQuery: context.getQuery, + refresh }; }
\ No newline at end of file diff --git a/lib/admin/src/types.ts b/lib/admin/src/types.ts index f03c008..60b0064 100644 --- a/lib/admin/src/types.ts +++ b/lib/admin/src/types.ts @@ -14,7 +14,7 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. import { UseOffsetPaginationReturn } from '@vueuse/core'; -import { AxiosInstance } from 'axios'; +import { AxiosInstance, AxiosRequestConfig } from 'axios'; import { Dictionary } from 'lodash'; import { Ref } from 'vue'; @@ -185,17 +185,29 @@ export interface ContentApi { */ getAllContent(): Promise<ContentMeta[]>; /** + * Gets a single content meta object by its id + * @param id The id of the content meta object to get + * @returns A promise that resolves to the content meta object + */ + getContent(id: string): Promise<ContentMeta | undefined>; + /** * Deletes a content meta object from the server in the current channel * @param content The content meta object to delete + * @returns A promise that resolves when the content has been deleted */ deleteContent(content: ContentMeta): Promise<void>; /** + * Deletes an array of content meta objects from the server in the current channel + * @param content The content items to delete + */ + deleteContent(content: ContentMeta[]): Promise<void>; + /** * Uploads a content file to the server in the current channel * @param content The content file to upload * @param name The name of the content file * @returns A promise that resolves to the content meta object for the uploaded content */ - uploadContent(data: File, name: string): Promise<ContentMeta>; + uploadContent(data: File, name: string, config?: AxiosRequestConfig): Promise<ContentMeta>; /** * Updates the content for a post in the current channel * @param post The post to update the content for @@ -221,7 +233,7 @@ export interface ContentApi { * @param content The content meta object to update * @param data The new content data file */ - updateContent(content: ContentMeta, data: File): Promise<ContentMeta>; + updateContent(content: ContentMeta, data: File, config?:AxiosRequestConfig): Promise<ContentMeta>; } /** @@ -244,6 +256,10 @@ export interface ComputedBlogApi<T> extends CanPaginate<T>{ } export interface ComputedPosts extends PostApi, ComputedBlogApi<PostMeta> { + /** + * Triggers a refresh of the posts + */ + refresh(): void; } /** |