198 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			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>
 |