diff options
Diffstat (limited to 'front-end/src')
5 files changed, 87 insertions, 27 deletions
diff --git a/front-end/src/views/Blog/ckeditor/Editor.vue b/front-end/src/views/Blog/ckeditor/Editor.vue index 3cd9a8c..4fc534b 100644 --- a/front-end/src/views/Blog/ckeditor/Editor.vue +++ b/front-end/src/views/Blog/ckeditor/Editor.vue @@ -1,7 +1,21 @@ <template> <div class="pt-6"> <div class="flex justify-end w-full gap-2 my-2"> - <div class="w-fit"> + <div class="w-fit"> + <div class="flex flex-row py-2 mr-auto"> + <Switch v-model="podcastMode" + :class="$props.podcastMode ? 'bg-primary-500' : 'bg-gray-300 dark:bg-dark-500'" + class="relative inline-flex items-center w-10 h-5 my-auto duration-75 rounded-full"> + <span class="sr-only">Podcast Mode</span> + <span :class="$props.podcastMode ? 'translate-x-6' : 'translate-x-1'" + class="inline-block w-3 h-3 transition transform bg-white rounded-full" /> + </Switch> + <div class="my-auto ml-3"> + Podcast Mode + </div> + </div> + </div> + <div class="w-fit"> <Popover class="relative"> <PopoverButton class="btn"> Add @@ -56,11 +70,11 @@ <script setup lang="ts"> import { debounce, defer } from 'lodash-es'; -import { ref } from 'vue'; +import { computed, ref, toRefs } from 'vue'; import { useSessionStorage } from '@vueuse/core'; import { tryOnMounted } from '@vueuse/shared'; import { apiCall } from '@vnuge/vnlib.browser'; -import { Popover, PopoverButton, PopoverPanel } from '@headlessui/vue' +import { Popover, PopoverButton, PopoverPanel, Switch } from '@headlessui/vue' import { BlogState } from '../blog-api' import { Converter } from 'showdown' @@ -68,18 +82,24 @@ import { Converter } from 'showdown' import { config } from './build.ts' import ContentSearch from '../components/ContentSearch.vue'; -const emit = defineEmits(['change', 'load']) +const emit = defineEmits(['change', 'load', 'mode-change']) -defineProps<{ - blog: BlogState +const props = defineProps<{ + blog: BlogState, + podcastMode: boolean }>() let editor = {} +const propRefs = toRefs(props) //Init new shodown converter const showdownConverter = new Converter() const mdBuffer = ref('') const editorFrame = ref(null) const crashBuffer = useSessionStorage('post-crash', '') +const podcastMode = computed({ + get: () => propRefs.podcastMode.value, + set: (v) => emit('mode-change', v) +}) const recoverFromCrash = () => { //Set editor content from crash buffer diff --git a/front-end/src/views/Blog/components/ContentSearch.vue b/front-end/src/views/Blog/components/ContentSearch.vue index 03cb432..78cfa1a 100644 --- a/front-end/src/views/Blog/components/ContentSearch.vue +++ b/front-end/src/views/Blog/components/ContentSearch.vue @@ -79,8 +79,8 @@ const searchResults = computed<ContentResult[]>(() => { return { ...content, //truncate the id and name for display - shortId: truncate(content.id, { length: 15 }), - shortName: truncate(content.name, { length: 24 }), + shortId: truncate(content.id, { length: 18 }), + shortName: truncate(content.name, { length: 36 }), copyLink: () => copyLink(content, copy), copied } @@ -110,6 +110,10 @@ const onSelected = (result: ContentResult) => { .controls{ @apply min-w-[4rem] text-center; } + + &.name{ + @apply text-sm; + } } </style>
\ No newline at end of file diff --git a/front-end/src/views/Blog/components/Posts/PostEdit.vue b/front-end/src/views/Blog/components/Posts/PostEdit.vue index e55deee..6ea0bac 100644 --- a/front-end/src/views/Blog/components/Posts/PostEdit.vue +++ b/front-end/src/views/Blog/components/Posts/PostEdit.vue @@ -9,9 +9,6 @@ </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"> @@ -28,7 +25,7 @@ /> <div id="post-content-editor" class="px-6" :class="{'invalid':v$.content.$invalid}"> - <Editor @change="onContentChanged" :blog="$props.blog" @load="onEditorLoad" /> + <Editor :podcast-mode="podcastMode" :blog="$props.blog" @change="onContentChanged" @mode-change="onModeChange" @load="onEditorLoad" /> </div> <FeedFields :properties="postProperties" :blog="$props.blog" /> @@ -44,7 +41,7 @@ </div> </template> <script setup lang="ts"> -import { computed } from 'vue'; +import { computed, ref } from 'vue'; import { BlogState } from '../../blog-api'; import { reactiveComputed } from '@vueuse/core'; import { isNil, isString, split } from 'lodash-es'; @@ -64,6 +61,7 @@ const { getProfile } = useUser(); const { schema, getValidator } = getPostForm(); const { posts, content } = props.blog; +const podcastMode = ref(false) const isNew = computed(() => isNil(posts.selectedItem.value)); @@ -98,6 +96,14 @@ const onSubmit = async () =>{ //Remove the content from the post object delete post.content; + //Store the post content on the html descrption if in podcast mode + if(podcastMode.value){ + post.html_description = v$.value.content.$model; + } + else{ + delete post.html_description; + } + //Convert the tags string to an array of strings post.tags = isString(post.tags) ? split(post.tags, ',') : post.tags; @@ -136,6 +142,10 @@ const setMeAsAuthor = () => { }) } +const onModeChange = (e: boolean) => { + podcastMode.value = e; +} + const onEditorLoad = async (editor : any) =>{ //Get the initial content @@ -146,6 +156,12 @@ const onEditorLoad = async (editor : any) =>{ onContentChanged(postContent); editor.setData(postContent); } + + //If the post has an html description, set podcast mode + if(postBuffer.html_description){ + //Set podcast mode to true + podcastMode.value = true; + } } </script> diff --git a/front-end/src/views/Blog/components/podcast-helpers/EpisodeAdder.vue b/front-end/src/views/Blog/components/podcast-helpers/EpisodeAdder.vue index d4adb6f..6d1e473 100644 --- a/front-end/src/views/Blog/components/podcast-helpers/EpisodeAdder.vue +++ b/front-end/src/views/Blog/components/podcast-helpers/EpisodeAdder.vue @@ -13,12 +13,26 @@ <div class="fixed inset-0 flex justify-center pt-[8rem]"> <DialogPanel class="dialog"> <div class=""> - <DialogTitle>Set feed enclosure</DialogTitle> - <DialogDescription> + <DialogTitle class="text-2xl font-bold">Add Media Enclosure</DialogTitle> + <DialogDescription class="text-xs"> You may set a podcast episode or other rss enclosure from content stored in the cms. </DialogDescription> - <div class="my-3 ml-auto w-fit"> + <div class="flex flex-row gap-3 my-3 ml-auto w-fit"> + <div class="flex flex-row gap-2 my-auto"> + <div class="text-sm"> + Explicit + </div> + <div class=""> + <Switch v-model="isExplicit" + :class="isExplicit ? 'bg-red-500' : 'bg-gray-300 dark:bg-dark-500'" + class="relative inline-flex items-center w-10 h-5 my-auto duration-75 rounded-full"> + <span class="sr-only">Podcast Mode</span> + <span :class="isExplicit ? 'translate-x-6' : 'translate-x-1'" + class="inline-block w-3 h-3 transition transform bg-white rounded-full" /> + </Switch> + </div> + </div> <Popover class="relative"> <PopoverButton class="btn"> Add media @@ -57,7 +71,7 @@ </template> <script setup lang="ts"> -import { ref, reactive } from 'vue'; +import { ref, reactive, computed } from 'vue'; import { BlogState } from '../../blog-api'; import { PodcastEntity, getPodcastForm } from './podcast-form' import { @@ -68,6 +82,7 @@ import { PopoverButton, PopoverPanel, Popover, + Switch } from '@headlessui/vue' import ContentSearch from '../ContentSearch.vue' import { apiCall, debugLog } from '@vnuge/vnlib.browser'; @@ -87,6 +102,11 @@ const buffer = reactive<PodcastEntity>({} as PodcastEntity) const { v$, validate } = getValidator(buffer) +const isExplicit = computed({ + get : () => buffer.explicit, + set : (v: boolean) => buffer.explicit = v +}); + const setIsOpen = (value: boolean) => isOpen.value = value const onFormSubmit = async () =>{ @@ -102,15 +122,13 @@ const onFormSubmit = async () =>{ setIsOpen(false) } -const onCancel = () =>{ - setIsOpen(false) -} +const onCancel = () => setIsOpen(false) const onContentSelected = (content: ContentMeta) =>{ apiCall(async () =>{ //Get the content link from the server const url = await getPublicUrl(content) - + //set the form content setEnclosureContent(buffer, content, `/${url}`) }) @@ -147,7 +165,7 @@ const onContentSelected = (content: ContentMeta) =>{ @apply py-1.5 bg-transparent; &:disabled{ - @apply bg-gray-100 dark:bg-transparent dark:border-transparent; + @apply bg-gray-100 py-0.5 bg-transparent disabled:text-sm disabled:border-0 dark:text-gray-400 text-black; } &:focus{ diff --git a/front-end/src/views/Blog/components/podcast-helpers/podcast-form.ts b/front-end/src/views/Blog/components/podcast-helpers/podcast-form.ts index ab8ad8a..56b898c 100644 --- a/front-end/src/views/Blog/components/podcast-helpers/podcast-form.ts +++ b/front-end/src/views/Blog/components/podcast-helpers/podcast-form.ts @@ -25,6 +25,7 @@ export interface EnclosureEntity{ contentUrl: string; contentLength: number; contentType: string; + explicit: boolean; } export interface PodcastEntity extends EnclosureEntity{ @@ -58,7 +59,6 @@ export const getPodcastForm = (editMode?: Ref<boolean>) => { label: 'File Id', name: 'fileId', placeholder: '', - description: 'The file id of the episode already in the channel', disabled: true, }, { @@ -67,7 +67,6 @@ export const getPodcastForm = (editMode?: Ref<boolean>) => { label: 'Content url', name: 'contentUrl', placeholder: '', - description: 'This the relative url to the episode content file', disabled: true, }, { @@ -76,16 +75,14 @@ export const getPodcastForm = (editMode?: Ref<boolean>) => { label: 'Content length', name: 'contentLength', placeholder: '', - description: 'This the length in bytes of the episode content file', disabled: true, }, { id: 'content-type', type: 'text', - label: 'The MIME content type', + label: 'MIME content type', name: 'contentType', placeholder: '', - description: 'The MIME content type for the episode content file', disabled: true, } ] @@ -159,6 +156,11 @@ export const getPodcastForm = (editMode?: Ref<boolean>) => { length: podcast.contentLength?.toString(), type: podcast.contentType }, + }, + { + name: 'explicit', + namespace: 'itunes', + value: podcast.explicit ? 'true' : 'false' } ] } |