aboutsummaryrefslogtreecommitdiff
path: root/front-end/src/views/Blog/components/Posts/PostEdit.vue
diff options
context:
space:
mode:
authorLibravatar vnugent <public@vaughnnugent.com>2023-07-12 01:28:23 -0400
committerLibravatar vnugent <public@vaughnnugent.com>2023-07-12 01:28:23 -0400
commitf64955c69d91e578e580b409ba31ac4b3477da96 (patch)
tree16f01392ddf1abfea13d7d1ede3bfb0459fe8f0d /front-end/src/views/Blog/components/Posts/PostEdit.vue
Initial commit
Diffstat (limited to 'front-end/src/views/Blog/components/Posts/PostEdit.vue')
-rw-r--r--front-end/src/views/Blog/components/Posts/PostEdit.vue155
1 files changed, 155 insertions, 0 deletions
diff --git a/front-end/src/views/Blog/components/Posts/PostEdit.vue b/front-end/src/views/Blog/components/Posts/PostEdit.vue
new file mode 100644
index 0000000..4f7b52b
--- /dev/null
+++ b/front-end/src/views/Blog/components/Posts/PostEdit.vue
@@ -0,0 +1,155 @@
+<template>
+ <div id="new-post-editor" class="flex flex-col w-full">
+ <div class="my-4 ml-auto">
+ <div class="button-group">
+ <!-- Submit the post form -->
+ <button class="btn primary" form="post-edit-form">Save</button>
+ <button class="btn" @click="onClose">Cancel</button>
+ </div>
+ </div>
+ <div class="mx-auto">
+ <h4 class="text-center">Edit Post</h4>
+ <p>
+ Add or edit a post to publish to your blog.
+ </p>
+ </div>
+ <div class="relative">
+ <div class="absolute top-2 right-10">
+ <button class="btn no-border" @click="setMeAsAuthor">@Me</button>
+ </div>
+ </div>
+ <dynamic-form
+ id="post-edit-form"
+ class="mx-auto"
+ :form="schema"
+ :disabled="false"
+ :validator="v$"
+ @submit="onSubmit"
+ />
+
+ <div id="post-content-editor" class="px-6" :class="{'invalid':v$.content.$invalid}">
+ <Editor @change="onContentChanged" :blog="$props.blog" @load="onEditorLoad" />
+ </div>
+
+ <FeedFields :properties="postProperties" :blog="$props.blog" />
+
+ <div class="mx-auto my-4">
+ <div class="button-group">
+ <!-- Submit the post form -->
+ <button class="btn primary" form="post-edit-form">Save</button>
+ <button class="btn" @click="onClose">Cancel</button>
+ <button v-if="!isNew" class="btn red" @click="onDelete">Delete Forever</button>
+ </div>
+ </div>
+ </div>
+</template>
+<script setup lang="ts">
+import { computed } from 'vue';
+import { BlogState } from '../../blog-api';
+import { reactiveComputed } from '@vueuse/core';
+import { isNil, isString, split } from 'lodash';
+import { PostMeta, useXmlProperties } from '@vnuge/cmnext-admin';
+import { apiCall, useConfirm, useUser } from '@vnuge/vnlib.browser';
+import { getPostForm } from '../../form-helpers';
+import Editor from '../../ckeditor/Editor.vue';
+import FeedFields from '../FeedFields.vue';
+
+const emit = defineEmits(['close', 'submit', 'delete']);
+const props = defineProps<{
+ blog: BlogState
+}>()
+
+const { reveal } = useConfirm();
+const { getProfile } = useUser();
+const { schema, getValidator } = getPostForm();
+
+const { posts, content } = props.blog;
+
+const isNew = computed(() => isNil(posts.selectedItem.value));
+
+/* Post meta may load delayed from the api so it must be computed
+and reactive, it may also be empty when a new post is created */
+const postBuffer = reactiveComputed<PostMeta>(() => {
+ return {
+ ...posts.selectedItem.value,
+ content: ''
+ } as PostMeta
+});
+
+const { v$, validate } = getValidator(postBuffer);
+
+//Wrap the post properties in an xml feed editor
+const postProperties = useXmlProperties(posts.selectedItem);
+
+const onSubmit = async () =>{
+ if(!await validate()){
+ return;
+ }
+
+ //get all properties
+ const p = postProperties.getCurrentProperties();
+
+ const post = {
+ ...postBuffer,
+ properties: p,
+ content: undefined
+ }
+
+ //Remove the content from the post object
+ delete post.content;
+
+ //Convert the tags string to an array of strings
+ post.tags = isString(post.tags) ? split(post.tags, ',') : post.tags;
+
+ emit('submit', { post, content: v$.value.content.$model});
+}
+
+const onClose = () => emit('close');
+
+const onContentChanged = (content: string) => {
+ //Set the validator content string
+ v$.value.content.$model = content;
+}
+
+const onDelete = async () => {
+ //Show confirm
+ const { isCanceled } = await reveal({
+ title: 'Delete Post?',
+ text: 'Are you sure you want to delete this post? This action cannot be undone.',
+ })
+ if (isCanceled) {
+ return;
+ }
+
+ if (!confirm('Are you sure you want to delete this post forever?')) {
+ return;
+ }
+
+ //Emit the delete event with the original post
+ emit('delete', posts.selectedItem.value)
+}
+
+const setMeAsAuthor = () => {
+ apiCall(async () => {
+ const { first, last } = await getProfile<{first?:string, last?:string, email:string}>();
+ v$.value.author.$model = `${first} ${last}`
+ })
+}
+
+const onEditorLoad = async (editor : any) =>{
+
+ //Get the initial content
+ const postContent = await content.getSelectedPostContent();
+
+ //Set the initial content
+ if(!isNil(postContent)){
+ onContentChanged(postContent);
+ editor.setData(postContent);
+ }
+}
+
+</script>
+
+<style lang="scss">
+
+</style> \ No newline at end of file