1
0
This commit is contained in:
Philip Wagner
2024-08-31 10:01:49 +02:00
commit 78b6c0d381
1169 changed files with 235103 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
<template>
<k-field :input="_uid" v-bind="$props" class="k-embed-field k-url-field k-field">
<div class="preview" v-if="hasMedia" :data-provider="providerName">
<div class="preview-content" v-html="media.code"></div>
<div class="preview-background"></div>
</div>
<k-input ref="input" :id="_uid" v-bind="$props" :value="inputValue" :media="media" theme="field" v-on="$listeners" @setMedia="setMedia" @startLoading="startLoading">
<div class="k-embed-infos" slot="icon">
<div class="k-embed-status">
<span v-if="loading" class="k-embed-status-loading"><span class="loader"></span></span>
<span v-else-if="hasMedia" class="k-embed-status-synced">{{ $t('embed.synced') }} <span class="checkmark"></span></span>
<span v-else-if="syncFailed" class="k-embed-status-failed">{{ $t('embed.failed') }} <span class="cross"></span></span>
</div>
<k-button v-if="link"
:icon="icon"
:link="inputValue"
:tooltip="$t('open')"
class="k-input-icon-button"
tabindex="-1"
target="_blank"
rel="noopener" />
</div>
</k-input>
</k-field>
</template>
<script>
import { isUrl, matchProvider } from '../helpers/validators.js'
export default {
extends: 'k-url-field',
data() {
return {
media: Object,
loading: false,
}
},
props: {
provider: String,
},
created() {
if(this.value && this.value.media && this.hasLength(this.value.media)) {
this.media = this.value.media
}
},
watch: {
inputValue() {
if(this.value && this.value.media && this.hasLength(this.value.media)) {
this.media = this.value.media
}
else {
this.media = {}
}
}
},
computed: {
hasMedia() {
return this.hasLength(this.media) && this.media.code
},
providerName() {
return this.hasMedia && this.media.providerName ? this.media.providerName.toLowerCase() : null
},
syncFailed() {
return this.inputValue != '' && this.isEmbeddableUrl(this.inputValue) && !this.hasMedia
},
inputValue() {
return this.value && this.value.input ? this.value.input : ''
}
},
methods: {
setMedia(media) {
this.media = media
this.stopLoading()
},
hasLength(obj) {
return Object.keys(obj).length
},
startLoading() {
this.loading = true
},
stopLoading() {
this.loading = false
},
isEmbeddableUrl(value) {
if(!isUrl(value)) return false
if(this.provider && !matchProvider(value, this.provider)) return false
return true
}
}
};
</script>
<style lang="scss">
@import '../assets/css/styles.scss'
</style>

View File

@@ -0,0 +1,88 @@
<script>
import { isUrl, matchProvider } from '../helpers/validators.js'
export default {
extends: 'k-url-input',
props: {
provider: String,
media: Object,
},
mounted() {
this.loadEmbedScripts()
},
methods: {
onInput(value) {
if(value == '' || !this.isEmbeddableUrl(value)) {
this.media = {}
this.emitInput(value)
return false;
}
if(value.includes('https://www.instagram.com')) {
value = value.split('?')[0].replace(/\/$/, "");
}
this.$emit('startLoading')
this.$api
.get('kirby-embed/get-data', { url: value })
.then(response => {
if(response['status'] == 'success' && response['data']) {
if(response['data']['providerName'] == 'Vimeo') {
let iframe = response['data']['code']
iframe = this.htmlToElement(iframe)
iframe.setAttribute('referrerpolicy', 'strict-origin-when-cross-origin')
response['data']['code'] = iframe.outerHTML
}
this.media = response['data']
}
else {
this.media = {}
}
this.emitInput(value)
})
.catch(error => {
this.media = {}
this.emitInput(value)
})
},
emitInput(value) {
this.$emit("input", { input: value, media: this.media });
this.$emit("setMedia", this.media)
this.loadEmbedScripts()
},
loadEmbedScripts() {
if (window.twttr) {
window.twttr.widgets.load();
}
else if (this.media && Object.keys(this.media).length && this.media.providerName.toLowerCase() == 'twitter') {
const embed = document.createElement('script');
embed.src = 'https://platform.twitter.com/widgets.js';
document.body.appendChild(embed);
}
if (window.instgrm) {
window.instgrm.Embeds.process();
}
else if (this.media && Object.keys(this.media).length && this.media.providerName.toLowerCase() == 'instagram') {
const embed = document.createElement('script');
embed.src = 'https://www.instagram.com/embed.js';
document.body.appendChild(embed);
}
},
isEmbeddableUrl(value) {
if(!isUrl(value)) return false
if(this.provider && !matchProvider(value, this.provider)) return false
return true
},
htmlToElement(html) {
let template = document.createElement('template')
html = html.trim()
template.innerHTML = html
return template.content.firstChild
}
},
};
</script>

View File

@@ -0,0 +1,53 @@
<template>
<div class="k-embed-field-preview">
<div class="k-embed-field-preview-inner k-bubble" data-has-text="true">
<div class="k-embed-icon k-frame">
<img :src="iconSrc">
</div>
<div class="k-embed-url">
{{ url }}
</div>
</div>
</div>
</template>
<script>
export default {
props: {
value: String,
field: Object
},
computed: {
url() {
return this.value.input.replace(/^\/\/|^.*?:\/\//, '')
},
isSynced() {
return Object.keys(this.value.media).length && this.value.media.code !== null
},
iconSrc() {
return this.$panel.$urls.site +'/media/plugins/sylvainjule/embed/svg/'+ this.providerIcon;
},
providerIcon() {
if(this.isSynced) {
if(this.field.icons) {
let provider = this.value.media.providerName
let icons = ['Vimeo', 'Flickr', 'Instagram', 'SoundCloud', 'Spotify', 'Twitter', 'YouTube'];
if(icons.includes(provider)) {
return 'embed-icon-'+ provider.toLowerCase() +'.svg'
}
else {
return 'embed-icon-synced.svg';
}
}
else {
return 'embed-icon-synced.svg'
}
}
else {
return 'embed-icon-failed.svg'
}
}
},
};
</script>