traxxx/assets/components/campaigns/campaign.vue

221 lines
4.3 KiB
Vue
Executable File

<template>
<iframe
v-if="campaign?.banner?.type === 'html'"
:width="campaign.banner.width"
:height="campaign.banner.height"
:src="getSource(campaign)"
scrolling="none"
marginwidth="0"
marginheight="0"
class="campaign frame"
/>
<a
v-else-if="campaign"
:href="campaign.url || campaign.affiliate?.url"
target="_blank"
class="campaign"
>
<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
console.log('TOO WIDE');
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%;
}
</style>