diff options
author | vnugent <public@vaughnnugent.com> | 2024-06-07 15:45:56 -0400 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2024-06-07 15:45:56 -0400 |
commit | f77ff50150e6ff5d1f2b03c4f465846d5bb49a96 (patch) | |
tree | 1096bba241834211a25f7895db21e1a8d581ea17 /front-end/src/views/Blog/components | |
parent | f9e2109c27af5ece546261c018d4b2781860ff1c (diff) |
Squashed commit of the following:v0.1.5-alpha
commit 8ed4663e539d9c2ea58aaad02a1fc2896956f6b6
Author: vnugent <public@vaughnnugent.com>
Date: Fri Jun 7 15:43:48 2024 -0400
fix: invalid chars in status cookie name
commit 9d1df65d99732a68b4fe96dcc75273442cbd322f
Author: vnugent <public@vaughnnugent.com>
Date: Thu Jun 6 21:31:30 2024 -0400
fix: Some container fixes and compatability
commit 5ecd6b39cccdc9500540b10685605b5fcba61f69
Author: vnugent <public@vaughnnugent.com>
Date: Thu Jun 6 17:19:48 2024 -0400
Update and expose storage config for container
commit 3a62bafd210a2e00d23d3df773e47011e09eba6e
Author: vnugent <public@vaughnnugent.com>
Date: Thu Jun 6 16:18:36 2024 -0400
ci: build admin lib before building front-end
commit 35920ad6c8596fc14bcfed66303511e8c249be8d
Author: vnugent <public@vaughnnugent.com>
Date: Thu Jun 6 15:56:36 2024 -0400
ci: Local vite config, force set lib versions
commit 3c228b3cc5172fae398af8de72b64bd780ace20c
Author: vnugent <public@vaughnnugent.com>
Date: Wed Jun 5 19:55:39 2024 -0400
ci: Update packages and add container build
commit 21d2719701f851d4a555c363b141f289f14a5192
Author: vnugent <public@vaughnnugent.com>
Date: Wed Jun 5 15:58:07 2024 -0400
fix: #1 new channel page when hitting new button
commit eefba88ac4e2c70517aa71c79ed94c346f9de554
Author: vnugent <public@vaughnnugent.com>
Date: Wed Jun 5 15:26:15 2024 -0400
chore: Package updates
commit 9eed4022a79f2cba139c9f8a359bfc8c1f9c31c5
Author: vnugent <public@vaughnnugent.com>
Date: Wed Jun 5 14:44:08 2024 -0400
ci: Stage blocking changes
Diffstat (limited to 'front-end/src/views/Blog/components')
6 files changed, 209 insertions, 224 deletions
diff --git a/front-end/src/views/Blog/components/Channels.vue b/front-end/src/views/Blog/components/Channels.vue index df71720..8de6527 100644 --- a/front-end/src/views/Blog/components/Channels.vue +++ b/front-end/src/views/Blog/components/Channels.vue @@ -1,22 +1,4 @@ -<template> - <div id="channel-editor"> - <EditorTable title="Manage channels" :show-edit="showEdit" :pagination="pagination" @open-new="openNew"> - <template #table> - <ChannelTable - :items="items" - @open-edit="openEdit" - /> - </template> - <template #editor> - <ChannelEdit - @close="closeEdit" - @on-submit="onSubmit" - @on-delete="onDelete" - /> - </template> - </EditorTable> - </div> -</template> + <script setup lang="ts"> import { computed } from 'vue'; @@ -33,7 +15,7 @@ const emit = defineEmits(['close']) const store = useStore() const { items, pagination } = store.channels.createPages() -const showEdit = computed(() => !isEmpty(store.channels.editChannel)) +const showEdit = computed(() => !isEmpty(store.channels.editId)) const openEdit = (channel: BlogChannel) => store.channels.editId = channel.id; @@ -44,13 +26,13 @@ const closeEdit = (update?:boolean) => { store.channels.refresh() } //Reset page to top - window.scrollTo(0, 0) + window.scrollTo({ top: 0, behavior: 'smooth' }) } const openNew = () => { - store.channels.editId = 'new' + store.channels.editId = 'new' //Reset page to top - window.scrollTo(0, 0) + window.scrollTo({ top: 0, behavior: 'smooth' }) } const onSubmit = async ({channel, feed} : { channel:BlogChannel, feed? : ChannelFeed}) => { @@ -86,6 +68,15 @@ const onDelete = async (channel : BlogChannel) => { </script> -<style lang="scss"> - -</style>
\ No newline at end of file +<template> + <div id="channel-editor"> + <EditorTable title="Manage channels" :show-edit="showEdit" :pagination="pagination" @open-new="openNew"> + <template #table> + <ChannelTable :items="items" @open-edit="openEdit" /> + </template> + <template #editor> + <ChannelEdit @close="closeEdit" @on-submit="onSubmit" @on-delete="onDelete" /> + </template> + </EditorTable> + </div> +</template> diff --git a/front-end/src/views/Blog/components/Content.vue b/front-end/src/views/Blog/components/Content.vue index 5e81629..568f2d1 100644 --- a/front-end/src/views/Blog/components/Content.vue +++ b/front-end/src/views/Blog/components/Content.vue @@ -1,43 +1,3 @@ -<template> - <div id="content-editor" class=""> - <EditorTable title="Manage content" :show-edit="showEdit" :pagination="pagination" @open-new="openNew"> - <template #table> - <ContentTable - :items="items" - @open-edit="openEdit" - @copy-link="copyLink" - @delete="onDelete" - @download="onDownload" - /> - </template> - <template #editor> - <div v-if="showProgress" class="max-w-xl mx-auto"> - <span id="ProgressLabel" class="sr-only">Loading</span> - - <span - role="progressbar" - aria-labelledby="ProgressLabel" - :aria-valuenow="uploadProgress" - class="relative block bg-gray-200 rounded-full dark:bg-dark-500" - > - <span class="absolute inset-0 flex items-center justify-center text-[10px]/4"> - <span class="font-bold text-white "> {{ loadingProgress }} </span> - </span> - - <span class="block h-4 text-center rounded-full bg-primary-600" :style="progressWidth"></span> - </span> - </div> - <ContentEditor - @submit="onSubmit" - @close="closeEdit" - @delete="onDelete" - /> - </template> - </EditorTable> - <a class="hidden" ref="downloadAnchor"></a> - </div> -</template> - <script setup lang="ts"> import { computed, shallowRef } from 'vue'; import { isEmpty } from 'lodash-es'; @@ -50,7 +10,6 @@ import EditorTable from './EditorTable.vue'; import ContentEditor from './Content/ContentEditor.vue'; import ContentTable from './Content/ContentTable.vue'; - const store = useStore() const { uploadProgress } = storeToRefs(store) const { items, pagination } = store.content.createPages() @@ -63,7 +22,6 @@ const loadingProgress = computed(() => `${uploadProgress.value}%`); const progressWidth = computed(() => ({ width: `${uploadProgress.value}%` })); const showProgress = computed(() => uploadProgress.value > 0 && uploadProgress.value < 100); - const openEdit = async (item: ContentMeta) => store.content.selectedId = item.id const closeEdit = (update?: boolean) => { @@ -173,4 +131,44 @@ const onDownload = async (item: ContentMeta) => { }) } -</script>
\ No newline at end of file +</script> + +<template> + <div id="content-editor" class=""> + <EditorTable title="Manage content" :show-edit="showEdit" :pagination="pagination" @open-new="openNew"> + <template #table> + <ContentTable + :items="items" + @open-edit="openEdit" + @copy-link="copyLink" + @delete="onDelete" + @download="onDownload" + /> + </template> + <template #editor> + <div v-if="showProgress" class="max-w-xl mx-auto"> + <span id="ProgressLabel" class="sr-only">Loading</span> + + <span + role="progressbar" + aria-labelledby="ProgressLabel" + :aria-valuenow="uploadProgress" + class="relative block bg-gray-200 rounded-full dark:bg-dark-500" + > + <span class="absolute inset-0 flex items-center justify-center text-[10px]/4"> + <span class="font-bold text-white "> {{ loadingProgress }} </span> + </span> + + <span class="block h-4 text-center rounded-full bg-primary-600" :style="progressWidth"></span> + </span> + </div> + <ContentEditor + @submit="onSubmit" + @close="closeEdit" + @delete="onDelete" + /> + </template> + </EditorTable> + <a class="hidden" ref="downloadAnchor"></a> + </div> +</template>
\ No newline at end of file diff --git a/front-end/src/views/Blog/components/Content/ContentTable.vue b/front-end/src/views/Blog/components/Content/ContentTable.vue index 98a76a4..dab63bd 100644 --- a/front-end/src/views/Blog/components/Content/ContentTable.vue +++ b/front-end/src/views/Blog/components/Content/ContentTable.vue @@ -1,3 +1,48 @@ +<script setup lang="ts"> +import { defineAsyncComponent, ref } from 'vue'; +import { filter as _filter, defaultTo, includes, truncate } from 'lodash-es'; +import { useClipboard } from '@vueuse/core'; +import { useWait } from '@vnuge/vnlib.browser'; +import { ContentMeta } from '@vnuge/cmnext-admin'; +const ImgPreviewDialog = defineAsyncComponent(() => import('../image-preview-dialog.vue')) + +const emit = defineEmits(['open-edit', 'copy-link', 'delete', 'download']) +defineProps<{ items: ContentMeta[] }>() + +const { waiting } = useWait() +const { copy } = useClipboard() + +const previewItem = ref<ContentMeta | undefined>() + +const getDateString = (time?: number) => new Date((time || 0) * 1000).toLocaleString(); +const getItemLength = (item: ContentMeta) : string =>{ + const length = item.length || 0; + return length > 1024 ? `${(length / 1024).toFixed(2)} KB` : `${length} B` +} +const getItemId = (item: ContentMeta) => truncate(item.id || '', { length: 20 }) +const getItemName = (item : ContentMeta) => truncate(item.name || '', { length: 30 }) + +const getContentIconType = (item: ContentMeta) => { + const type = defaultTo(item.content_type, '') + if (includes(type, 'image')) return 'image' + if (includes(type, 'video')) return 'video' + if (includes(type, 'audio')) return 'headphones' + if (includes(type, 'html')) return 'code' + if (includes(type, 'zip')) return 'file-zipper' + return 'file' +} + +const isImage = (item: ContentMeta) => includes(item.content_type, 'image') +const openEdit = async (item: ContentMeta) => emit('open-edit', item) +const copyLink = (item : ContentMeta) => emit('copy-link', item) +const deleteItem = (item : ContentMeta) => emit('delete', item) +const download = (item : ContentMeta) => emit('download', item) + +const onShowPreview = (item: ContentMeta) => previewItem.value = item +const onClosePreview = () => previewItem.value = undefined + +</script> + <template> <thead> <tr> @@ -63,48 +108,3 @@ <!-- Image preview dialog --> <ImgPreviewDialog :item="previewItem" @close="onClosePreview()" /> </template> - -<script setup lang="ts"> -import { defineAsyncComponent, ref } from 'vue'; -import { filter as _filter, defaultTo, includes, truncate } from 'lodash-es'; -import { useClipboard } from '@vueuse/core'; -import { useWait } from '@vnuge/vnlib.browser'; -import { ContentMeta } from '@vnuge/cmnext-admin'; -const ImgPreviewDialog = defineAsyncComponent(() => import('../image-preview-dialog.vue')) - -const emit = defineEmits(['open-edit', 'copy-link', 'delete', 'download']) -defineProps<{ items: ContentMeta[] }>() - -const { waiting } = useWait() -const { copy } = useClipboard() - -const previewItem = ref<ContentMeta | undefined>() - -const getDateString = (time?: number) => new Date((time || 0) * 1000).toLocaleString(); -const getItemLength = (item: ContentMeta) : string =>{ - const length = item.length || 0; - return length > 1024 ? `${(length / 1024).toFixed(2)} KB` : `${length} B` -} -const getItemId = (item: ContentMeta) => truncate(item.id || '', { length: 20 }) -const getItemName = (item : ContentMeta) => truncate(item.name || '', { length: 30 }) - -const getContentIconType = (item: ContentMeta) => { - const type = defaultTo(item.content_type, '') - if (includes(type, 'image')) return 'image' - if (includes(type, 'video')) return 'video' - if (includes(type, 'audio')) return 'headphones' - if (includes(type, 'html')) return 'code' - if (includes(type, 'zip')) return 'file-zipper' - return 'file' -} - -const isImage = (item: ContentMeta) => includes(item.content_type, 'image') -const openEdit = async (item: ContentMeta) => emit('open-edit', item) -const copyLink = (item : ContentMeta) => emit('copy-link', item) -const deleteItem = (item : ContentMeta) => emit('delete', item) -const download = (item : ContentMeta) => emit('download', item) - -const onShowPreview = (item: ContentMeta) => previewItem.value = item -const onClosePreview = () => previewItem.value = undefined - -</script> diff --git a/front-end/src/views/Blog/components/ContentSearch.vue b/front-end/src/views/Blog/components/ContentSearch.vue index 7871196..0970bf1 100644 --- a/front-end/src/views/Blog/components/ContentSearch.vue +++ b/front-end/src/views/Blog/components/ContentSearch.vue @@ -1,39 +1,3 @@ -<template> - <div id="content-search" class="my-4"> - <div class=""> - <div class=""> - <input class="w-full input primary" placeholder="Search..." v-model="search" /> - </div> - </div> - <div class="search-results"> - <div v-if="searchResults.length == 0" class="result"> - No results found. - </div> - <div v-else v-for="result in searchResults" :key="result.id" @click.prevent="onSelected(result)" class="result"> - <div class="flex-auto result name"> - {{ result.shortName }} - </div> - <div class="result id"> - {{ result.shortId }} - </div> - <div class="rseult controls"> - <div v-if="waiting"> - <fa-icon icon="spinner" spin /> - </div> - <div v-else-if="result.copied.value" class="text-sm text-amber-500"> - copied - </div> - <div v-else class=""> - <button class="btn secondary sm borderless" @click="result.copyLink()"> - <fa-icon icon="link" /> - </button> - </div> - </div> - </div> - </div> - </div> -</template> - <script setup lang="ts"> import { useClipboard } from '@vueuse/core'; import { apiCall, useWait } from '@vnuge/vnlib.browser'; @@ -89,6 +53,42 @@ const onSelected = (result: ContentResult) => { </script> +<template> + <div id="content-search" class="my-4"> + <div class=""> + <div class=""> + <input class="w-full input primary" placeholder="Search..." v-model="search" /> + </div> + </div> + <div class="search-results"> + <div v-if="searchResults.length == 0" class="result"> + No results found. + </div> + <div v-else v-for="result in searchResults" :key="result.id" @click.prevent="onSelected(result)" class="result"> + <div class="flex-auto result name"> + {{ result.shortName }} + </div> + <div class="result id"> + {{ result.shortId }} + </div> + <div class="rseult controls"> + <div v-if="waiting"> + <fa-icon icon="spinner" spin /> + </div> + <div v-else-if="result.copied.value" class="text-sm text-amber-500"> + copied + </div> + <div v-else class=""> + <button class="btn secondary sm borderless" @click="result.copyLink()"> + <fa-icon icon="link" /> + </button> + </div> + </div> + </div> + </div> + </div> +</template> + <style lang="scss"> .search-results{ diff --git a/front-end/src/views/Blog/components/EditorTable.vue b/front-end/src/views/Blog/components/EditorTable.vue index 4ec5a33..a7f4f66 100644 --- a/front-end/src/views/Blog/components/EditorTable.vue +++ b/front-end/src/views/Blog/components/EditorTable.vue @@ -1,3 +1,25 @@ +<script setup lang="ts"> +import { toRefs } from 'vue'; +import { useWait } from '@vnuge/vnlib.browser'; +import { UseOffsetPaginationReturn } from '@vueuse/core'; + +const emit = defineEmits(['open-new']) +const props = defineProps<{ + title: string, + showEdit: boolean, + pagination: UseOffsetPaginationReturn +}>() + +const { showEdit } = toRefs(props) +const { waiting } = useWait() + +//Get pagination +const { pageCount, next, prev, isLastPage, isFirstPage, currentPage } = props.pagination + +const openNew = () => emit('open-new') + +</script> + <template> <slot class="flex flex-row"> <div class="flex-1 px-4 mt-3"> @@ -6,12 +28,12 @@ <div class="w-[20rem]"> <h4>{{ $props.title }}</h4> </div> - <div class="h-full"> - <div :class="{'opacity-100':waiting}" class="opacity-0"> + <div class="h-full"> + <div :class="{ 'opacity-100': waiting }" class="opacity-0"> <fa-icon icon="spinner" class="animate-spin" /> </div> </div> - <div class="mt-auto"> + <div class="mt-auto"> <div class="flex justify-center"> <nav aria-label="Pagination"> <ul class="inline-flex items-center space-x-1 text-sm rounded-md"> @@ -22,11 +44,11 @@ </li> <li> <span class="inline-flex items-center px-4 py-2 space-x-1"> - Page + Page <b class="mx-1"> {{ currentPage }} </b> - of + of <b class="ml-1"> {{ pageCount }} </b> @@ -41,16 +63,16 @@ </nav> </div> </div> - + <div class="h-fit"> - <button class="rounded btn primary sm" @click="openNew"> + <button class="rounded btn primary sm" id="new-btn" @click="openNew"> <fa-icon :icon="['fas', 'plus']" class="mr-2" /> New </button> </div> </div> <table class="edit-table"> - <slot name="table" /> + <slot name="table" /> </table> </div> <div v-else class=""> @@ -60,37 +82,10 @@ </slot> </template> -<script setup lang="ts"> -import { toRefs } from 'vue'; -import { useWait } from '@vnuge/vnlib.browser'; -import { UseOffsetPaginationReturn } from '@vueuse/core'; - -const emit = defineEmits(['open-new']) -const props = defineProps<{ - title: string, - showEdit: boolean, - pagination: UseOffsetPaginationReturn -}>() - -const { showEdit } = toRefs(props) - -const { waiting } = useWait() - -//Get pagination -const { pageCount, next, prev, isLastPage, isFirstPage, currentPage } = props.pagination - -const openNew = () => { - emit('open-new') -} - -</script> - <style lang="scss"> - -button.page-button{ +button.page-button { @apply inline-flex items-center px-2 py-1.5 space-x-2 font-medium; @apply text-gray-500 bg-white border border-gray-300 rounded-full hover:bg-gray-50; - @apply dark:border-dark-300 dark:bg-transparent dark:text-gray-300 hover:dark:bg-dark-700; + @apply dark:border-dark-300 dark:bg-transparent dark:text-gray-300 hover:dark:bg-dark-700; } - </style>
\ No newline at end of file diff --git a/front-end/src/views/Blog/components/FeedFields.vue b/front-end/src/views/Blog/components/FeedFields.vue index e38c3d7..2d725f9 100644 --- a/front-end/src/views/Blog/components/FeedFields.vue +++ b/front-end/src/views/Blog/components/FeedFields.vue @@ -1,40 +1,3 @@ -<template> - <div id="feed-custom-fields"> - <div class="my-3 text-center"> - <h4>Feed custom fields</h4> - </div> - - <div v-if="cleanXml" class="w-full max-w-2xl mx-auto"> - <pre class="xml"> -{{ cleanXml }} - </pre> - </div> - - - <div class="my-2 ml-auto w-fit"> - <div v-if="!editMode" class="button-group"> - <button class="btn" @click="edit">Edit</button> - </div> - <div v-else class="button-group"> - <button class="btn primary" @click="save" >Update</button> - <button class="btn" @click="cancel">Cancel</button> - </div> - </div> - - - <div v-if="editMode" class="flex flex-col"> - <div v-if="$props.showEpAdder" class="mb-2"> - <EpAdder @submit="onAddEnclosure" /> - </div> - - <div class=""> - <JsonEditorVue :ask-to-format="true" class="json" v-model="jsonFeedData"/> - </div> - </div> - - </div> -</template> - <script setup lang="ts"> import { computed, defineAsyncComponent, ref } from 'vue'; import { FeedProperty, UseXmlProperties } from '@vnuge/cmnext-admin'; @@ -100,6 +63,44 @@ const onAddEnclosure = (props: FeedProperty[]) =>{ </script> +<template> + <div id="feed-custom-fields"> + <div class="my-3 text-center"> + <h4>Feed custom fields</h4> + </div> + + <div v-if="cleanXml" class="w-full max-w-2xl mx-auto"> + <pre class="xml"> +{{ cleanXml }} + </pre> + </div> + + + <div class="my-2 ml-auto w-fit"> + <div v-if="!editMode" class="button-group"> + <button class="btn" @click="edit">Edit</button> + </div> + <div v-else class="button-group"> + <button class="btn primary" @click="save" >Update</button> + <button class="btn" @click="cancel">Cancel</button> + </div> + </div> + + + <div v-if="editMode" class="flex flex-col"> + <div v-if="$props.showEpAdder" class="mb-2"> + <EpAdder @submit="onAddEnclosure" /> + </div> + + <div class=""> + <JsonEditorVue :ask-to-format="true" class="json" v-model="jsonFeedData"/> + </div> + </div> + + </div> +</template> + + <style lang="scss"> #feed-custom-fields{ |