diff options
author | vnugent <public@vaughnnugent.com> | 2024-01-30 15:23:06 -0500 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2024-01-30 15:23:06 -0500 |
commit | 5abc489b9954111d66d1385aa62a3ea962fa0a55 (patch) | |
tree | b1715e5c5e6316f33e3e33fb55397d93200ab518 /front-end/src/views/Blog | |
parent | e4dc63ded324c6e9678603296953bb1f7dea7569 (diff) |
merge upstream. Add dynamic client-side support for optional oauth2 and social login methods
Diffstat (limited to 'front-end/src/views/Blog')
-rw-r--r-- | front-end/src/views/Blog/components/Posts.vue | 51 | ||||
-rw-r--r-- | front-end/src/views/Blog/components/image-preview-dialog.vue | 54 | ||||
-rw-r--r-- | front-end/src/views/Blog/index.vue | 66 |
3 files changed, 81 insertions, 90 deletions
diff --git a/front-end/src/views/Blog/components/Posts.vue b/front-end/src/views/Blog/components/Posts.vue index 647e093..b89d263 100644 --- a/front-end/src/views/Blog/components/Posts.vue +++ b/front-end/src/views/Blog/components/Posts.vue @@ -1,24 +1,3 @@ -<template> - <div id="post-editor" class=""> - <EditorTable title="Manage posts" :show-edit="showEdit" :pagination="pagination" @open-new="openNew"> - <template #table> - <PostTable - :items="items" - @open-edit="openEdit" - @delete="onDelete" - /> - </template> - <template #editor> - <PostEditor - @submit="onSubmit" - @close="closeEdit(true)" - @delete="onDelete" - /> - </template> - </EditorTable> - </div> -</template> - <script setup lang="ts"> import { computed, defineAsyncComponent } from 'vue'; import { isEmpty } from 'lodash-es'; @@ -49,7 +28,7 @@ const closeEdit = (update?: boolean) => { //reload channels if (update) { //must refresh content and posts when a post is updated - refresh(); + refresh(); } //Reset page to top window.scrollTo(0, 0); @@ -62,14 +41,14 @@ const openNew = () => { window.scrollTo(0, 0) } -const onSubmit = async ({post, content } : { post: PostMeta, content: string }) => { +const onSubmit = async ({ post, content }: { post: PostMeta, content: string }) => { debugLog('submitting', post, content); //Check for new channel, or updating old channel if (store.posts.selectedId === 'new') { //Exec create call - await apiCall(async ({toaster}) => { + await apiCall(async ({ toaster }) => { //endpoint returns the content const newMeta = await store.posts.add(post); @@ -86,9 +65,9 @@ const onSubmit = async ({post, content } : { post: PostMeta, content: string }) } else if (!isEmpty(store.posts.selectedId)) { //Exec update call - await apiCall(async ( {toaster} ) => { + await apiCall(async ({ toaster }) => { await store.posts.update(post); - + //Publish the content await store.content.updatePostContent(post, content) @@ -129,6 +108,26 @@ const onDelete = async (post: PostMeta) => { } </script> +<template> + <div id="post-editor" class=""> + <EditorTable title="Manage posts" :show-edit="showEdit" :pagination="pagination" @open-new="openNew"> + <template #table> + <PostTable + :items="items" + @open-edit="openEdit" + @delete="onDelete" + /> + </template> + <template #editor> + <PostEditor + @submit="onSubmit" + @close="closeEdit(true)" + @delete="onDelete" + /> + </template> + </EditorTable> + </div> +</template> <style lang="scss"> diff --git a/front-end/src/views/Blog/components/image-preview-dialog.vue b/front-end/src/views/Blog/components/image-preview-dialog.vue index 5cfe552..b134d19 100644 --- a/front-end/src/views/Blog/components/image-preview-dialog.vue +++ b/front-end/src/views/Blog/components/image-preview-dialog.vue @@ -1,34 +1,14 @@ -<template> - <div class=""> - <Dialog :open="isOpen" @close="onClose" class="relative z-50"> - <!-- The backdrop, rendered as a fixed sibling to the panel container --> - <div class="fixed inset-0 bg-black/30" aria-hidden="true" /> - - <!-- Full-screen container to center the panel --> - <div class="fixed inset-0 flex items-center justify-center w-screen p-4"> - <!-- The actual dialog panel --> - <DialogPanel class="p-2 bg-white rounded dark:bg-dark-700" ref="dialog"> - <DialogDescription> - <img class="preview-image" :src="imgUrl" alt="preview" /> - </DialogDescription> - <!-- ... --> - </DialogPanel> - </div> - </Dialog> - </div> -</template> - <script setup lang="ts"> import { ref, computed, watch, toRefs } from 'vue' import { Dialog, DialogDescription } from '@headlessui/vue' -import { onClickOutside } from '@vueuse/core'; +import { onClickOutside, set } from '@vueuse/core'; import { useStore } from '../../../store'; import { ContentMeta } from '../../../../../lib/admin/dist'; import { isNil } from 'lodash-es'; import { apiCall } from '@vnuge/vnlib.browser'; const emit = defineEmits(['close']) -const props = defineProps<{ +const props = defineProps<{ item: ContentMeta | undefined, }>() @@ -52,19 +32,33 @@ const downloadImage = (item: ContentMeta) => { }) } -//load the image when open -watch(item, (item) => { - if (isNil(item)) { - imgUrl.value = undefined - } else { - downloadImage(item) - } -}) +//load the image when open or remove it if the item is undefined +watch(item, (item) => isNil(item) ? set(imgUrl, undefined) : downloadImage(item)) //Close dialog when clicking outside onClickOutside(dialog, onClose) </script> + +<template> + <div class=""> + <Dialog :open="isOpen" @close="onClose" class="relative z-50"> + <!-- The backdrop, rendered as a fixed sibling to the panel container --> + <div class="fixed inset-0 bg-black/30" aria-hidden="true" /> + + <!-- Full-screen container to center the panel --> + <div class="fixed inset-0 flex items-center justify-center w-screen p-4"> + <!-- The actual dialog panel --> + <DialogPanel class="p-2 bg-white rounded dark:bg-dark-700" ref="dialog"> + <DialogDescription> + <img class="preview-image" :src="imgUrl" alt="preview" /> + </DialogDescription> + <!-- ... --> + </DialogPanel> + </div> + </Dialog> + </div> +</template> <style lang="scss"> .preview-image { diff --git a/front-end/src/views/Blog/index.vue b/front-end/src/views/Blog/index.vue index de435ec..af6ab88 100644 --- a/front-end/src/views/Blog/index.vue +++ b/front-end/src/views/Blog/index.vue @@ -1,3 +1,35 @@ +<script setup lang="ts"> +import { computed } from 'vue'; +import { useRouteQuery } from '@vueuse/router'; +import { TabGroup, TabList, Tab, TabPanels, TabPanel, Switch } from '@headlessui/vue' +import { defer, first } from 'lodash-es'; +import { useStore, SortType } from '../../store'; +import Channels from './components/Channels.vue'; +import Posts from './components/Posts.vue'; +import Content from './components/Content.vue'; + +//Protect page +const store = useStore() +store.setPageTitle('Blog Admin') + +const firstLetter = computed(() => first(store.userName)) +const tabIdQ = useRouteQuery<string>('tabid', '', { mode: 'push' }) + +//Map queries to their respective computed values +const tabId = computed(() => tabIdQ.value ? parseInt(tabIdQ.value) : 0); +const lastModified = computed({ + get: () => store.queryState.sort === SortType.ModifiedTime, + set: (value: boolean) => { + store.queryState.sort = value ? SortType.ModifiedTime : SortType.CreatedTime + } +}) + +const onTabChange = (id: number) => tabIdQ.value = id.toString(10) + +//Load channels on page load +defer(() => store.channels.refresh()); + +</script> <template> <div class="container mx-auto mt-10 mb-[10rem]"> <div id="blog-admin-template" class=""> @@ -107,40 +139,6 @@ </div> </template> -<script setup lang="ts"> -import { computed } from 'vue'; -import { useRouteQuery } from '@vueuse/router'; -import { TabGroup, TabList, Tab, TabPanels, TabPanel, Switch } from '@headlessui/vue' -import { defer, first } from 'lodash-es'; -import { useStore, SortType } from '../../store'; -import Channels from './components/Channels.vue'; -import Posts from './components/Posts.vue'; -import Content from './components/Content.vue'; - - -//Protect page -const store = useStore() -store.setPageTitle('Blog Admin') - -const firstLetter = computed(() => first(store.userName)) -const tabIdQ = useRouteQuery<string>('tabid', '', { mode: 'push' }) - -//Map queries to their respective computed values -const tabId = computed(() => tabIdQ.value ? parseInt(tabIdQ.value) : 0); -const lastModified = computed({ - get :() => store.queryState.sort === SortType.ModifiedTime, - set: (value:boolean) => { - store.queryState.sort = value ? SortType.ModifiedTime : SortType.CreatedTime - } -}) - -const onTabChange = (id:number) => tabIdQ.value = id.toString(10) - -//Load channels on page load -defer(() => store.channels.refresh()); - -</script> - <style lang="scss"> #blog-admin-template{ |