fchat-rising/chat/ads/AdLauncher.vue

198 lines
5.4 KiB
Vue

<template>
<modal action="Post Ads" @submit="submit" ref="dialog" @open="load" dialogClass="w-100" class="adLauncher" :buttonText="'Start Posting Ads'">
<div v-if="hasAds()">
<h4>Ad Tags</h4>
<div class="form-group">
<p>Serve ads that match any one of these tags:</p>
<label class="control-label" :for="`adr-tag-${index}`" v-for="(tag,index) in tags">
<input type="checkbox" v-model="tag.value" :id="`adr-tag-${index}`" />
{{ tag.title }}
</label>
</div>
<h4>Target Channels</h4>
<div class="form-group">
<p>Serve ads on these channels:</p>
<label class="control-label" :for="`adr-channel-${index}`" v-for="(channel,index) in channels">
<input type="checkbox" v-model="channel.value" :id="`adr-channel-${index}`" />
{{ channel.title }}
</label>
</div>
<h4>Post Order</h4>
<div class="form-group">
<label class="control-label" for="adOrderRandom">
<input type="radio" v-model="adOrder" value="random" id="adOrderRandom" />
Random order
</label>
<label class="control-label" for="adOrderAdCenter">
<input type="radio" v-model="adOrder" value="ad-center" id="adOrderAdCenter" />
Follow order in Ad Center
</label>
</div>
<h4>Campaign</h4>
<div class="form-group">
<label class="control-label" for="timeoutMinutes">
Timeout
</label>
<select class="form-control" v-model="timeoutMinutes" id="timeoutMinutes">
<option v-for="timeout in timeoutOptions" :value="timeout.value">{{timeout.title}}</option>
</select>
</div>
<p class="matches">
<b>{{matchCount}}</b> ads will be used.
</p>
</div>
<div v-else>
<h4>No Ads to Post!</h4>
<p>Use the <button class="btn btn-outline-secondary" @click="openAdEditor()">Ad Editor</button> to create some ads first, then return here to post them.</p>
</div>
</modal>
</template>
<script lang="ts">
import {Component, Watch} from '@f-list/vue-ts';
import CustomDialog from '../../components/custom_dialog';
import Modal from '../../components/Modal.vue';
import core from '../core';
import _ from 'lodash';
import AdCenterDialog from './AdCenter.vue';
@Component({
components: {modal: Modal}
})
export default class AdLauncherDialog extends CustomDialog {
adOrder: 'random' | 'ad-center' = 'random';
matchCount = 0;
timeoutMinutes = 180;
tags: { value: boolean, title: string }[] = [];
channels: { value: boolean, title: string, id: string }[] = [];
timeoutOptions = [
{ value: 30, title: '30 minutes' },
{ value: 60, title: '1 hour' },
{ value: 120, title: '2 hours' },
{ value: 180, title: '3 hours' }
]
load() {
this.channels = _.map(_.filter(core.channels.joinedChannels, (c) => (c.mode === 'ads' || c.mode === 'both')),
(c) => ({ value: false, title: c.name, id: c.id }));
this.tags = _.map(core.adCenter.getActiveTags(), (t) => ({ value: false, title: t }));
this.checkCanSubmit();
}
hasAds(): boolean {
return core.adCenter.getActiveAds().length > 0;
}
@Watch('tags', { deep: true })
updateTags(): void {
this.matchCount = core.adCenter.getMatchingAds(this.getWantedTags()).length;
this.checkCanSubmit();
}
@Watch('channels', { deep: true })
updateChannels(): void {
this.checkCanSubmit();
}
checkCanSubmit() {
const channelCount = _.filter(this.channels, (channel) => channel.value).length;
const tagCount = _.filter(this.tags, (tag) => tag.value).length;
this.dialog.forceDisabled(tagCount === 0 || channelCount === 0);
}
getWantedTags(): string[] {
return _.map(_.filter(this.tags, (t) => t.value), (t) => t.title);
}
getWantedChannels(): string[] {
return _.map(_.filter(this.channels, (t) => t.value), (t) => t.id);
}
openAdEditor(): void {
this.hide();
(<AdCenterDialog>this.$parent.$refs['adCenter']).show();
}
submit(e: Event) {
const tags = this.getWantedTags();
const channelIds = this.getWantedChannels();
if (tags.length === 0) {
e.preventDefault();
alert('Select at least one tag to post');
return;
}
if (channelIds.length === 0) {
e.preventDefault();
alert('Select at least one channel to post in');
return;
}
if (!_.every(channelIds, (channelId) => {
if (core.adCenter.isSafeToOverride(channelId)) {
return true;
}
const chan = core.channels.getChannel(channelId);
if (!chan) {
return true;
}
return confirm(`Warning: This action will overwrite ads on channel ${chan.name}. Ads that are not stored in the Ad Center will be lost. Are you sure you wish to continue?`);
})) {
e.preventDefault();
return;
}
core.adCenter.schedule(
tags,
channelIds,
this.adOrder,
this.timeoutMinutes
);
this.hide();
}
}
</script>
<style lang="scss">
.adLauncher {
label {
display: block;
margin-left: 0.75rem;
color: var(--gray-dark);
}
select {
margin-left: 0.75rem;
width: auto;
padding-right: 1.5rem;
}
.matches {
margin: 0;
margin-top: 2rem;
color: var(--gray);
}
}
</style>