aboutsummaryrefslogtreecommitdiff
path: root/front-end/src/views/Blog/components/podcast-helpers/EpisodeAdder.vue
blob: 79b21cf98b9c9fb4de59fc26773d2ada29e81aab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<template>
    <div id="podcast-upload-form">

        <div class="ml-auto w-fit">
            <div class="">
                <button class="btn sm" @click="setIsOpen(true)">Add enclosure</button>
            </div>
        </div>

        <Dialog id="enclosure-dialog" :open="isOpen" @close="setIsOpen" class="relative z-50">
            <div class="fixed inset-0 bg-black/30" aria-hidden="true" />

            <div class="fixed inset-0 flex justify-center pt-[8rem]">
                <DialogPanel class="dialog">
                    <div class="">
                        <DialogTitle>Set feed enclosure</DialogTitle>
                        <DialogDescription>
                            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">
                            <Popover class="relative">
                                <PopoverButton class="btn">
                                    Add media
                                    <fa-icon class="ml-2" icon="photo-film" />
                                </PopoverButton>
                                <PopoverPanel class="absolute right-0 z-10 top-10">
                                    <div class="md-pannel">
                                        <div class="">
                                            Search for content by its id or file name.
                                        </div>
                                        <ContentSearch :blog="$props.blog" @selected="onContentSelected"/>
                                    </div>
                                </PopoverPanel>
                            </Popover>
                        </div>
                        <dynamic-form
                            class=""
                            id="enclosure-form"
                            :form="schema"
                            :validator="v$"
                            @submit="onFormSubmit"
                            @cancel="onCancel"
                        />
                        <div class="mt-4 ml-auto w-fit">
                            <div class="button-group">
                                <button class="btn sm primary" @click="onFormSubmit">Submit</button>
                                <button class="btn sm" @click="onCancel">Cancel</button>
                            </div>
                        </div>
                    </div>
                </DialogPanel>
            </div>
        </Dialog>
    </div>
</template>
<script setup lang="ts">

import { ref, reactive } from 'vue';
import { BlogState } from '../../blog-api';
import { PodcastEntity, getPodcastForm } from './podcast-form'
import {
    Dialog,
    DialogPanel,
    DialogTitle,
    DialogDescription,
    PopoverButton,
    PopoverPanel,
    Popover,
} from '@headlessui/vue'
import ContentSearch from '../ContentSearch.vue'
import { apiCall, debugLog } from '@vnuge/vnlib.browser';
import { ContentMeta } from '@vnuge/cmnext-admin';

const emit = defineEmits(['submit'])

const props = defineProps<{
    blog: BlogState,
}>()

const isOpen = ref(false)
const { getPublicUrl } = props.blog.content;
const { schema, setEnclosureContent, getValidator, exportProperties } = getPodcastForm()

const buffer = reactive<PodcastEntity>({} as PodcastEntity)

const { v$, validate } = getValidator(buffer)

const setIsOpen = (value: boolean) => isOpen.value = value

const onFormSubmit = async () =>{
    //Validate the form
    if(! await validate()){
        return
    }

    //get the enclosure properties to add to the xml
    const props = exportProperties(buffer)
    debugLog(props);
    emit('submit', props)
    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}`)
    })
}

</script>

<style lang="scss">

#enclosure-dialog{

    .dialog{
        @apply w-full max-w-3xl px-8 pb-8 pt-4 mx-auto mb-auto border rounded shadow-md;
        @apply bg-white dark:bg-dark-700 dark:text-gray-300 dark:border-dark-500;
    }
    
    .dynamic-form.input-group{
        @apply grid grid-cols-2 gap-4;
    }

    .dynamic-form.input-container{
        @apply flex flex-col;
    }

    .dynamic-form.field-description{
        @apply text-sm text-gray-500 dark:text-gray-400 px-2;
    }

    .dynamic-form.input-label{
        @apply text-sm font-semibold text-gray-700 dark:text-gray-100 ml-1 mb-1;
    }

    .dynamic-form.dynamic-input.input{
        @apply py-1.5 bg-transparent;

        &:disabled{
            @apply bg-gray-100 dark:bg-transparent dark:border-transparent;
        }

        &:focus{
            @apply border-primary-500;
        }
    }

    .dirty.dynamic-form.input-container{
        &.data-invalid .dynamic-form.dynamic-input.input{
            @apply border-red-500;
        }
    }
}

</style>