238 lines
4.6 KiB
Vue
Executable File
238 lines
4.6 KiB
Vue
Executable File
<template>
|
|
<iframe
|
|
v-if="campaign?.banner?.type === 'html'"
|
|
ref="iframe"
|
|
:width="campaign.banner.width"
|
|
:height="campaign.banner.height"
|
|
:src="getSource(campaign)"
|
|
scrolling="none"
|
|
marginwidth="0"
|
|
marginheight="0"
|
|
class="campaign frame"
|
|
data-umami-event="campaign-click"
|
|
:data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`"
|
|
/>
|
|
|
|
<a
|
|
v-else-if="campaign"
|
|
:href="campaign.url || campaign.affiliate?.url"
|
|
target="_blank"
|
|
class="campaign"
|
|
data-umami-event="campaign-click"
|
|
:data-umami-event-campaign-id="`${campaign.entity.slug}-${campaign.id}`"
|
|
>
|
|
<img
|
|
:src="getSource(campaign)"
|
|
:width="campaign.banner.width"
|
|
:height="campaign.banner.height"
|
|
class="campaign-banner"
|
|
>
|
|
</a>
|
|
</template>
|
|
|
|
<script>
|
|
function ratioFilter(banner) {
|
|
if (!banner) {
|
|
return false;
|
|
}
|
|
|
|
if (this.minHeight && banner.height < this.minHeight) {
|
|
return false;
|
|
}
|
|
|
|
if (this.maxHeight && banner.height > this.minHeight) {
|
|
return false;
|
|
}
|
|
|
|
if (banner.type === 'html' && banner.width > window.innerWidth) {
|
|
// usually non-scalable iframes
|
|
return false;
|
|
}
|
|
|
|
if (this.minRatio && banner.ratio < this.minRatio) {
|
|
return false;
|
|
}
|
|
|
|
if (this.maxRatio && banner.ratio > this.maxRatio) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function getSource(campaign) {
|
|
if (campaign.banner.entity.type === 'network' || !campaign.banner.entity.parent) {
|
|
return `/banners/${campaign.banner.entity.slug}/${campaign.banner.id}.${campaign.banner.type || 'jpg'}`;
|
|
}
|
|
|
|
if (campaign.banner.entity.type === 'channel' && campaign.banner.entity.parent?.type === 'network') {
|
|
return `/banners/${campaign.banner.entity.parent.slug}/${campaign.banner.entity.slug}/${campaign.banner.id}.${campaign.banner.type || 'jpg'}`;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function entityCampaign() {
|
|
const bannerCampaigns = this.entity.campaigns
|
|
.concat(this.entity.children?.flatMap((child) => child.campaigns))
|
|
.concat(this.entity.parent?.campaigns)
|
|
.filter((campaignX) => campaignX && this.ratioFilter(campaignX.banner));
|
|
|
|
if (bannerCampaigns.length > 0) {
|
|
const randomCampaign = bannerCampaigns[Math.floor(Math.random() * bannerCampaigns.length)];
|
|
|
|
this.campaign = randomCampaign;
|
|
this.$emit('campaign', randomCampaign);
|
|
|
|
return randomCampaign;
|
|
}
|
|
|
|
if (this.allowGeneric) {
|
|
return this.genericCampaign();
|
|
}
|
|
|
|
this.$emit('campaign', null);
|
|
|
|
return null;
|
|
}
|
|
|
|
function tagCampaign() {
|
|
const campaignBanners = this.tag.banners.filter((banner) => banner.campaigns.length > 0 && this.ratioFilter(banner));
|
|
const banner = campaignBanners[Math.floor(Math.random() * campaignBanners.length)];
|
|
|
|
if (banner?.campaigns.length > 0) {
|
|
const randomCampaign = {
|
|
...banner.campaigns[Math.floor(Math.random() * banner.campaigns.length)],
|
|
banner,
|
|
};
|
|
|
|
this.campaign = randomCampaign;
|
|
this.$emit('campaign', randomCampaign);
|
|
|
|
return randomCampaign;
|
|
}
|
|
|
|
if (this.allowGeneric) {
|
|
return this.genericCampaign();
|
|
}
|
|
|
|
this.$emit('campaign', null);
|
|
|
|
return null;
|
|
}
|
|
|
|
async function genericCampaign() {
|
|
const randomCampaign = await this.$store.dispatch('fetchRandomCampaign', { minRatio: this.minRatio, maxRatio: this.maxRatio });
|
|
|
|
this.campaign = randomCampaign;
|
|
this.$emit('campaign', randomCampaign);
|
|
|
|
return randomCampaign;
|
|
}
|
|
|
|
async function specificCampaign(campaignId) {
|
|
const campaign = await this.$store.dispatch('fetchCampaign', campaignId);
|
|
|
|
this.campaign = campaign;
|
|
this.$emit('campaign', campaign);
|
|
|
|
return campaign;
|
|
}
|
|
|
|
async function mounted() {
|
|
if (this.$route.query.campaign) {
|
|
await this.specificCampaign(this.$route.query.campaign);
|
|
return;
|
|
}
|
|
|
|
if (this.entity) {
|
|
await this.entityCampaign();
|
|
return;
|
|
}
|
|
|
|
if (this.tag) {
|
|
await this.tagCampaign();
|
|
return;
|
|
}
|
|
|
|
await this.genericCampaign();
|
|
}
|
|
|
|
export default {
|
|
props: {
|
|
entity: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
tag: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
minHeight: {
|
|
type: Number,
|
|
default: null,
|
|
},
|
|
maxHeight: {
|
|
type: Number,
|
|
default: null,
|
|
},
|
|
minRatio: {
|
|
type: Number,
|
|
default: null,
|
|
},
|
|
allowGeneric: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
maxRatio: {
|
|
type: Number,
|
|
default: null,
|
|
},
|
|
},
|
|
emits: ['campaign'],
|
|
data() {
|
|
return {
|
|
campaign: null,
|
|
};
|
|
},
|
|
mounted,
|
|
methods: {
|
|
entityCampaign,
|
|
genericCampaign,
|
|
getSource,
|
|
ratioFilter,
|
|
specificCampaign,
|
|
tagCampaign,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.campaign {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border: none;
|
|
}
|
|
|
|
.campaign-banner {
|
|
height: auto;
|
|
width: auto;
|
|
max-height: 100%;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.frame-container {
|
|
position: relative;
|
|
font-size: 0;
|
|
}
|
|
|
|
.frame-target {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
}
|
|
</style>
|